1 # Copyright 2004 Vladimir Prus.
2 # Distributed under the Boost Software License, Version 1.0. (See
3 # accompanying file LICENSE_1_0.txt or copy at
4 # http://www.boost.org/LICENSE_1_0.txt)
6 # Support for Python and the the Boost.Python library.
10 # - a project 'python' with a target 'python' in it, that corresponds to the
13 # - a main target rule 'python-extension' which can be used to build a python
16 # Extensions that use Boost.Python must explicitly link to it.
24 import "class" : new ;
39 # Make this module a project.
40 project.initialize $(__name__) ;
43 # Save the project so that if 'init' is called several times we define new
44 # targets in the python project, not in whatever project we were called by.
45 .project = [ project.current ] ;
47 # Dynamic linker lib. Necessary to specify it explicitly on some platforms.
49 # This contains 'openpty' function need by python. Again, on some system need to
50 # pass this to linker explicitly.
52 # Python uses pthread symbols.
54 # Extra library needed by phtread on some platforms.
57 # The pythonpath feature specifies additional elements for the PYTHONPATH
58 # environment variable, set by run-pyd. For example, pythonpath can be used to
59 # access Python modules that are part of the product being built, but are not
60 # installed in the development system's default paths.
61 feature.feature pythonpath : : free optional path ;
63 # Initializes the Python toolset. Note that all parameters are optional.
65 # - version -- the version of Python to use. Should be in Major.Minor format,
66 # for example 2.3. Do not include the subminor version.
68 # - cmd-or-prefix: Preferably, a command that invokes a Python interpreter.
69 # Alternatively, the installation prefix for Python libraries and includes. If
70 # empty, will be guessed from the version, the platform's installation
71 # patterns, and the python executables that can be found in PATH.
73 # - includes: the include path to Python headers. If empty, will be guessed.
75 # - libraries: the path to Python library binaries. If empty, will be guessed.
76 # On MacOS/Darwin, you can also pass the path of the Python framework.
78 # - condition: if specified, should be a set of properties that are matched
79 # against the build configuration when Boost.Build selects a Python
80 # configuration to use.
82 # - extension-suffix: A string to append to the name of extension modules before
83 # the true filename extension. Ordinarily we would just compute this based on
84 # the value of the <python-debugging> feature. However ubuntu's python-dbg
85 # package uses the windows convention of appending _d to debug-build extension
86 # modules. We have no way of detecting ubuntu, or of probing python for the
87 # "_d" requirement, and if you configure and build python using
88 # --with-pydebug, you'll be using the standard *nix convention. Defaults to ""
89 # (or "_d" when targeting windows and <python-debugging> is set).
93 # using python : 2.3 ;
94 # using python : 2.3 : /usr/local/bin/python ;
96 rule init ( version ? : cmd-or-prefix ? : includes * : libraries ?
97 : condition * : extension-suffix ? )
99 project.push-current $(.project) ;
101 debug-message Configuring python... ;
102 for local v in version cmd-or-prefix includes libraries condition
106 debug-message " user-specified "$(v): \"$($(v))\" ;
110 configure $(version) : $(cmd-or-prefix) : $(includes) : $(libraries) : $(condition) : $(extension-suffix) ;
112 project.pop-current ;
115 # A simpler version of SHELL that grabs stderr as well as stdout, but returns
116 # nothing if there was an error.
118 local rule shell-cmd ( cmd )
120 debug-message running command '$(cmd)" 2>&1"' ;
121 x = [ SHELL $(cmd)" 2>&1" : exit-status ] ;
133 # Try to identify Cygwin symlinks. Invoking such a file directly as an NT
134 # executable from a native Windows build of bjam would be fatal to the bjam
135 # process. One /can/ invoke them through sh.exe or bash.exe, if you can prove
136 # that those are not also symlinks. ;-)
138 # If a symlink is found returns non-empty; we try to extract the target of the
139 # symlink from the file and return that.
141 # Note: 1. only works on NT 2. path is a native path.
142 local rule is-cygwin-symlink ( path )
146 # Look for a file with the given path having the S attribute set, as cygwin
147 # symlinks do. /-C means "do not use thousands separators in file sizes."
148 local dir-listing = [ shell-cmd "DIR /-C /A:S \""$(path)"\"" ] ;
152 # Escape any special regex characters in the base part of the path.
153 local base-pat = [ regex.escape $(path:D=) : ].[()*+?|\\$^ : \\ ] ;
155 # Extract the file's size from the directory listing.
156 local size-of-system-file = [ MATCH "([0-9]+) "$(base-pat) : $(dir-listing) : 1 ] ;
158 # If the file has a reasonably small size, look for the special symlink
159 # identification text.
160 if $(size-of-system-file) && [ numbers.less $(size-of-system-file) 1000 ]
162 local link = [ SHELL "FIND /OFF \"!<symlink>\" \""$(path)"\" 2>&1" ] ;
168 is-symlink = [ MATCH ".*!<symlink>([^"$(nl)"]*)" : $(link[1]) : 1 ] ;
171 is-symlink = [ *nix-path-to-native $(is-symlink) ] ;
172 is-symlink = $(is-symlink:R=$(path:D)) ;
178 return $(is-symlink) ;
182 # Append ext to each member of names that does not contain '.'.
184 local rule default-extension ( names * : ext * )
187 for local n in $(names)
191 case *.* : result += $(n) ;
192 case * : result += $(n)$(ext) ;
199 # Tries to determine whether invoking "cmd" would actually attempt to launch a
202 # Note: only works on NT.
204 local rule invokes-cygwin-symlink ( cmd )
206 local dirs = $(cmd:D) ;
209 dirs = . [ os.executable-path ] ;
211 local base = [ default-extension $(cmd:D=) : .exe .cmd .bat ] ;
212 local paths = [ GLOB $(dirs) : $(base) ] ;
215 # Make sure we have not run into a Cygwin symlink. Invoking such a file
216 # as an NT executable would be fatal for the bjam process.
217 return [ is-cygwin-symlink $(paths[1]) ] ;
222 local rule debug-message ( message * )
224 if --debug-configuration in [ modules.peek : ARGV ]
226 ECHO notice: [python-cfg] $(message) ;
231 # Like W32_GETREG, except prepend HKEY_CURRENT_USER\SOFTWARE and
232 # HKEY_LOCAL_MACHINE\SOFTWARE to the first argument, returning the first result
233 # found. Also accounts for the fact that on 64-bit machines, 32-bit software has
234 # its own area, under SOFTWARE\Wow6432node.
236 local rule software-registry-value ( path : data ? )
239 for local root in HKEY_CURRENT_USER HKEY_LOCAL_MACHINE
241 for local x64elt in "" Wow6432node\\ # Account for 64-bit windows
245 result = [ W32_GETREG $(root)\\SOFTWARE\\$(x64elt)$(path) : $(data) ] ;
254 .windows-drive-letter-re = ^([A-Za-z]):[\\/](.*) ;
255 .cygwin-drive-letter-re = ^/cygdrive/([a-z])/(.*) ;
257 .working-directory = [ PWD ] ;
258 .working-drive-letter = [ SUBST $(.working-directory) $(.windows-drive-letter-re) $1 ] ;
259 .working-drive-letter ?= [ SUBST $(.working-directory) $(.cygwin-drive-letter-re) $1 ] ;
262 local rule windows-to-cygwin-path ( path )
264 # If path is rooted with a drive letter, rewrite it using the /cygdrive
266 local p = [ SUBST $(path:T) $(.windows-drive-letter-re) /cygdrive/$1/$2 ] ;
268 # Else if path is rooted without a drive letter, use the working directory.
269 p ?= [ SUBST $(path:T) ^/(.*) /cygdrive/$(.working-drive-letter:L)/$2 ] ;
271 # Else return the path unchanged.
272 return $(p:E=$(path:T)) ;
276 # :W only works in Cygwin builds of bjam. This one works on NT builds as well.
278 local rule cygwin-to-windows-path ( path )
280 path = $(path:R="") ; # strip any trailing slash
282 local drive-letter = [ SUBST $(path) $(.cygwin-drive-letter-re) $1:/$2 ] ;
285 path = $(drive-letter) ;
287 else if $(path:R=/x) = $(path) # already rooted?
289 # Look for a cygwin mount that includes each head sequence in $(path).
290 local head = $(path) ;
295 local root = [ software-registry-value
296 "Cygnus Solutions\\Cygwin\\mounts v2\\"$(head) : native ] ;
300 path = $(tail:R=$(root)) ;
303 tail = $(tail:R=$(head:D=)) ;
315 return [ regex.replace $(path:R="") / \\ ] ;
319 # Convert a *nix path to native.
321 local rule *nix-path-to-native ( path )
325 path = [ cygwin-to-windows-path $(path) ] ;
331 # Convert an NT path to native.
333 local rule windows-path-to-native ( path )
341 return [ windows-to-cygwin-path $(path) ] ;
346 # Return nonempty if path looks like a windows path, i.e. it starts with a drive
347 # letter or contains backslashes.
349 local rule guess-windows-path ( path )
351 return [ SUBST $(path) ($(.windows-drive-letter-re)|.*([\\]).*) $1 ] ;
355 local rule path-to-native ( paths * )
359 for local p in $(paths)
361 if [ guess-windows-path $(p) ]
363 result += [ windows-path-to-native $(p) ] ;
367 result += [ *nix-path-to-native $(p:T) ] ;
374 # Validate the version string and extract the major/minor part we care about.
376 local rule split-version ( version )
378 local major-minor = [ MATCH ^([0-9]+)\.([0-9]+)(.*)$ : $(version) : 1 2 3 ] ;
379 if ! $(major-minor[2]) || $(major-minor[3])
381 ECHO "Warning: \"using python\" expects a two part (major, minor) version number; got" $(version) instead ;
383 # Add a zero to account for the missing digit if necessary.
387 return $(major-minor[1]) $(major-minor[2]) ;
391 # Build a list of versions from 3.4 down to 1.5. Because bjam can not enumerate
392 # registry sub-keys, we have no way of finding a version with a 2-digit minor
393 # version, e.g. 2.10 -- let us hope that never happens.
395 .version-countdown = ;
396 for local v in [ numbers.range 15 34 ]
398 .version-countdown = [ SUBST $(v) (.)(.*) $1.$2 ] $(.version-countdown) ;
402 local rule windows-installed-pythons ( version ? )
404 version ?= $(.version-countdown) ;
407 for local v in $(version)
409 local install-path = [
410 software-registry-value "Python\\PythonCore\\"$(v)"\\InstallPath" ] ;
414 install-path = [ windows-path-to-native $(install-path) ] ;
415 debug-message Registry indicates Python $(v) installed at \"$(install-path)\" ;
418 interpreters += $(:E=python:R=$(install-path)) ;
420 return $(interpreters) ;
424 local rule darwin-installed-pythons ( version ? )
426 version ?= $(.version-countdown) ;
429 = [ GLOB /System/Library/Frameworks /Library/Frameworks
430 : Python.framework ] ;
432 return $(prefix)/Versions/$(version)/bin/python ;
436 # Assume "python-cmd" invokes a python interpreter and invoke it to extract all
437 # the information we care about from its "sys" module. Returns void if
440 local rule probe ( python-cmd )
442 # Avoid invoking a Cygwin symlink on NT.
446 skip-symlink = [ invokes-cygwin-symlink $(python-cmd) ] ;
451 debug-message -------------------------------------------------------------------- ;
452 debug-message \"$(python-cmd)\" would attempt to invoke a Cygwin symlink, ;
453 debug-message causing a bjam built for Windows to hang. ;
455 debug-message If you intend to target a Cygwin build of Python, please ;
456 debug-message replace the path to the link with the path to a real executable ;
457 debug-message (guessing: \"$(skip-symlink)\") "in" your 'using python' line ;
458 debug-message "in" user-config.jam or site-config.jam. Do not forget to escape ;
459 debug-message backslashes ;
460 debug-message -------------------------------------------------------------------- ;
464 # Prepare a List of Python format strings and expressions that can be
465 # used to print the constants we want from the sys module.
467 # We do not really want sys.version since that is a complicated string,
468 # so get the information from sys.version_info instead.
469 local format = "version=%d.%d" ;
470 local exprs = "version_info[0]" "version_info[1]" ;
472 for local s in $(sys-elements[2-])
478 # Invoke Python and ask it for all those values.
480 $(python-cmd)" -c \"from sys import *; print('"$(format:J=\\n)"' % ("$(exprs:J=,)"))\"" ;
482 local output = [ shell-cmd $(full-cmd) ] ;
485 # Parse the output to get all the results.
489 for s in $(sys-elements)
491 # These variables are expected to be declared local in the
492 # caller, so Jam's dynamic scoping will set their values there.
493 sys.$(s) = [ SUBST $(output) \\<$(s)=([^$(nl)]+) $1 ] ;
501 # Make sure the "libraries" and "includes" variables (in an enclosing scope)
502 # have a value based on the information given.
504 local rule compute-default-paths ( target-os : version ? : prefix ? :
507 exec-prefix ?= $(prefix) ;
509 if $(target-os) = windows
511 # The exec_prefix is where you're supposed to look for machine-specific
513 local default-library-path = $(exec-prefix)\\libs ;
514 local default-include-path = $(:E=Include:R=$(prefix)) ;
516 # If the interpreter was found in a directory called "PCBuild" or
517 # "PCBuild8," assume we're looking at a Python built from the source
518 # distro, and go up one additional level to the default root. Otherwise,
519 # the default root is the directory where the interpreter was found.
521 # We ask Python itself what the executable path is in case of
522 # intermediate symlinks or shell scripts.
523 local executable-dir = $(sys.executable:D) ;
525 if [ MATCH ^(PCBuild) : $(executable-dir:D=) ]
527 debug-message "This Python appears to reside in a source distribution;" ;
528 debug-message "prepending \""$(executable-dir)"\" to default library search path" ;
530 default-library-path = $(executable-dir) $(default-library-path) ;
532 default-include-path = $(:E=PC:R=$(executable-dir:D)) $(default-include-path) ;
534 debug-message "and \""$(default-include-path[1])"\" to default #include path" ;
537 libraries ?= $(default-library-path) ;
538 includes ?= $(default-include-path) ;
542 includes ?= $(prefix)/include/python$(version) ;
544 local lib = $(exec-prefix)/lib ;
545 libraries ?= $(lib)/python$(version)/config $(lib) ;
549 # The version of the python interpreter to use.
550 feature.feature python : : propagated ;
551 feature.feature python.interpreter : : free ;
553 toolset.flags python.capture-output PYTHON : <python.interpreter> ;
556 # Support for Python configured --with-pydebug
558 feature.feature python-debugging : off on : propagated ;
559 builtin.variant debug-python : debug : <python-debugging>on ;
562 # Return a list of candidate commands to try when looking for a Python
563 # interpreter. prefix is expected to be a native path.
565 local rule candidate-interpreters ( version ? : prefix ? : target-os )
567 local bin-path = bin ;
568 if $(target-os) = windows
570 # On Windows, look in the root directory itself and, to work with the
571 # result of a build-from-source, the PCBuild directory.
572 bin-path = PCBuild8 PCBuild "" ;
575 bin-path = $(bin-path:R=$(prefix)) ;
577 if $(target-os) in windows darwin
580 $(:E=python:R=$(bin-path)) # Relative to the prefix, if any
582 [ $(target-os)-installed-pythons $(version) ] # Standard install locations
587 # Search relative to the prefix, or if none supplied, in PATH.
588 local unversioned = $(:E=python:R=$(bin-path:E=)) ;
590 # If a version was specified, look for a python with that specific
591 # version appended before looking for one called, simply, "python"
592 return $(unversioned)$(version) $(unversioned) ;
597 # Compute system library dependencies for targets linking with static Python
600 # On many systems, Python uses libraries such as pthreads or libdl. Since static
601 # libraries carry no library dependency information of their own that the linker
602 # can extract, these extra dependencies have to be given explicitly on the link
603 # line of the client. The information about these dependencies is packaged into
604 # the "python" target below.
606 # Even where Python itself uses pthreads, it never allows extension modules to
607 # be entered concurrently (unless they explicitly give up the interpreter lock).
608 # Therefore, extension modules do not need the efficiency overhead of threadsafe
609 # code as produced by <threading>multi, and we handle libpthread along with
610 # other libraries here. Note: this optimization is based on an assumption that
611 # the compiler generates link-compatible code in both the single- and
612 # multi-threaded cases, and that system libraries do not change their ABIs
615 # Returns a list of usage-requirements that link to the necessary system
618 local rule system-library-dependencies ( target-os )
622 case s[uo][nl]* : # solaris, sun, sunos
623 # Add a librt dependency for the gcc toolset on SunOS (the sun
624 # toolset adds -lrt unconditionally). While this appears to
625 # duplicate the logic already in gcc.jam, it does not as long as
626 # we are not forcing <threading>multi.
628 # On solaris 10, distutils.sysconfig.get_config_var('LIBS') yields
629 # '-lresolv -lsocket -lnsl -lrt -ldl'. However, that does not seem
630 # to be the right list for extension modules. For example, on my
631 # installation, adding -ldl causes at least one test to fail because
632 # the library can not be found and removing it causes no failures.
634 # Apparently, though, we need to add -lrt for gcc.
635 return <toolset>gcc:<library>rt ;
637 case osf : return <library>pthread <toolset>gcc:<library>rt ;
640 case darwin : return ;
641 case windows : return ;
643 case hpux : return <library>rt ;
644 case *bsd : return <library>pthread <toolset>gcc:<library>util ;
646 case aix : return <library>pthread <library>dl ;
648 case * : return <library>pthread <library>dl
649 <toolset>gcc:<library>util <toolset-intel:platform>linux:<library>util ;
654 # Declare a target to represent Python's library.
656 local rule declare-libpython-target ( version ? : requirements * )
658 # Compute the representation of Python version in the name of Python's
660 local lib-version = $(version) ;
661 if <target-os>windows in $(requirements)
663 local major-minor = [ split-version $(version) ] ;
664 lib-version = $(major-minor:J="") ;
665 if <python-debugging>on in $(requirements)
667 lib-version = $(lib-version)_d ;
673 ECHO *** warning: could not determine Python version, which will ;
674 ECHO *** warning: probably prevent us from linking with the python ;
675 ECHO *** warning: library. Consider explicitly passing the version ;
676 ECHO *** warning: to 'using python'. ;
680 lib python.lib : : <name>python$(lib-version) $(requirements) ;
684 # Implementation of init.
685 local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
686 condition * : extension-suffix ? )
691 local interpreter-cmd ;
693 local target-os = [ feature.get-values target-os : $(condition) ] ;
694 target-os ?= [ feature.defaults target-os ] ;
695 target-os = $(target-os:G=) ;
697 if $(target-os) = windows && <python-debugging>on in $(condition)
699 extension-suffix ?= _d ;
701 extension-suffix ?= "" ;
703 # Normalize and dissect any version number.
707 major-minor = [ split-version $(version) ] ;
708 version = $(major-minor:J=.) ;
713 if ! $(cmd-or-prefix) || [ GLOB $(cmd-or-prefix) : * ]
715 # If the user did not pass a command, whatever we got was a prefix.
716 prefix = $(cmd-or-prefix) ;
717 cmds-to-try = [ candidate-interpreters $(version) : $(prefix) : $(target-os) ] ;
721 # Work with the command the user gave us.
722 cmds-to-try = $(cmd-or-prefix) ;
724 # On Windows, do not nail down the interpreter command just yet in case
725 # the user specified something that turns out to be a cygwin symlink,
726 # which could bring down bjam if we invoke it.
727 if $(target-os) != windows
729 interpreter-cmd = $(cmd-or-prefix) ;
733 # Values to use in case we can not really find anything in the system.
734 local fallback-cmd = $(cmds-to-try[1]) ;
735 local fallback-version ;
737 # Anything left to find or check?
738 if ! ( $(interpreter-cmd) && $(includes) && $(libraries) )
740 # Values to be extracted from python's sys module. These will be set by
741 # the probe rule, above, using Jam's dynamic scoping.
742 local sys-elements = version platform prefix exec_prefix executable ;
743 local sys.$(sys-elements) ;
745 # Compute the string Python's sys.platform needs to match. If not
746 # targeting Windows or cygwin we will assume only native builds can
747 # possibly run, so we will not require a match and we leave sys.platform
752 case windows : platform = win32 ;
753 case cygwin : platform = cygwin ;
759 local cmd = $(cmds-to-try[1]) ;
760 cmds-to-try = $(cmds-to-try[2-]) ;
762 debug-message Checking interpreter command \"$(cmd)\"... ;
765 fallback-version ?= $(sys.version) ;
767 # Check for version/platform validity.
768 for local x in version platform
770 if $($(x)) && $($(x)) != $(sys.$(x))
772 debug-message ...$(x) "mismatch (looking for"
773 $($(x)) but found $(sys.$(x))")" ;
780 debug-message ...requested configuration matched! ;
782 exec-prefix = $(sys.exec_prefix) ;
784 compute-default-paths $(target-os) : $(sys.version) :
785 $(sys.prefix) : $(sys.exec_prefix) ;
787 version = $(sys.version) ;
788 interpreter-cmd ?= $(cmd) ;
789 cmds-to-try = ; # All done.
794 debug-message ...does not invoke a working interpreter ;
799 # Anything left to compute?
800 if $(includes) && $(libraries)
806 version ?= $(fallback-version) ;
808 exec-prefix ?= $(prefix) ;
809 compute-default-paths $(target-os) : $(version) : $(prefix:E=) ;
812 if ! $(interpreter-cmd)
814 fallback-cmd ?= python ;
815 debug-message No working Python interpreter found. ;
816 if [ os.name ] != NT || ! [ invokes-cygwin-symlink $(fallback-cmd) ]
818 interpreter-cmd = $(fallback-cmd) ;
819 debug-message falling back to \"$(interpreter-cmd)\" ;
823 includes = [ path-to-native $(includes) ] ;
824 libraries = [ path-to-native $(libraries) ] ;
826 debug-message "Details of this Python configuration:" ;
827 debug-message " interpreter command:" \"$(interpreter-cmd:E=<empty>)\" ;
828 debug-message " include path:" \"$(includes:E=<empty>)\" ;
829 debug-message " library path:" \"$(libraries:E=<empty>)\" ;
830 if $(target-os) = windows
832 debug-message " DLL search path:" \"$(exec-prefix:E=<empty>)\" ;
836 # End autoconfiguration sequence.
838 local target-requirements = $(condition) ;
840 # Add the version, if any, to the target requirements.
843 if ! $(version) in [ feature.values python ]
845 feature.extend python : $(version) ;
847 target-requirements += <python>$(version:E=default) ;
850 target-requirements += <target-os>$(target-os) ;
852 # See if we can find a framework directory on darwin.
853 local framework-directory ;
854 if $(target-os) = darwin
856 # Search upward for the framework directory.
857 local framework-directory = $(libraries[-1]) ;
858 while $(framework-directory:D=) && $(framework-directory:D=) != Python.framework
860 framework-directory = $(framework-directory:D) ;
863 if $(framework-directory:D=) = Python.framework
865 debug-message framework directory is \"$(framework-directory)\" ;
869 debug-message "no framework directory found; using library path" ;
870 framework-directory = ;
874 local dll-path = $(libraries) ;
876 # Make sure that we can find the Python DLL on Windows.
877 if ( $(target-os) = windows ) && $(exec-prefix)
879 dll-path += $(exec-prefix) ;
883 # Prepare usage requirements.
885 local usage-requirements = [ system-library-dependencies $(target-os) ] ;
886 usage-requirements += <include>$(includes) <python.interpreter>$(interpreter-cmd) ;
887 if <python-debugging>on in $(condition)
889 if $(target-os) = windows
891 # In pyconfig.h, Py_DEBUG is set if _DEBUG is set. If we define
892 # Py_DEBUG we will get multiple definition warnings.
893 usage-requirements += <define>_DEBUG ;
897 usage-requirements += <define>Py_DEBUG ;
901 # Global, but conditional, requirements to give access to the interpreter
902 # for general utilities, like other toolsets, that run Python scripts.
903 toolset.add-requirements
904 $(target-requirements:J=,):<python.interpreter>$(interpreter-cmd) ;
906 # Register the right suffix for extensions.
907 register-extension-suffix $(extension-suffix) : $(target-requirements) ;
910 # Declare the "python" target. This should really be called
911 # python_for_embedding.
914 if $(framework-directory)
918 : $(target-requirements)
920 : $(usage-requirements) <framework>$(framework-directory)
925 declare-libpython-target $(version) : $(target-requirements) ;
927 # This is an evil hack. On, Windows, when Python is embedded, nothing
928 # seems to set up sys.path to include Python's standard library
929 # (http://article.gmane.org/gmane.comp.python.general/544986). The evil
930 # here, aside from the workaround necessitated by Python's bug, is that:
932 # a. we're guessing the location of the python standard library from the
933 # location of pythonXX.lib
935 # b. we're hijacking the <testing.launcher> property to get the
936 # environment variable set up, and the user may want to use it for
937 # something else (e.g. launch the debugger).
938 local set-PYTHONPATH ;
939 if $(target-os) = windows
941 set-PYTHONPATH = [ common.prepend-path-variable-command PYTHONPATH :
942 $(libraries:D)/Lib ] ;
947 : $(target-requirements)
949 # Why python.lib must be listed here instead of along with the
950 # system libs is a mystery, but if we do not do it, on cygwin,
951 # -lpythonX.Y never appears in the command line (although it does on
953 : $(usage-requirements)
954 <testing.launcher>$(set-PYTHONPATH)
955 <library-path>$(libraries) <dll-path>$(dll-path) <library>python.lib
959 # On *nix, we do not want to link either Boost.Python or Python extensions
960 # to libpython, because the Python interpreter itself provides all those
961 # symbols. If we linked to libpython, we would get duplicate symbols. So
962 # declare two targets -- one for building extensions and another for
965 # Unlike most *nix systems, Mac OS X's linker does not permit undefined
966 # symbols when linking a shared library. So, we still need to link against
967 # the Python framework, even when building extensions. Note that framework
968 # builds of Python always use shared libraries, so we do not need to worry
969 # about duplicate Python symbols.
970 if $(target-os) in windows cygwin darwin
972 alias python_for_extensions : python : $(target-requirements) ;
974 # On AIX we need Python extensions and Boost.Python to import symbols from
975 # the Python interpreter. Dynamic libraries opened with dlopen() do not
976 # inherit the symbols from the Python interpreter.
977 else if $(target-os) = aix
979 alias python_for_extensions
981 : $(target-requirements)
983 : $(usage-requirements) <linkflags>-Wl,-bI:$(libraries[1])/python.exp
988 alias python_for_extensions
990 : $(target-requirements)
992 : $(usage-requirements)
1000 return $(.configured) ;
1004 type.register PYTHON_EXTENSION : : SHARED_LIB ;
1007 local rule register-extension-suffix ( root : condition * )
1011 switch [ feature.get-values target-os : $(condition) ]
1013 case windows : suffix = pyd ;
1014 case cygwin : suffix = dll ;
1017 if [ feature.get-values python : $(condition) ] in 1.5 1.6 2.0 2.1 2.2 2.3 2.4
1026 case * : suffix = so ;
1029 type.set-generated-target-suffix PYTHON_EXTENSION : $(condition) : <$(root).$(suffix)> ;
1033 # Unset 'lib' prefix for PYTHON_EXTENSION
1034 type.set-generated-target-prefix PYTHON_EXTENSION : : "" ;
1037 rule python-extension ( name : sources * : requirements * : default-build * :
1038 usage-requirements * )
1042 requirements += <use>/python//python_for_extensions ;
1044 requirements += <suppress-import-lib>true ;
1046 local project = [ project.current ] ;
1048 targets.main-target-alternative
1049 [ new typed-target $(name) : $(project) : PYTHON_EXTENSION
1050 : [ targets.main-target-sources $(sources) : $(name) ]
1051 : [ targets.main-target-requirements $(requirements) : $(project) ]
1052 : [ targets.main-target-default-build $(default-build) : $(project) ]
1056 IMPORT python : python-extension : : python-extension ;
1060 common.copy $(<) : $(>) ;
1066 2to3 -wn --no-diffs "$(<)"
1067 2to3 -dwn --no-diffs "$(<)"
1071 # Support for testing.
1072 type.register PY : py ;
1073 type.register RUN_PYD_OUTPUT ;
1074 type.register RUN_PYD : : TEST ;
1077 class python-test-generator : generator
1081 rule __init__ ( * : * )
1083 generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
1084 self.composing = true ;
1087 rule run ( project name ? : property-set : sources * : multiple ? )
1089 local pyversion = [ $(property-set).get <python> ] ;
1091 local other-pythons ;
1093 # Make new target that converting Python source by 2to3 when running with Python 3.
1094 local rule make-2to3-source ( source )
1096 if $(pyversion) >= 3.0
1098 local a = [ new action $(source) : python.py2to3 : $(property-set) ] ;
1099 local t = [ utility.basename [ $(s).name ] ] ;
1100 local p = [ new file-target $(t) : PY : $(project) : $(a) ] ;
1109 for local s in $(sources)
1111 if [ $(s).type ] = PY
1115 # First Python source ends up on command line.
1116 python = [ make-2to3-source $(s) ] ;
1121 # Other Python sources become dependencies.
1122 other-pythons += [ make-2to3-source $(s) ] ;
1128 for local s in $(sources)
1130 if [ $(s).type ] = PYTHON_EXTENSION
1132 extensions += $(s) ;
1137 for local s in $(sources)
1139 if [ type.is-derived [ $(s).type ] LIB ]
1140 && ! $(s) in $(extensions)
1147 for local s in $(sources)
1149 if [ type.is-derived [ $(s).type ] CPP ]
1151 local name = [ utility.basename [ $(s).name ] ] ;
1152 if $(name) = [ utility.basename [ $(python).name ] ]
1154 name = $(name)_ext ;
1156 local extension = [ generators.construct $(project) $(name) :
1157 PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
1159 # The important part of usage requirements returned from
1160 # PYTHON_EXTENSION generator are xdll-path properties that will
1161 # allow us to find the python extension at runtime.
1162 property-set = [ $(property-set).add $(extension[1]) ] ;
1164 # Ignore usage requirements. We're a top-level generator and
1165 # nobody is going to use what we generate.
1166 new-sources += $(extension[2-]) ;
1170 property-set = [ $(property-set).add-raw <dependency>$(other-pythons) ] ;
1172 return [ construct-result $(python) $(extensions) $(new-sources) :
1173 $(project) $(name) : $(property-set) ] ;
1179 [ new python-test-generator python.capture-output : : RUN_PYD_OUTPUT ] ;
1181 generators.register-standard testing.expect-success
1182 : RUN_PYD_OUTPUT : RUN_PYD ;
1185 # There are two different ways of spelling OS names. One is used for [ os.name ]
1186 # and the other is used for the <host-os> and <target-os> properties. Until that
1187 # is remedied, this sets up a crude mapping from the latter to the former, that
1188 # will work *for the purposes of cygwin/NT cross-builds only*. Could not think
1189 # of a better name than "translate".
1191 .translate-os-windows = NT ;
1192 .translate-os-cygwin = CYGWIN ;
1193 local rule translate-os ( src-os )
1195 local x = $(.translate-os-$(src-os)) [ os.name ] ;
1200 # Extract the path to a single ".pyd" source. This is used to build the
1201 # PYTHONPATH for running bpl tests.
1203 local rule pyd-pythonpath ( source )
1205 return [ on $(source) return $(LOCATE) $(SEARCH) ] ;
1209 # The flag settings on testing.capture-output do not apply to python.capture
1210 # output at the moment. Redo this explicitly.
1211 toolset.flags python.capture-output ARGS <testing.arg> ;
1214 rule capture-output ( target : sources * : properties * )
1216 # Setup up a proper DLL search path. Here, $(sources[1]) is a python module
1217 # and $(sources[2]) is a DLL. Only $(sources[1]) is passed to
1218 # testing.capture-output, so RUN_PATH variable on $(sources[2]) is not
1219 # consulted. Move it over explicitly.
1220 RUN_PATH on $(sources[1]) = [ on $(sources[2-]) return $(RUN_PATH) ] ;
1222 PYTHONPATH = [ sequence.transform pyd-pythonpath : $(sources[2-]) ] ;
1223 PYTHONPATH += [ feature.get-values pythonpath : $(properties) ] ;
1225 # After test is run, we remove the Python module, but not the Python script.
1226 testing.capture-output $(target) : $(sources[1]) : $(properties) :
1229 # PYTHONPATH is different; it will be interpreted by whichever Python is
1230 # invoked and so must follow path rules for the target os. The only OSes
1231 # where we can run python for other OSes currently are NT and CYGWIN so we
1232 # only need to handle those cases.
1233 local target-os = [ feature.get-values target-os : $(properties) ] ;
1234 # Oddly, host-os is not in properties, so grab the default value.
1235 local host-os = [ feature.defaults host-os ] ;
1236 host-os = $(host-os:G=) ;
1237 if $(target-os) != $(host-os) && $(target-os) in windows cygwin && $(host-os) in windows cygwin
1239 PYTHONPATH = [ sequence.transform $(host-os)-to-$(target-os)-path :
1242 local path-separator = [ os.path-separator [ translate-os $(target-os) ] ] ;
1243 local set-PYTHONPATH = [ common.variable-setting-command PYTHONPATH :
1244 $(PYTHONPATH:J=$(path-separator)) ] ;
1245 LAUNCHER on $(target) = $(set-PYTHONPATH) [ on $(target) return \"$(PYTHON)\" ] ;
1249 rule bpl-test ( name : sources * : requirements * )
1252 sources ?= $(name).py $(name).cpp ;
1253 return [ testing.make-test run-pyd : $(sources) /boost/python//boost_python
1254 : $(requirements) : $(name) ] ;
1258 IMPORT $(__name__) : bpl-test : : bpl-test ;