if ! $(gPYTHON_INCLUDED)
{
gPYTHON_INCLUDED = true ;
    
# Do some OS-specific setup
if $(NT)
{
    CATENATE = type ;
    PYTHON_VERSION ?= 2.1 ;
}
else if $(UNIX)
{
    CATENATE = cat ;
    PYTHON_VERSION ?= 1.5 ;
}

# Strip the dot from the Python version in order to be able to name
# libraries
PYTHON_VERSION_NODOT
 = [ SUBST $(PYTHON_VERSION) ([0-9]*)\.([0-9]*) $1$2 ]
      ;

local RUN_PATH = $(RUN_PATH) ;

gcc-compilers = gcc gcc-stlport ;

if $(NT)
{
    PYTHON_ROOT ?= c:/tools/python ;
    
    # Reconstitute any paths split due to embedded spaces.
    PYTHON_ROOT = $(PYTHON_ROOT:J=" ") ;
    
    PYTHON_LIB_PATH ?= $(PYTHON_ROOT)/libs $(PYTHON_ROOT)/PCBuild ;
    PYTHON_STDLIB_PATH ?= $(PYTHON_ROOT)/Lib ;

    # Locate Python libraries. In the case of MSVC the libraries are
    # found implicitly, and GCC/MINGW will use -lpython<version> to
    # find it, but other compilers may need an explicit pointer on the
    # command line.
    PYTHON_LIB ?= <python-library@>python$(PYTHON_VERSION_NODOT).lib ;
    SEARCH on $(PYTHON_LIB) = $(PYTHON_LIB_PATH) ;

    PYTHON_D_LIB ?= <python-library@>python$(PYTHON_VERSION_NODOT)_d.lib ;
    SEARCH on $(PYTHON_D_LIB) = $(PYTHON_LIB_PATH) ;

    # common properties required for compiling any Python module.
    PYTHON_PROPERTIES ?=
      select-python-includes
      <runtime-link>dynamic
      <include>$(BOOST_ROOT)
      <$(gcc-compilers)><*><define>USE_DL_IMPORT
      <$(gcc-compilers)><*><find-library>python$(PYTHON_VERSION).dll 
      ;
    
    GCC_PYTHON_ROOT ?= $(CYGWIN_ROOT)/usr/local ;
    GCC_PYTHON_ROOT ?= /usr/local ;
    
    GCC_PYTHON_DEBUG_ROOT ?= $(CYGWIN_ROOT)/usr/local/pydebug ;
    GCC_PYTHON_DEBUG_ROOT ?= /usr/local/pydebug ;
}
else if $(UNIX)
{
    PYTHON_VERSION ?= 1.5 ;
    PYTHON_ROOT ?= /usr/local ;
    PYTHON_ROOT = $(PYTHON_ROOT:J=" ") ;
    PYTHON_INCLUDES ?= $(PYTHON_ROOT)/include/python$(PYTHON_VERSION) ;
    PYTHON_LIB_PATH ?= $(PYTHON_ROOT)/lib/python$(PYTHON_VERSION)/config ;
    PYTHON_STDLIB_PATH ?= $(PYTHON_ROOT)/lib/python$(PYTHON_VERSION) ;

    PYTHON_PROPERTIES ?=
      <include>$(PYTHON_INCLUDES)
        <library-path>$(PYTHON_LIB_PATH)
      ;
    
    if $(OS) = OSF
    {
        PYTHON_PROPERTIES += <*><*><linkflags>"-expect_unresolved 'Py*' -expect_unresolved '_Py*'" ;
    }
}

# Locate the python executable
PYTHON ?= <executable@>python$(SUFEXE) ;
SEARCH on $(PYTHON) = $(PYTHON_ROOT)  $(PYTHON_ROOT)/bin $(PYTHON_ROOT)/PCBuild $(RUN_PATH) ;

# And the debugging version
PYTHON_D ?= $(PYTHON:S=)_d$(PYTHON:S) ;
SEARCH on $(PYTHON_D) = $(PYTHON_ROOT) $(PYTHON_ROOT)/bin $(PYTHON_ROOT)/PCBuild $(RUN_PATH) ;

# select-python-library
#
# Ungristed elements of a requirements list are treated as the rule
# names to be called to transform the property set. This is used when
# the requirements are too complicated to express otherwise.  This
# rule selects the right python library when building on Windows.
rule select-python-library ( toolset variant : properties * )
{
    if $(NT) 
    {
        if $(toolset) = mingw
        {
            local lib = python$(PYTHON_VERSION_NODOT) ;
            if <define>BOOST_DEBUG_PYTHON in $(properties)
            {
                lib = python$(PYTHON_VERSION_NODOT)_d ;
            }
            properties += <find-library>$(lib) ;
        }
        else if $(toolset) in $(gcc-compilers)
        {
            local python-root = $(GCC_PYTHON_ROOT) ;
            if <define>BOOST_DEBUG_PYTHON in $(properties)
            {
                python-root = $(GCC_PYTHON_DEBUG_ROOT) ;
            }
            properties += <library-path>$(python-root)/lib/python$(PYTHON_VERSION)/config ;
        }
        else if ! ( $(toolset) = msvc )
        {
            local lib = $(PYTHON_LIB) ;
            if <define>BOOST_DEBUG_PYTHON in $(properties)
            {
                lib = $(PYTHON_D_LIB) ;
            }
            properties += <library-file>$(lib) ;
        } 
    }
    return $(properties) ;
}

rule select-python-includes ( toolset variant : properties * )
{
    if $(toolset) in $(gcc-compilers)
    {
        local python-root = $(GCC_PYTHON_ROOT) ;
        if <define>BOOST_DEBUG_PYTHON in $(properties)
        {
            python-root = $(GCC_PYTHON_DEBUG_ROOT) ;
        }
        properties += <include>$(python-root)/include/python$(PYTHON_VERSION) ;
    }
    else
    {
      properties +=
          <include>$(PYTHON_ROOT)/include
            <include>$(PYTHON_ROOT)/PC # in case the user is using a source installation
              <debug-python><define>_DEBUG
              ;
    }
    return $(properties) ;
}

PYTHON_PROPERTIES += 
        <$(gcc-compilers)><*><find-library>util
        <include>$(BOOST_ROOT)
          <stlport-iostream>on
            select-python-library
            ;

if $(NT)
{
    # Most Windows compilers pick up implicit directions from #pragmas
    # to look for those libraries.
    PYTHON_PROPERTIES += <library-path>$(PYTHON_LIB_PATH) ;
}

# Set gcc-specific release build properties
{
    local gcc-release-properties
      = <optimization>speed <cxxflags>-fomit-frame-pointer
      <inlining>on
      # GCC 2.95.4, which ships with Debian, chokes on this.
      # <cxxflags>-foptimize-sibling-calls 
      ;
    
    PYTHON_PROPERTIES += <$(gcc-compilers)><release>$(gcc-release-properties) ;
}

BOOST_PYTHON_V2_PROPERTIES 
  = $(PYTHON_PROPERTIES)
    <metrowerks><*><cxxflags>"-inline deferred" 
    <cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
      <define>BOOST_PYTHON_DYNAMIC_LIB
      <define>BOOST_PYTHON_V2
      ;

# Extends the RUN_PATH assignment for targets built under Cygwin so
# that the Python DLL can be found.
rule add-cygwin-python-run-path ( module )
{
    local d = $(GCC_ROOT_DIRECTORY) ;
    while $(d:D) != $(d)
    {
        local python-root = $(GCC_PYTHON_ROOT) ;
        if <define>BOOST_DEBUG_PYTHON in $(gBUILD_PROPERTIES)
        {
            python-root = $(GCC_PYTHON_DEBUG_ROOT) ;
        }
        gRUN_PATH($(module)) += $(python-root)/lib/python$(PYTHON_VERSION)/config ;

        d = $(d:D) ;
    }
}

# This is the generator function for Python modules. It deals with the
# need to change the name of modules compiled with debugging on. This
# is just a wrapper around the generator for shared libraries,
# dll-files.
rule python-files ( module implib ? : sources * )
{
    dll-files $(module) $(implib) : $(sources) : PYD ;

    if $(gCURRENT_TOOLSET) in $(gcc-compilers)
    {
        if $(NT)
        {
            add-cygwin-python-run-path $(<[-1]) ;
        }
        else
        {
            gRUN_PATH($(module)) += $(GCC_ROOT_DIRECTORY)/lib ;
        }
    }
}

if $(NT)
{
    # Adjust the name of Python modules so that they have the _d
    # suffix when compiled with python debugging enabled.
    gNAME_ADJUST(PYD) = name-adjust-PYD ;

    rule name-adjust-PYD ( pyd implib ? : properties * : toolset variant )
    {
        # Cygwin python is only happy if compiled modules have a .dll
        # extension
        if $(toolset) in $(gcc-compilers)
        {
            pyd = $(pyd:S=.dll) ;
        }
        else if <define>BOOST_DEBUG_PYTHON in $(properties)
        {
            pyd = $(pyd:S=)_d$(pyd:S) ;
        }
        return $(pyd) $(implib) ;
    }
}

rule Link-PYD
{
    gRUN_PATH($(<)) += $(gLOCATE($(<[1]))) ;
    if $(UNIX) 
    {
        RUN_LD_LIBRARY_PATH on $(<) = [ join $(gRUN_LD_LIBRARY_PATH($(<))) : $(SPLITPATH) ] ;
        gRUN_LD_LIBRARY_PATH($(<)) += $(gLOCATE($(<[1]))) ;
    }
    Link-action $(<) : $(>) : PYD ;
}

declare-target-type PYD : <shared-linkable>true ;
gGENERATOR_FUNCTION(PYD) = python-files ;
if $(NT)
{
    SUFPYD = .pyd $(SUFDLL[2-]) ;
}
else
{
    SUFPYD = $(SUFDLL) ;
}
PYDMODE = $(DLLMODE) ;
SHARED_TYPES += PYD ;

gTARGET_TYPE_ID(pyd) = PYD ;
gIS_DEPENDENCY(PYD) = TRUE ;

# Declare a python extension.
rule extension ( name : sources + : requirements * : default-BUILD * )
{
    requirements += $(PYTHON_PROPERTIES) ;
    

    declare-local-target $(name) : $(sources) : $(requirements) : $(default-BUILD) : PYD ;
}

# boost-python-runtest target : python-script sources : requirements : local-build : args
#
# declare two python module tests: $(<).test which builds when out-of-date, and
# $(<).run which builds unconditionally.
rule boost-python-runtest (
  target : python-script sources + : requirements * : local-build * : args * )
{
    # tell Jam that the python script is relative to this directory
    SEARCH on $(python-script) = $(SEARCH_SOURCE) ;
    

    # The user can add additional arguments in PYTHON_TEST_ARGS.
    local gPYTHON_TEST_ARGS = $(args) $(PYTHON_TEST_ARGS) ;

    # declare the two subsidiary tests.
    declare-local-target $(<) : $(>) : $(PYTHON_PROPERTIES) : $(4) : PYTHON_TEST ;
    declare-local-target $(<) : $(>) : $(PYTHON_PROPERTIES) : $(4) <suppress>true : PYTHON_RUNTEST ;
}

rule boost-python-test ( name : sources + : requirements * : default-BUILD * )
{
    extension $(name) : $(sources) : $(requirements) <suppress>true : $(4) ;
}

# special rules for two new target types: PYTHON_TEST and PYTHON_RUNTEST.
# These are identical except that PYTHON_TEST runs the test when out-of-date, and
# PYTHON_RUNTEST runs the test unconditionally. These are used by boost-python-runtest.
SUFPYTHON_TEST = .test ;
gGENERATOR_FUNCTION(PYTHON_TEST) = python-test-target ;
rule python-test-target ( test-target : sources + )
{
    python-runtest-aux $(test-target) : $(sources) ;
    Clean clean : $(test-target) ; # remove the test-target as part of any clean operation
    type-DEPENDS test : $(test-target) ;
    MakeLocate $(test-target) : $(LOCATE_TARGET) ;
    MakeLocate $(test-target) : $(LOCATE_TARGET) ;
}

if $(UNIX)
{
    gAPPEND_LD_LIBRARY_PATH = ":$LD_LIBRARY_PATH" ;
}

actions python-test-target bind PYTHON
{
    $(SHELL_SET)PATH=$(PATH)
    $(SHELL_EXPORT)PATH
    $(SHELL_SET)LD_LIBRARY_PATH=$(LD_LIBRARY_PATH)$(gAPPEND_LD_LIBRARY_PATH)
    $(SHELL_EXPORT)LD_LIBRARY_PATH
    $(SHELL_SET)PYTHONPATH=$(PYTHONPATH)
    $(SHELL_EXPORT)PYTHONPATH
    $(PYTHON_LAUNCH) $(PYTHON) $(PYTHON_ARGS) "$(>)" $(ARGS) 2>&1 "$(<)" || $(CATENATE) "$(<)"
}

SUFPYTHON_RUNTEST = .run ;
gGENERATOR_FUNCTION(PYTHON_RUNTEST) = python-runtest-target ;
rule python-runtest-target ( test-target : sources + )
{
    type-DEPENDS runtest : $(test-target) ;
    python-runtest-aux $(test-target) : $(sources) ;
    NOTFILE $(test-target) ;
    ALWAYS $(test-target) ;
}
actions python-runtest-target bind PYTHON
{
    $(SHELL_SET)PATH=$(PATH)
    $(SHELL_EXPORT)PATH
    $(SHELL_SET)LD_LIBRARY_PATH=$(LD_LIBRARY_PATH)$(gAPPEND_LD_LIBRARY_PATH)
    $(SHELL_EXPORT)LD_LIBRARY_PATH
    $(SHELL_SET)PYTHONPATH=$(PYTHONPATH)
    $(SHELL_EXPORT)PYTHONPATH
    $(PYTHON_LAUNCH) $(PYTHON) $(PYTHON_ARGS) "$(>)" $(ARGS)
}

# This is the rule that actually causes the test to run. It is used by
# bothe python-test-target and python-runtest-target.
rule python-runtest-aux ( target : sources + )
{
    DEPENDS $(target) : $(>) ;

    ARGS on $(target) += $(gPYTHON_TEST_ARGS) ;
    
    # Some tests need an extra command-line arg if built with
    # msvc. Checking the target grist is a cheap way to
    # find out. 
    switch $(target)
    {
        case <*\\\\msvc\\\\*>* : ARGS on $(target) += --broken-auto-ptr ;
        case <*\\\\intel-win32\\\\*>* : ARGS on $(target) += --broken-auto-ptr ;
    }

    # choose the right python executable
    local python = $(PYTHON) ;
    local splitpath = $(SPLITPATH) ;
    
    # compute the PYTHONPATH environment variable that will allow the test to
    # find all of the modules on which it depends.
    local pythonpath =
      $(gLOCATE($(>[1])))                     # location of python test file
          $(gRUN_PATH($(target)))                 # location of module dependencies
          [ join-path $(TOP) libs python test ]   # location of doctest
          $(>:D)                                  # directory of python driver file(s)
          $(PYTHONPATH)                           # base PYTHONPATH from environment
          ;
    
    if $(NT) && ( $(gCURRENT_TOOLSET) in $(gcc-compilers) )
    {
        python = python$(PYTHON_VERSION)$(SUFEXE) ;
        local python-root = $(GCC_PYTHON_ROOT) ;
        if <define>BOOST_DEBUG_PYTHON in $(gBUILD_PROPERTIES)
        {
            python-root = $(GCC_PYTHON_DEBUG_ROOT) ;
        }
        SEARCH on $(python) = [ join-path [ split-path $(python-root)/bin ] ] $(RUN_PATH) ;
        splitpath = ":" ;
        
        local pp ;
        for local p in $(pythonpath)
        {
            # if already rooted...
            if $(p:R=xx) = $(p)
            {
                p = [ split-path $(p) ] ;
                p = [ join-path /cygdrive [ SUBST $(p[1]) ^(.).* $1 ] $(p[2-]) ] ;
            }
            pp += $(p) ;
        }
        pythonpath = $(pp:T) ;
    }
    else if <define>BOOST_DEBUG_PYTHON in $(gBUILD_PROPERTIES) && $(NT)
    {
        python = $(PYTHON_D) ;
    }
    
    # adding the dummy at the end fixes a problem which causes a
    # trailing space to be added to the last path.
    PYTHONPATH on $(target) = [ join $(pythonpath) "" : $(splitpath) ] ;
    
    # set the path so that DLLs linked into extension modules will be
    # found
    PATH on $(target) = [ join
        $(gRUN_PATH($(target)))                      # location of module dependencies
        $(>:D)                                  # directory of python driver file(s)
        $(PATH)                                 # base PATH from environment
        : $(SPLITPATH) ] ;                      # platform path separator

    LD_LIBRARY_PATH on $(target) = [ join
        $(gRUN_LD_LIBRARY_PATH($(target)))      # location of module dependencies
        : $(SPLITPATH) ] ;                      # platform path separator

    PYTHON on $(target) = $(python) ;
    DEPENDS $(target) : $(python) ;
}

}
