]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/tools/build/src/tools/python.jam
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / tools / build / src / tools / python.jam
index cc13385cac9bf7530b1c184b8d232320916ed3a0..cf8c379b3140830dc7862e9fabd9c75bb162c2ed 100644 (file)
@@ -34,6 +34,7 @@ import path ;
 import feature ;
 import set ;
 import builtin ;
+import property-set ;
 
 
 # Make this module a project.
@@ -50,7 +51,10 @@ lib dl ;
 # pass this to linker explicitly.
 lib util ;
 # Python uses pthread symbols.
-lib pthread ;
+lib pthread :
+    : <target-os>linux:<link>shared
+    ;
+
 # Extra library needed by phtread on some platforms.
 lib rt ;
 
@@ -60,6 +64,10 @@ lib rt ;
 # installed in the development system's default paths.
 feature.feature pythonpath : : free optional path ;
 
+# The best configured version of Python 2 and 3.
+py2-version = ;
+py3-version = ;
+
 # Initializes the Python toolset. Note that all parameters are optional.
 #
 # - version -- the version of Python to use. Should be in Major.Minor format,
@@ -76,7 +84,7 @@ feature.feature pythonpath : : free optional path ;
 #   On MacOS/Darwin, you can also pass the path of the Python framework.
 #
 # - condition: if specified, should be a set of properties that are matched
-#   against the build configuration when Boost.Build selects a Python
+#   against the build configuration when B2 selects a Python
 #   configuration to use.
 #
 # - extension-suffix: A string to append to the name of extension modules before
@@ -103,7 +111,7 @@ rule init ( version ? : cmd-or-prefix ? : includes * : libraries ?
     {
         if $($(v))
         {
-            debug-message "  user-specified "$(v): \"$($(v))\" ;
+            debug-message "  user-specified $(v):" \"$($(v))\" ;
         }
     }
 
@@ -150,7 +158,7 @@ local rule is-cygwin-symlink ( path )
     if $(dir-listing)
     {
         # Escape any special regex characters in the base part of the path.
-        local base-pat = [ regex.escape $(path:D=) : ].[()*+?|\\$^ : \\ ] ;
+        local base-pat = [ regex.escape $(path:D=) : "].[()*+?|\\$^" : \\ ] ;
 
         # Extract the file's size from the directory listing.
         local size-of-system-file = [ MATCH "([0-9]+) "$(base-pat) : $(dir-listing) : 1 ] ;
@@ -223,7 +231,7 @@ local rule debug-message ( message * )
 {
     if --debug-configuration in [ modules.peek : ARGV ]
     {
-        ECHO notice: [python-cfg] $(message) ;
+        ECHO "notice:" "[python-cfg]" $(message) ;
     }
 }
 
@@ -251,8 +259,8 @@ local rule software-registry-value ( path : data ? )
 }
 
 
-.windows-drive-letter-re = ^([A-Za-z]):[\\/](.*) ;
-.cygwin-drive-letter-re = ^/cygdrive/([a-z])/(.*) ;
+.windows-drive-letter-re = "^([A-Za-z]):[\\/](.*)" ;
+.cygwin-drive-letter-re = "^/cygdrive/([a-z])/(.*)" ;
 
 .working-directory = [ PWD ] ;
 .working-drive-letter = [ SUBST $(.working-directory) $(.windows-drive-letter-re) $1 ] ;
@@ -279,7 +287,7 @@ local rule cygwin-to-windows-path ( path )
 {
     path = $(path:R="") ; # strip any trailing slash
 
-    local drive-letter = [ SUBST $(path) $(.cygwin-drive-letter-re) $1:/$2 ] ;
+    local drive-letter = [ SUBST $(path) $(.cygwin-drive-letter-re) "$1:/$2" ] ;
     if $(drive-letter)
     {
         path = $(drive-letter) ;
@@ -348,7 +356,7 @@ local rule windows-path-to-native ( path )
 #
 local rule guess-windows-path ( path )
 {
-    return [ SUBST $(path) ($(.windows-drive-letter-re)|.*([\\]).*) $1 ] ;
+    return [ SUBST $(path) "($(.windows-drive-letter-re)|.*([\\]).*)" $1 ] ;
 }
 
 
@@ -375,7 +383,7 @@ local rule path-to-native ( paths * )
 #
 local rule split-version ( version )
 {
-    local major-minor = [ MATCH ^([0-9]+)\.([0-9]+)(.*)$ : $(version) : 1 2 3 ] ;
+    local major-minor = [ MATCH "^([0-9]+)\.([0-9]+)(.*)$" : $(version) : 1 2 3 ] ;
     if ! $(major-minor[2]) || $(major-minor[3])
     {
         ECHO "Warning: \"using python\" expects a two part (major, minor) version number; got" $(version) instead ;
@@ -454,7 +462,7 @@ local rule probe ( python-cmd )
         debug-message ;
         debug-message If you intend to target a Cygwin build of Python, please ;
         debug-message replace the path to the link with the path to a real executable ;
-        debug-message (guessing: \"$(skip-symlink)\") "in" your 'using python' line ;
+        debug-message "(guessing:" \"$(skip-symlink)\") "in" your 'using python' line ;
         debug-message "in" user-config.jam or site-config.jam. Do not forget to escape ;
         debug-message backslashes ;
         debug-message -------------------------------------------------------------------- ;
@@ -490,7 +498,7 @@ local rule probe ( python-cmd )
             {
                 # These variables are expected to be declared local in the
                 # caller, so Jam's dynamic scoping will set their values there.
-                sys.$(s) = [ SUBST $(output) \\<$(s)=([^$(nl)]+) $1 ] ;
+                sys.$(s) = [ SUBST $(output) "\\<$(s)=([^$(nl)]+)" $1 ] ;
             }
         }
         return $(output) ;
@@ -547,7 +555,7 @@ local rule compute-default-paths ( target-os : version ? : prefix ? :
 }
 
 # The version of the python interpreter to use.
-feature.feature python : : propagated ;
+feature.feature python : : propagated symmetric ;
 feature.feature python.interpreter : : free ;
 
 toolset.flags python.capture-output PYTHON : <python.interpreter> ;
@@ -556,7 +564,7 @@ toolset.flags python.capture-output PYTHON : <python.interpreter> ;
 # Support for Python configured --with-pydebug
 #
 feature.feature python-debugging : off on : propagated ;
-builtin.variant debug-python : debug : <python-debugging>on ;
+variant debug-python : debug : <python-debugging>on ;
 
 
 # Return a list of candidate commands to try when looking for a Python
@@ -652,6 +660,15 @@ local rule system-library-dependencies ( target-os )
 }
 
 
+# Define a version suffix for libraries depending on Python.
+# For example, Boost.Python built for Python 2.7 uses the suffix "27"
+rule version-suffix ( version )
+{
+    local major-minor = [ split-version $(version) ] ;
+    local suffix = $(major-minor:J="") ;
+    return $(suffix) ;
+}
+
 # Declare a target to represent Python's library.
 #
 local rule declare-libpython-target ( version ? : requirements * )
@@ -671,10 +688,10 @@ local rule declare-libpython-target ( version ? : requirements * )
 
     if ! $(lib-version)
     {
-        ECHO *** warning: could not determine Python version, which will ;
-        ECHO *** warning: probably prevent us from linking with the python ;
-        ECHO *** warning: library.  Consider explicitly passing the version ;
-        ECHO *** warning: to 'using python'. ;
+        ECHO *** "warning:" could not determine Python version, which will ;
+        ECHO *** "warning:" probably prevent us from linking with the python ;
+        ECHO *** "warning:" library.  Consider explicitly passing the version ;
+        ECHO *** "warning:" to 'using python'. ;
     }
 
     # Declare it.
@@ -701,14 +718,6 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
     }
     extension-suffix ?= "" ;
 
-    # Normalize and dissect any version number.
-    local major-minor ;
-    if $(version)
-    {
-        major-minor = [ split-version $(version) ] ;
-        version = $(major-minor:J=.) ;
-    }
-
     local cmds-to-try ;
 
     if ! $(cmd-or-prefix) || [ GLOB $(cmd-or-prefix) : * ]
@@ -803,7 +812,7 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
         debug-message Python headers and libraries not found. ;
         return ;
     }
-    
+
     .configured = true ;
 
     if ! $(interpreter-cmd)
@@ -841,18 +850,28 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
     {
         .numpy = true ;
         .numpy-include = $(result[1]) ;
-       debug-message "NumPy enabled" ;
+        debug-message "NumPy enabled" ;
     }
     else
     {
-       debug-message "NumPy disabled. Reason:" ;
-       debug-message "  $(full-cmd) aborted with " ;
-       debug-message "  $(result[1])" ;
+        debug-message "NumPy disabled. Reason:" ;
+        debug-message "  $(full-cmd) aborted with " ;
+        debug-message "  $(result[1])" ;
     }
 
     #
     # End autoconfiguration sequence.
     #
+
+    # Normalize and dissect any version number.
+    local major-minor ;
+    if $(version)
+    {
+        major-minor = [ split-version $(version) ] ;
+        version = $(major-minor:J=.) ;
+    }
+
+
     local target-requirements = $(condition) ;
 
     # Add the version, if any, to the target requirements.
@@ -861,6 +880,11 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
         if ! $(version) in [ feature.values python ]
         {
             feature.extend python : $(version) ;
+            py$(major-minor[1])-version ?= $(version) ;
+            if $(py$(major-minor[1])-version) < $(version)
+            {
+                py$(major-minor[1])-version = $(version) ;
+            }
         }
         target-requirements += <python>$(version:E=default) ;
     }
@@ -916,40 +940,23 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
         }
     }
 
+    # In case we added duplicate requirements from what the user specified.
+    target-requirements = [ sequence.unique $(target-requirements) ] ;
+
     # Global, but conditional, requirements to give access to the interpreter
     # for general utilities, like other toolsets, that run Python scripts.
     toolset.add-requirements
-        $(target-requirements:J=,):<python.interpreter>$(interpreter-cmd) ;
-
-    # We also set a default requirement that assigns the first python configured
-    # for a particular target OS as the default. This makes it so that we can
-    # select a python interpreter with only knowledge of the target OS. And hence
-    # can configure different Pythons based on the target OS only.
-    local toolset-requirements = [ toolset.requirements ] ;
-    local toolset-target-os-requirements
-        = [ property.evaluate-conditionals-in-context
-            [ $(toolset-requirements).raw ] : <target-os>$(target-os) ] ;
-    if ! <python> in $(toolset-target-os-requirements:G)
-    {
-        toolset.add-requirements <target-os>$(target-os):<python>$(version:E=default) ;
-    }
-
-    # We also set a default requirement that assigns the first python configured
-    # for a particular target OS as the default. This makes it so that we can
-    # select a python interpreter with only knowledge of the target OS. And hence
-    # can configure different Pythons based on the target OS only.
-    local toolset-requirements = [ toolset.requirements ] ;
-    local toolset-target-os-requirements
-        = [ property.evaluate-conditionals-in-context
-            [ $(toolset-requirements).raw ] : <target-os>$(target-os) ] ;
-    if ! <python> in $(toolset-target-os-requirements:G)
-    {
-        toolset.add-requirements <target-os>$(target-os):<python>$(version:E=default) ;
-    }
+        "$(target-requirements:J=,):<python.interpreter>$(interpreter-cmd)" ;
 
     # Register the right suffix for extensions.
     register-extension-suffix $(extension-suffix) : $(target-requirements) ;
 
+    # Make sure that the python feature is always considered
+    # relevant for any targets that depend on python.  Without
+    # this, it would only be considered relevant when there are
+    # multiple configurations defined within the same build.
+    target-requirements += <relevant>python ;
+
     #
     # Declare the "python" target. This should really be called
     # python_for_embedding.
@@ -1026,7 +1033,7 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
             :
             : $(target-requirements)
             :
-            : $(usage-requirements) <linkflags>-Wl,-bI:$(libraries[1])/python.exp
+            : $(usage-requirements) <linkflags>"-Wl,-bI:$(libraries[1])/python.exp"
             ;
     }
     else
@@ -1038,6 +1045,26 @@ local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
             : $(usage-requirements)
             ;
     }
+
+}
+
+# Conditional rule specification that will prevent building of a target
+# if there is no matching python configuration available with the given
+# required properties.
+rule require-py ( properties * )
+{
+    local py-ext-target = [ $(.project).find python_for_extensions : no-error ] ;
+    if ! $(py-ext-target)
+    {
+        return <build>no ;
+    }
+    local property-set = [ property-set.create $(properties) ] ;
+    property-set = [ $(property-set).expand ] ;
+    local py-ext-alternative = [ $(py-ext-target).select-alternatives $(property-set) ] ;
+    if ! $(py-ext-alternative)
+    {
+        return <build>no ;
+    }
 }
 
 
@@ -1238,6 +1265,10 @@ local rule pyd-pythonpath ( source )
 toolset.flags python.capture-output ARGS <testing.arg> ;
 toolset.flags python.capture-output INPUT_FILES <testing.input-file> ;
 
+toolset.uses-features python.capture-output :
+    <testing.launcher> <testing.execute> <dll-path> <xdll-path> <target-os>
+    <pythonpath> ;
+
 rule capture-output ( target : sources * : properties * )
 {
     # Setup up a proper DLL search path. Here, $(sources[1]) is a python module
@@ -1250,10 +1281,7 @@ rule capture-output ( target : sources * : properties * )
     PYTHONPATH += [ feature.get-values pythonpath : $(properties) ] ;
 
     # After test is run, we remove the Python module, but not the Python script.
-    local targets-to-remove = $(sources[2-]) ;
-    targets-to-remove ?= none ;
-    testing.capture-output $(target) : $(sources[1]) : $(properties) :
-        $(targets-to-remove) ;
+    testing.capture-output $(target) : $(sources[1]) : $(properties) ;
 
     # PYTHONPATH is different; it will be interpreted by whichever Python is
     # invoked and so must follow path rules for the target os. The only OSes
@@ -1270,7 +1298,7 @@ rule capture-output ( target : sources * : properties * )
     }
     local path-separator = [ os.path-separator [ translate-os $(target-os) ] ] ;
     local set-PYTHONPATH = [ common.variable-setting-command PYTHONPATH :
-        $(PYTHONPATH:J=$(path-separator)) ] ;
+        $(PYTHONPATH:E=:J=$(path-separator)) ] ;
     LAUNCHER on $(target) = $(set-PYTHONPATH) [ on $(target) return \"$(PYTHON)\" ] ;
 }
 
@@ -1298,5 +1326,11 @@ rule numpy-test ( name : sources * : requirements * )
         : $(name) ] ;
 }
 
+rule py-version ( n )
+{
+    return $(py$(n)-version) ;
+}
+
 IMPORT $(__name__) : bpl-test : : bpl-test ;
 IMPORT $(__name__) : numpy-test : : numpy-test ;
+IMPORT $(__name__) : py-version : : py-version ;