Imported Upstream version 1.57.0
[platform/upstream/boost.git] / tools / build / src / tools / python.jam
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)
5
6 # Support for Python and the the Boost.Python library.
7 #
8 # This module defines
9 #
10 # - a project 'python' with a target 'python' in it, that corresponds to the
11 #   python library
12 #
13 # - a main target rule 'python-extension' which can be used to build a python
14 #   extension.
15 #
16 # Extensions that use Boost.Python must explicitly link to it.
17
18 import type ;
19 import testing ;
20 import generators ;
21 import project ;
22 import errors ;
23 import targets ;
24 import "class" : new ;
25 import os ;
26 import common ;
27 import toolset ;
28 import regex ;
29 import numbers ;
30 import string ;
31 import property ;
32 import sequence ;
33 import path ;
34 import feature ;
35 import set ;
36 import builtin ;
37
38
39 # Make this module a project.
40 project.initialize $(__name__) ;
41 project python ;
42
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 ] ;
46
47 # Dynamic linker lib. Necessary to specify it explicitly on some platforms.
48 lib dl ;
49 # This contains 'openpty' function need by python. Again, on some system need to
50 # pass this to linker explicitly.
51 lib util ;
52 # Python uses pthread symbols.
53 lib pthread ;
54 # Extra library needed by phtread on some platforms.
55 lib rt ;
56
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 ;
62
63 # Initializes the Python toolset. Note that all parameters are optional.
64 #
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.
67 #
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.
72 #
73 # - includes: the include path to Python headers. If empty, will be guessed.
74 #
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.
77 #
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.
81 #
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).
90 #
91 # Example usage:
92 #
93 #   using python : 2.3 ;
94 #   using python : 2.3 : /usr/local/bin/python ;
95 #
96 rule init ( version ? : cmd-or-prefix ? : includes * : libraries ?
97     : condition * : extension-suffix ? )
98 {
99     project.push-current $(.project) ;
100
101     debug-message Configuring python... ;
102     for local v in version cmd-or-prefix includes libraries condition
103     {
104         if $($(v))
105         {
106             debug-message "  user-specified "$(v): \"$($(v))\" ;
107         }
108     }
109
110     configure $(version) : $(cmd-or-prefix) : $(includes) : $(libraries) : $(condition) : $(extension-suffix) ;
111
112     project.pop-current ;
113 }
114
115 # A simpler version of SHELL that grabs stderr as well as stdout, but returns
116 # nothing if there was an error.
117 #
118 local rule shell-cmd ( cmd )
119 {
120     debug-message running command '$(cmd)" 2>&1"' ;
121     x = [ SHELL $(cmd)" 2>&1" : exit-status ] ;
122     if $(x[2]) = 0
123     {
124         return $(x[1]) ;
125     }
126     else
127     {
128         return ;
129     }
130 }
131
132
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. ;-)
137 #
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.
140 #
141 # Note: 1. only works on NT  2. path is a native path.
142 local rule is-cygwin-symlink ( path )
143 {
144     local is-symlink = ;
145
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)"\"" ] ;
149
150     if $(dir-listing)
151     {
152         # Escape any special regex characters in the base part of the path.
153         local base-pat = [ regex.escape $(path:D=) : ].[()*+?|\\$^ : \\ ] ;
154
155         # Extract the file's size from the directory listing.
156         local size-of-system-file = [ MATCH "([0-9]+) "$(base-pat) : $(dir-listing) : 1 ] ;
157
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 ]
161         {
162             local link = [ SHELL "FIND /OFF \"!<symlink>\" \""$(path)"\" 2>&1" ] ;
163             if $(link[2]) != 0
164             {
165                 local nl = "
166
167 " ;
168                 is-symlink = [ MATCH ".*!<symlink>([^"$(nl)"]*)" : $(link[1]) : 1 ] ;
169                 if $(is-symlink)
170                 {
171                     is-symlink = [ *nix-path-to-native $(is-symlink) ] ;
172                     is-symlink = $(is-symlink:R=$(path:D)) ;
173                 }
174
175             }
176         }
177     }
178     return $(is-symlink) ;
179 }
180
181
182 # Append ext to each member of names that does not contain '.'.
183 #
184 local rule default-extension ( names * : ext * )
185 {
186     local result ;
187     for local n in $(names)
188     {
189         switch $(n)
190         {
191             case *.* : result += $(n) ;
192             case * : result += $(n)$(ext) ;
193         }
194     }
195     return $(result) ;
196 }
197
198
199 # Tries to determine whether invoking "cmd" would actually attempt to launch a
200 # cygwin symlink.
201 #
202 # Note: only works on NT.
203 #
204 local rule invokes-cygwin-symlink ( cmd )
205 {
206     local dirs = $(cmd:D) ;
207     if ! $(dirs)
208     {
209         dirs = . [ os.executable-path ] ;
210     }
211     local base = [ default-extension $(cmd:D=) : .exe .cmd .bat ] ;
212     local paths = [ GLOB $(dirs) : $(base) ] ;
213     if $(paths)
214     {
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]) ] ;
218     }
219 }
220
221
222 local rule debug-message ( message * )
223 {
224     if --debug-configuration in [ modules.peek : ARGV ]
225     {
226         ECHO notice: [python-cfg] $(message) ;
227     }
228 }
229
230
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.
235 #
236 local rule software-registry-value ( path : data ? )
237 {
238     local result ;
239     for local root in HKEY_CURRENT_USER HKEY_LOCAL_MACHINE
240     {
241         for local x64elt in "" Wow6432node\\ # Account for 64-bit windows
242         {
243             if ! $(result)
244             {
245                 result = [ W32_GETREG $(root)\\SOFTWARE\\$(x64elt)$(path) : $(data) ] ;
246             }
247         }
248
249     }
250     return $(result) ;
251 }
252
253
254 .windows-drive-letter-re = ^([A-Za-z]):[\\/](.*) ;
255 .cygwin-drive-letter-re = ^/cygdrive/([a-z])/(.*) ;
256
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 ] ;
260
261
262 local rule windows-to-cygwin-path ( path )
263 {
264     # If path is rooted with a drive letter, rewrite it using the /cygdrive
265     # mountpoint.
266     local p = [ SUBST $(path:T) $(.windows-drive-letter-re) /cygdrive/$1/$2 ] ;
267
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 ] ;
270
271     # Else return the path unchanged.
272     return $(p:E=$(path:T)) ;
273 }
274
275
276 # :W only works in Cygwin builds of bjam.  This one works on NT builds as well.
277 #
278 local rule cygwin-to-windows-path ( path )
279 {
280     path = $(path:R="") ; # strip any trailing slash
281
282     local drive-letter = [ SUBST $(path) $(.cygwin-drive-letter-re) $1:/$2 ] ;
283     if $(drive-letter)
284     {
285         path = $(drive-letter) ;
286     }
287     else if $(path:R=/x) = $(path) # already rooted?
288     {
289         # Look for a cygwin mount that includes each head sequence in $(path).
290         local head = $(path) ;
291         local tail = "" ;
292
293         while $(head)
294         {
295             local root = [ software-registry-value
296                 "Cygnus Solutions\\Cygwin\\mounts v2\\"$(head) : native ] ;
297
298             if $(root)
299             {
300                 path = $(tail:R=$(root)) ;
301                 head = ;
302             }
303             tail = $(tail:R=$(head:D=)) ;
304
305             if $(head) = /
306             {
307                 head = ;
308             }
309             else
310             {
311                 head = $(head:D) ;
312             }
313         }
314     }
315     return [ regex.replace $(path:R="") / \\ ] ;
316 }
317
318
319 # Convert a *nix path to native.
320 #
321 local rule *nix-path-to-native ( path )
322 {
323     if [ os.name ] = NT
324     {
325         path = [ cygwin-to-windows-path $(path) ] ;
326     }
327     return $(path) ;
328 }
329
330
331 # Convert an NT path to native.
332 #
333 local rule windows-path-to-native ( path )
334 {
335     if [ os.name ] = NT
336     {
337         return $(path) ;
338     }
339     else
340     {
341         return [ windows-to-cygwin-path $(path) ] ;
342     }
343 }
344
345
346 # Return nonempty if path looks like a windows path, i.e. it starts with a drive
347 # letter or contains backslashes.
348 #
349 local rule guess-windows-path ( path )
350 {
351     return [ SUBST $(path) ($(.windows-drive-letter-re)|.*([\\]).*) $1 ] ;
352 }
353
354
355 local rule path-to-native ( paths * )
356 {
357     local result ;
358
359     for local p in $(paths)
360     {
361         if [ guess-windows-path $(p) ]
362         {
363             result += [ windows-path-to-native $(p) ] ;
364         }
365         else
366         {
367             result += [ *nix-path-to-native $(p:T) ] ;
368         }
369     }
370     return $(result) ;
371 }
372
373
374 # Validate the version string and extract the major/minor part we care about.
375 #
376 local rule split-version ( version )
377 {
378     local major-minor = [ MATCH ^([0-9]+)\.([0-9]+)(.*)$ : $(version) : 1 2 3 ] ;
379     if ! $(major-minor[2]) || $(major-minor[3])
380     {
381         ECHO "Warning: \"using python\" expects a two part (major, minor) version number; got" $(version) instead ;
382
383         # Add a zero to account for the missing digit if necessary.
384         major-minor += 0 ;
385     }
386
387     return $(major-minor[1]) $(major-minor[2]) ;
388 }
389
390
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.
394 #
395 .version-countdown = ;
396 for local v in [ numbers.range 15 34 ]
397 {
398     .version-countdown = [ SUBST $(v) (.)(.*) $1.$2 ] $(.version-countdown) ;
399 }
400
401
402 local rule windows-installed-pythons ( version ? )
403 {
404     version ?= $(.version-countdown) ;
405     local interpreters ;
406
407     for local v in $(version)
408     {
409         local install-path = [
410           software-registry-value "Python\\PythonCore\\"$(v)"\\InstallPath" ] ;
411
412         if $(install-path)
413         {
414             install-path = [ windows-path-to-native $(install-path) ] ;
415             debug-message Registry indicates Python $(v) installed at \"$(install-path)\" ;
416         }
417
418         interpreters += $(:E=python:R=$(install-path)) ;
419     }
420     return $(interpreters) ;
421 }
422
423
424 local rule darwin-installed-pythons ( version ? )
425 {
426     version ?= $(.version-countdown) ;
427
428     local prefix
429       = [ GLOB /System/Library/Frameworks /Library/Frameworks
430           : Python.framework ] ;
431
432     return $(prefix)/Versions/$(version)/bin/python ;
433 }
434
435
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
438 # unsuccessful.
439 #
440 local rule probe ( python-cmd )
441 {
442     # Avoid invoking a Cygwin symlink on NT.
443     local skip-symlink ;
444     if [ os.name ] = NT
445     {
446         skip-symlink = [ invokes-cygwin-symlink $(python-cmd) ] ;
447     }
448
449     if $(skip-symlink)
450     {
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. ;
454         debug-message ;
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 -------------------------------------------------------------------- ;
461     }
462     else
463     {
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.
466
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]" ;
471
472         for local s in $(sys-elements[2-])
473         {
474             format += $(s)=%s ;
475             exprs += $(s) ;
476         }
477
478         # Invoke Python and ask it for all those values.
479         local full-cmd =
480             $(python-cmd)" -c \"from sys import *; print('"$(format:J=\\n)"' % ("$(exprs:J=,)"))\"" ;
481
482         local output = [ shell-cmd $(full-cmd) ] ;
483         if $(output)
484         {
485             # Parse the output to get all the results.
486             local nl = "
487
488 " ;
489             for s in $(sys-elements)
490             {
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 ] ;
494             }
495         }
496         return $(output) ;
497     }
498 }
499
500
501 # Make sure the "libraries" and "includes" variables (in an enclosing scope)
502 # have a value based on the information given.
503 #
504 local rule compute-default-paths ( target-os : version ? : prefix ? :
505     exec-prefix ? )
506 {
507     exec-prefix ?= $(prefix) ;
508
509     if $(target-os) = windows
510     {
511         # The exec_prefix is where you're supposed to look for machine-specific
512         # libraries.
513         local default-library-path = $(exec-prefix)\\libs ;
514         local default-include-path = $(:E=Include:R=$(prefix)) ;
515
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.
520
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) ;
524
525         if [ MATCH ^(PCBuild) : $(executable-dir:D=) ]
526         {
527             debug-message "This Python appears to reside in a source distribution;" ;
528             debug-message "prepending \""$(executable-dir)"\" to default library search path" ;
529
530             default-library-path = $(executable-dir) $(default-library-path) ;
531
532             default-include-path = $(:E=PC:R=$(executable-dir:D)) $(default-include-path) ;
533
534             debug-message "and \""$(default-include-path[1])"\" to default #include path" ;
535         }
536
537         libraries ?= $(default-library-path) ;
538         includes ?= $(default-include-path) ;
539     }
540     else
541     {
542         includes ?= $(prefix)/include/python$(version) ;
543
544         local lib = $(exec-prefix)/lib ;
545         libraries ?= $(lib)/python$(version)/config $(lib) ;
546     }
547 }
548
549 # The version of the python interpreter to use.
550 feature.feature python : : propagated ;
551 feature.feature python.interpreter : : free ;
552
553 toolset.flags python.capture-output PYTHON : <python.interpreter> ;
554
555 #
556 # Support for Python configured --with-pydebug
557 #
558 feature.feature python-debugging : off on : propagated ;
559 builtin.variant debug-python : debug : <python-debugging>on ;
560
561
562 # Return a list of candidate commands to try when looking for a Python
563 # interpreter. prefix is expected to be a native path.
564 #
565 local rule candidate-interpreters ( version ? : prefix ? : target-os )
566 {
567     local bin-path = bin ;
568     if $(target-os) = windows
569     {
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 "" ;
573     }
574
575     bin-path = $(bin-path:R=$(prefix)) ;
576
577     if $(target-os) in windows darwin
578     {
579         return                                            # Search:
580             $(:E=python:R=$(bin-path))                    #   Relative to the prefix, if any
581             python                                        #   In the PATH
582             [ $(target-os)-installed-pythons $(version) ] #   Standard install locations
583         ;
584     }
585     else
586     {
587         # Search relative to the prefix, or if none supplied, in PATH.
588         local unversioned = $(:E=python:R=$(bin-path:E=)) ;
589
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) ;
593     }
594 }
595
596
597 # Compute system library dependencies for targets linking with static Python
598 # libraries.
599 #
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.
605 #
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
613 # either.
614 #
615 # Returns a list of usage-requirements that link to the necessary system
616 # libraries.
617 #
618 local rule system-library-dependencies ( target-os )
619 {
620     switch $(target-os)
621     {
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.
627
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.
633
634             # Apparently, though, we need to add -lrt for gcc.
635             return <toolset>gcc:<library>rt ;
636
637         case osf : return  <library>pthread <toolset>gcc:<library>rt ;
638
639         case qnx* : return ;
640         case darwin : return ;
641         case windows : return ;
642
643         case hpux : return  <library>rt ;
644         case *bsd : return  <library>pthread <toolset>gcc:<library>util ;
645
646         case aix : return  <library>pthread <library>dl ;
647
648         case * : return  <library>pthread <library>dl
649             <toolset>gcc:<library>util <toolset-intel:platform>linux:<library>util ;
650     }
651 }
652
653
654 # Declare a target to represent Python's library.
655 #
656 local rule declare-libpython-target ( version ? : requirements * )
657 {
658     # Compute the representation of Python version in the name of Python's
659     # library file.
660     local lib-version = $(version) ;
661     if <target-os>windows in $(requirements)
662     {
663         local major-minor = [ split-version $(version) ] ;
664         lib-version = $(major-minor:J="") ;
665         if <python-debugging>on in $(requirements)
666         {
667             lib-version = $(lib-version)_d ;
668         }
669     }
670
671     if ! $(lib-version)
672     {
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'. ;
677     }
678
679     # Declare it.
680     lib python.lib : : <name>python$(lib-version) $(requirements) ;
681 }
682
683
684 # Implementation of init.
685 local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? :
686     condition * : extension-suffix ? )
687 {
688     local prefix ;
689     local exec-prefix ;
690     local cmds-to-try ;
691     local interpreter-cmd ;
692
693     local target-os = [ feature.get-values target-os : $(condition) ] ;
694     target-os ?= [ feature.defaults target-os ] ;
695     target-os = $(target-os:G=) ;
696
697     if $(target-os) = windows && <python-debugging>on in $(condition)
698     {
699         extension-suffix ?= _d ;
700     }
701     extension-suffix ?= "" ;
702
703     # Normalize and dissect any version number.
704     local major-minor ;
705     if $(version)
706     {
707         major-minor = [ split-version $(version) ] ;
708         version = $(major-minor:J=.) ;
709     }
710
711     local cmds-to-try ;
712
713     if ! $(cmd-or-prefix) || [ GLOB $(cmd-or-prefix) : * ]
714     {
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) ] ;
718     }
719     else
720     {
721         # Work with the command the user gave us.
722         cmds-to-try = $(cmd-or-prefix) ;
723
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
728         {
729             interpreter-cmd = $(cmd-or-prefix) ;
730         }
731     }
732
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 ;
736
737     # Anything left to find or check?
738     if ! ( $(interpreter-cmd) && $(includes) && $(libraries) )
739     {
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) ;
744
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
748         # blank.
749         local platform ;
750         switch $(target-os)
751         {
752             case windows : platform = win32 ;
753             case cygwin : platform = cygwin ;
754         }
755
756         while $(cmds-to-try)
757         {
758             # Pop top command.
759             local cmd = $(cmds-to-try[1]) ;
760             cmds-to-try = $(cmds-to-try[2-]) ;
761
762             debug-message Checking interpreter command \"$(cmd)\"... ;
763             if [ probe $(cmd) ]
764             {
765                 fallback-version ?= $(sys.version) ;
766
767                 # Check for version/platform validity.
768                 for local x in version platform
769                 {
770                     if $($(x)) && $($(x)) != $(sys.$(x))
771                     {
772                         debug-message ...$(x) "mismatch (looking for"
773                             $($(x)) but found $(sys.$(x))")" ;
774                         cmd = ;
775                     }
776                 }
777
778                 if $(cmd)
779                 {
780                     debug-message ...requested configuration matched! ;
781
782                     exec-prefix = $(sys.exec_prefix) ;
783
784                     compute-default-paths $(target-os) : $(sys.version) :
785                         $(sys.prefix) : $(sys.exec_prefix) ;
786
787                     version = $(sys.version) ;
788                     interpreter-cmd ?= $(cmd) ;
789                     cmds-to-try = ;  # All done.
790                 }
791             }
792             else
793             {
794                 debug-message ...does not invoke a working interpreter ;
795             }
796         }
797     }
798
799     # Anything left to compute?
800     if $(includes) && $(libraries)
801     {
802         .configured = true ;
803     }
804     else
805     {
806         version ?= $(fallback-version) ;
807         version ?= 2.5 ;
808         exec-prefix ?= $(prefix) ;
809         compute-default-paths $(target-os) : $(version) : $(prefix:E=) ;
810     }
811
812     if ! $(interpreter-cmd)
813     {
814         fallback-cmd ?= python ;
815         debug-message No working Python interpreter found. ;
816         if [ os.name ] != NT || ! [ invokes-cygwin-symlink $(fallback-cmd) ]
817         {
818             interpreter-cmd = $(fallback-cmd) ;
819             debug-message falling back to \"$(interpreter-cmd)\" ;
820         }
821     }
822
823     includes = [ path-to-native $(includes) ] ;
824     libraries = [ path-to-native $(libraries) ] ;
825
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
831     {
832         debug-message "  DLL search path:" \"$(exec-prefix:E=<empty>)\" ;
833     }
834
835     #
836     # End autoconfiguration sequence.
837     #
838     local target-requirements = $(condition) ;
839
840     # Add the version, if any, to the target requirements.
841     if $(version)
842     {
843         if ! $(version) in [ feature.values python ]
844         {
845             feature.extend python : $(version) ;
846         }
847         target-requirements += <python>$(version:E=default) ;
848     }
849
850     target-requirements += <target-os>$(target-os) ;
851
852     # See if we can find a framework directory on darwin.
853     local framework-directory ;
854     if $(target-os) = darwin
855     {
856         # Search upward for the framework directory.
857         local framework-directory = $(libraries[-1]) ;
858         while $(framework-directory:D=) && $(framework-directory:D=) != Python.framework
859         {
860             framework-directory = $(framework-directory:D) ;
861         }
862
863         if $(framework-directory:D=) = Python.framework
864         {
865             debug-message framework directory is \"$(framework-directory)\" ;
866         }
867         else
868         {
869             debug-message "no framework directory found; using library path" ;
870             framework-directory = ;
871         }
872     }
873
874     local dll-path = $(libraries) ;
875
876     # Make sure that we can find the Python DLL on Windows.
877     if ( $(target-os) = windows ) && $(exec-prefix)
878     {
879         dll-path += $(exec-prefix) ;
880     }
881
882     #
883     # Prepare usage requirements.
884     #
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)
888     {
889         if $(target-os) = windows
890         {
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 ;
894         }
895         else
896         {
897             usage-requirements += <define>Py_DEBUG ;
898         }
899     }
900
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) ;
905
906     # Register the right suffix for extensions.
907     register-extension-suffix $(extension-suffix) : $(target-requirements) ;
908
909     #
910     # Declare the "python" target. This should really be called
911     # python_for_embedding.
912     #
913
914     if $(framework-directory)
915     {
916         alias python
917           :
918           : $(target-requirements)
919           :
920           : $(usage-requirements) <framework>$(framework-directory)
921           ;
922     }
923     else
924     {
925         declare-libpython-target $(version) : $(target-requirements) ;
926
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:
931         #
932         # a. we're guessing the location of the python standard library from the
933         #    location of pythonXX.lib
934         #
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
940         {
941             set-PYTHONPATH = [ common.prepend-path-variable-command PYTHONPATH :
942                 $(libraries:D)/Lib ] ;
943         }
944
945         alias python
946           :
947           : $(target-requirements)
948           :
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
952             # linux).
953           : $(usage-requirements)
954             <testing.launcher>$(set-PYTHONPATH)
955               <library-path>$(libraries) <dll-path>$(dll-path) <library>python.lib
956           ;
957     }
958
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
963     # embedding.
964     #
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
971     {
972         alias python_for_extensions : python : $(target-requirements) ;
973     }
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
978     {
979         alias python_for_extensions
980             :
981             : $(target-requirements)
982             :
983             : $(usage-requirements) <linkflags>-Wl,-bI:$(libraries[1])/python.exp
984             ;
985     }
986     else
987     {
988         alias python_for_extensions
989             :
990             : $(target-requirements)
991             :
992             : $(usage-requirements)
993             ;
994     }
995 }
996
997
998 rule configured ( )
999 {
1000      return $(.configured) ;
1001 }
1002
1003
1004 type.register PYTHON_EXTENSION : : SHARED_LIB ;
1005
1006
1007 local rule register-extension-suffix ( root : condition * )
1008 {
1009     local suffix ;
1010
1011     switch [ feature.get-values target-os : $(condition) ]
1012     {
1013         case windows : suffix = pyd ;
1014         case cygwin : suffix = dll ;
1015         case hpux :
1016         {
1017             if [ feature.get-values python : $(condition) ] in 1.5 1.6 2.0 2.1 2.2 2.3 2.4
1018             {
1019                 suffix = sl ;
1020             }
1021             else
1022             {
1023                 suffix = so ;
1024             }
1025         }
1026         case * : suffix = so ;
1027     }
1028
1029     type.set-generated-target-suffix PYTHON_EXTENSION : $(condition) : <$(root).$(suffix)> ;
1030 }
1031
1032
1033 # Unset 'lib' prefix for PYTHON_EXTENSION
1034 type.set-generated-target-prefix PYTHON_EXTENSION : : "" ;
1035
1036
1037 rule python-extension ( name : sources * : requirements * : default-build * :
1038                         usage-requirements * )
1039 {
1040     if [ configured ]
1041     {
1042         requirements += <use>/python//python_for_extensions ;
1043     }
1044     requirements += <suppress-import-lib>true ;
1045
1046     local project = [ project.current ] ;
1047
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) ]
1053         ] ;
1054 }
1055
1056 IMPORT python : python-extension : : python-extension ;
1057
1058 rule py2to3
1059 {
1060     common.copy $(<) : $(>) ;
1061     2to3 $(<) ;
1062 }
1063
1064 actions 2to3
1065 {
1066     2to3 -wn --no-diffs "$(<)"
1067     2to3 -dwn --no-diffs "$(<)"
1068 }
1069
1070
1071 # Support for testing.
1072 type.register PY : py ;
1073 type.register RUN_PYD_OUTPUT ;
1074 type.register RUN_PYD : : TEST ;
1075
1076
1077 class python-test-generator : generator
1078 {
1079     import set ;
1080
1081     rule __init__ ( * : * )
1082     {
1083         generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
1084         self.composing = true ;
1085     }
1086
1087     rule run ( project name ? : property-set : sources * : multiple ? )
1088     {
1089         local pyversion = [ $(property-set).get <python> ] ;
1090         local python ;
1091         local other-pythons ;
1092
1093         # Make new target that converting Python source by 2to3 when running with Python 3.
1094         local rule make-2to3-source ( source )
1095         {
1096             if $(pyversion) >= 3.0
1097             {
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) ] ;
1101                 return $(p) ;
1102             }
1103             else
1104             {
1105                 return $(source) ;
1106             }
1107         }
1108
1109         for local s in $(sources)
1110         {
1111             if [ $(s).type ] = PY
1112             {
1113                 if ! $(python)
1114                 {
1115                     # First Python source ends up on command line.
1116                     python = [ make-2to3-source $(s) ] ;
1117
1118                 }
1119                 else
1120                 {
1121                     # Other Python sources become dependencies.
1122                     other-pythons += [ make-2to3-source $(s) ] ;
1123                 }
1124             }
1125         }
1126
1127         local extensions ;
1128         for local s in $(sources)
1129         {
1130             if [ $(s).type ] = PYTHON_EXTENSION
1131             {
1132                 extensions += $(s) ;
1133             }
1134         }
1135
1136         local libs ;
1137         for local s in $(sources)
1138         {
1139             if [ type.is-derived [ $(s).type ] LIB ]
1140               && ! $(s) in $(extensions)
1141             {
1142                 libs += $(s) ;
1143             }
1144         }
1145
1146         local new-sources ;
1147         for local s in $(sources)
1148         {
1149             if [ type.is-derived [ $(s).type ] CPP ]
1150             {
1151                 local name = [ utility.basename [ $(s).name ] ] ;
1152                 if $(name) = [ utility.basename [ $(python).name ] ]
1153                 {
1154                     name = $(name)_ext ;
1155                 }
1156                 local extension = [ generators.construct $(project) $(name) :
1157                   PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
1158
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]) ] ;
1163
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-]) ;
1167             }
1168         }
1169
1170         property-set = [ $(property-set).add-raw <dependency>$(other-pythons) ] ;
1171
1172         return [ construct-result $(python) $(extensions) $(new-sources) :
1173             $(project) $(name) : $(property-set) ] ;
1174     }
1175 }
1176
1177
1178 generators.register
1179   [ new python-test-generator python.capture-output : : RUN_PYD_OUTPUT ] ;
1180
1181 generators.register-standard testing.expect-success
1182   : RUN_PYD_OUTPUT : RUN_PYD ;
1183
1184
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".
1190 #
1191 .translate-os-windows = NT ;
1192 .translate-os-cygwin = CYGWIN ;
1193 local rule translate-os ( src-os )
1194 {
1195     local x = $(.translate-os-$(src-os)) [ os.name ] ;
1196     return $(x[1]) ;
1197 }
1198
1199
1200 # Extract the path to a single ".pyd" source. This is used to build the
1201 # PYTHONPATH for running bpl tests.
1202 #
1203 local rule pyd-pythonpath ( source )
1204 {
1205     return [ on $(source) return $(LOCATE) $(SEARCH) ] ;
1206 }
1207
1208
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> ;
1212
1213
1214 rule capture-output ( target : sources * : properties * )
1215 {
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) ] ;
1221
1222     PYTHONPATH  = [ sequence.transform pyd-pythonpath : $(sources[2-]) ] ;
1223     PYTHONPATH += [ feature.get-values pythonpath : $(properties) ] ;
1224
1225     # After test is run, we remove the Python module, but not the Python script.
1226     testing.capture-output $(target) : $(sources[1]) : $(properties) :
1227         $(sources[2-]) ;
1228
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
1238     {
1239         PYTHONPATH = [ sequence.transform $(host-os)-to-$(target-os)-path :
1240             $(PYTHONPATH) ] ;
1241     }
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)\" ] ;
1246 }
1247
1248
1249 rule bpl-test ( name : sources * : requirements * )
1250 {
1251     local s ;
1252     sources ?= $(name).py $(name).cpp ;
1253     return [ testing.make-test run-pyd : $(sources) /boost/python//boost_python
1254         : $(requirements) : $(name) ] ;
1255 }
1256
1257
1258 IMPORT $(__name__) : bpl-test : : bpl-test ;