1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Environment support"""
23 import os
24 import sys
25 import re
26 import platform
27 import types
28 import optparse
29 import time
30 import copy
31
32 from base import *
33 import util
34 import build_env
35 import plan
36 import msvs
37 import mbuild
38
40
41 lib = args[0]
42 msgb("REMOVING", lib)
43 util.remove_file(lib)
44 return (0,['REMOVED %s\n' % ( lib )])
45
46
47
48
49
50
51
53 """The is the environment for compilation. The environment
54 includes a dictionary for holding everything custom about this
55 environment. The default environment includes:
56
57 - command line options. These are also in the environment dictionary.
58 - build_dir defaultE{:} obj
59 - src_dir defaultE{:} . or path to the mfile
60 - gen_dir defaultE{:} None (default path for generated files, if set)
61 - shared defaultE{:} False (default: no shared libraries)
62 - static defaultE{:} False (default: not to statically link)
63 - opt defaultE{:} 'noopt' (could be 'noopt, 0,1,2,3)
64 - debug defaultE{:} False
65 - separate_pdb_files defaultE{:} False
66 - targets defaultE{:} [] targets to build
67 - verbose defaultE{:} 1
68 - compiler defaultE{:} 'gnu', 'ms', 'clang', 'icc', 'icl', 'iclang'
69 - extra_defines defaultE{:} ''
70 - extra_flags defaultE{:} '' (for both CXXFLAGS & CCFLAGS)
71 - extra_cxxflags defaultE{:} ''
72 - extra_ccflags defaultE{:} ''
73 - extra_linkflags defaultE{:} ''
74 - extra_libs defaultE{:} ''
75 - use_yasm defaultE{:} False
76
77 - CPPPATH defaultE{:} [] The list of include paths
78 - SYSTEMINCLUDE defaultE{:} [] The list of system include paths (Not
79 supported by MSVS).
80 - DEFINES defaultE{:} {} The dictionary of defines
81
82
83 - short names for the primary compiler toolsE{:}
84 - CXX_COMPILER cl or g++
85 - CC_COMPILER cl or gcc
86 - ASSEMBLER ml/ml64 or gcc/gas (gcc is the default for gnu)
87 - LINKER link or g++/gcc (g++ is the default for gnu)
88 - ARCHIVER ar
89 - RANLIB_CMD ranlib
90
91 - toolchain path to the compiler tools (default is ''). If toolchain is
92 set, it should end with a trailing slash.
93 - vc_dir path to the compiler VC directory for MSVS (default is '')n
94 - icc_version 7, 8, 9, 10, ...
95 - gcc_version 2.96, 3.x.y, 4.x.y, ...
96 - msvs_version 6 (VC98), 7 (.NET 2003), 8 (Pro 2005), ...
97
98 - primary compilation toolsE{:}
99 - CC cl or gcc (with toolchain path)
100 - CXX cl or g++ (with toolchain path)
101 - AS ml,ml64 or gcc/gas (with toolchain path)
102 - LINK link or gcc/g++ (with toolchain path)
103 - AR lib or ar (with toolchain path)
104 - RANLIB ranlib (with toolchain path)
105 - flags for primary toolsE{:}
106 - CCFLAGS
107 - CXXFLAGS
108 - ASFLAGS
109 - ARFLAGS
110 - LINKFLAGS
111 - LIBS (libraries for the end of the link statement)
112
113 - preprocessor flags
114 - DOPT /D or -D
115 - ASDOPT /D or -D
116 - IOPT /I or -I
117 - OPTPOPT /O or -O
118 - DEBUGOPT /Zi or -g
119
120 - options to control compilation outputE{:}
121 - COPT /c or -c
122 - COUT /Fo or -o
123 - ASMOUT /Fo or -o
124 - LIBOUT /outE{:} or -o
125 - LINKOUT /OUTE{:} or -o
126 - DLLOPT -shared
127
128 - Override-buildersE{:} set these to a function pointer if you want
129 to replace the default builder function.
130
131 - ASSEMBLE_BUILDER if not set default is to use assemble_default()
132 - CXX_COMPILE_BUILDER if not set default is to use cxx_default()
133 - CC_COMPILE_BUILDER if not set default is to use cc_default()
134 - LINK_BUILDER if not set default is to use link_default()
135 - STATIC_LIBRARY_BUILDER if not set default is to use static_lib_default()
136 - DYNAMIC_LIBRARY_BUILDER if not set default is to use dynamic_lib_default()
137
138 - default extensionsE{:}
139 - OBJEXT .obj or .o
140 - LIBEXT .lib or .a
141 - DLLEXT .dll, .so, or .dylib
142 - EXEEXT .exe or ''
143
144 - System valuesE{:}
145 - uname standard python tuple of values from uname.
146 - system standard valuesE{:} 'Linux', 'Windows', 'Darwin', 'Microsoft', 'FreeBSD'
147 - hostname
148 - build_os standard valuesE{:} 'lin', 'win', 'mac', 'bsd'
149 - host_os standard valuesE{:} 'lin', 'win', 'mac', 'bsd'
150 - build_cpu standard valuesE{:} 'ia32', 'x86-64', 'ipf'
151 - host_cpu standard valuesE{:} 'ia32', 'x86-64', 'ipf'
152
153 """
154
155 obj_pattern = re.compile(r'.obj$')
156 objext_pattern = re.compile(r'[%][(]OBJEXT[)]s$')
157
158 mbuild_subs_pattern = re.compile('%[(][^)]+[)]')
159
160 assignment_pattern = re.compile(r'(?P<name>[-A-Za-z0-9_]+)[=](?P<value>.+)')
161 supplement_pattern = re.compile(r'(?P<name>[-A-Za-z0-9_]+)[+][=](?P<value>.+)')
162
164 """Emit the version string.
165 @rtype: string
166 @return: The version string
167 """
168
169
170 msgb("VERSION", "$Id: mbuild_env.py 44 2007-03-16 15:54:44Z mjcharne $")
172 """Write a value to the environment dictionary"""
173 if isinstance(value,types.StringType):
174 self.env[k] = util.posix_slashes(value)
175 else:
176 self.env[k] = value
178 if k in self.env:
179 return True
180 return False
181
183 """Read the environment dictionary. Not doing any
184 substitutions."""
185
186 try:
187 return self.env[k]
188 except:
189 die("env key not found: %s" % (k))
190
191 - def expand(self, command_string, newenv=None):
192 """Alias for expand_string()"""
193 return self.expand_string(command_string, newenv)
194
196 """Read the environment dictionary, doing recursive
197 substitutions from the environment. If no environment is
198 supplied, then the default environment is used.
199
200 @type command_string: string or list of strings
201 @param command_string: A string with %(...)s variables in it
202 @type newenv: L{env_t}
203 @param newenv: An environment within which to do the expansion. If
204 null, the default environment is used.
205 @rtype: string
206 """
207 if newenv == None:
208 newenv = self.env
209 if isinstance(command_string, types.StringType):
210 return self._iterative_substitute(command_string, newenv)
211 if isinstance(command_string, types.ListType):
212 return map(lambda(x): self._iterative_substitute(x, newenv), command_string)
213 die("expand_string only handles substitution in strings or lists of strings")
214
216 """Read the the value of k from the environment dictionary,
217 doing recursive substitutions from the environment. If no
218 environment is supplied, then the default environment is used.
219
220 @type k: string or list of strings
221 @param k: A string (or strings) containing a single key name(s)
222 @type newenv: L{env_t}
223 @param newenv: An environment within which to do the expansion. If
224 null, the default environment is used.
225 @rtype: string
226 """
227 if newenv == None:
228 newenv = self.env
229 if k not in newenv:
230 die("Could not find %s in the environment" % k)
231
232
233 if isinstance(newenv[k],types.ListType):
234
235
236 return map(lambda(x): self._iterative_substitute(x,newenv), newenv[k])
237 if isinstance(newenv[k], types.StringType):
238 return self._iterative_substitute("%(" + k + ")s", newenv)
239
240 return newenv[k]
241
242 - def _mysub(self,input, keyname, newval):
243 """Replace %(keyname)s in input with newval"""
244
245 s = '%('+keyname+')s'
246
247 output = input.replace(s,newval)
248 return output
249
250
252 """Replace all the %(...)s with values in s from the
253 dictionary dct1. Note, the dictionary can contain tuples of
254 the form (key, dict). In this case, this code uses the lookup
255 result of dct1[key] to query yet the dictionary dict. That
256 lookup can result in a string or another such tuple."""
257
258 subs_pattern = re.compile('%[(](?P<name>[^)]+)[)]s')
259 t = s
260 m = subs_pattern.search(t)
261 while m:
262 name = m.group('name')
263 if name not in dct1:
264 die("Bad substitution for " + name)
265
266 v = dct1[name]
267
268 while not isinstance(v,types.StringType):
269 if isinstance(v,types.TupleType):
270 (key, dct) = v
271
272
273
274
275 try:
276 subkey = dct1[key]
277 except:
278 die("nested dictionary lookup error during iterative string " +
279 " expansion. key=%s" % (str(key)))
280
281 try:
282 v = dct[ subkey ]
283 except:
284 try:
285 v = dct['otherwise']
286 except:
287 die("nested dictionary lookup error during iterative string " +
288 " expansion. key=%s subkey=%s" % (str(key),str(subkey)))
289 elif isinstance(v,types.FunctionType):
290 try:
291 v = v(dct1)
292 except:
293 die("Bad function invokation during iterative string expansion")
294 else:
295 die("Bad environment value: " + str(v) +
296 " when searching: " + s)
297 t = self._mysub(t,name,v)
298 m = subs_pattern.search(t)
299 if debug:
300 print t
301 return t
302
304 """Repeatedly substitute values from the dictionary d into the
305 string s while '%(...)' substrings remain in the thing we want
306 to return. If the input s is a list, then we recursively
307 expand each element of that list"""
308
309 if isinstance(s,types.ListType):
310 return map(lambda(x): self.dosub(x,d), s)
311
312
313 t = s
314 while env_t.mbuild_subs_pattern.search(t):
315 t = t % d
316 return t
317
319 """Print out the environment"""
320 s = []
321 s.append("BUILD_CPU:")
322 s.append(self.env['build_cpu'])
323 s.append("HOST_CPU:")
324 s.append(self.env['host_cpu'])
325 s.append("\nBUILD_OS: ")
326 s.append(self.env['build_os'])
327 s.append("\nHOST_OS: ")
328 s.append(self.env['host_os'])
329 s.append("\nUNAME: ")
330 s.append(str(self.env['uname']))
331 s.append("\nHOSTNAME: ")
332 s.append(self.env['hostname'])
333 s.append("\nSYSTEM: ")
334 s.append(self.env['system'])
335 s.append("\nDICTIONARY:\n")
336 for k,v in self.env.iteritems():
337 s.append("\t")
338 s.append(k)
339 s.append("->")
340 s.append(str(v))
341 s.append("\n")
342 return ''.join(s)
343
345 if self._emitted_startup_msg:
346 return
347 self._emitted_startup_msg = True
348 if verbose(1):
349 msgb("INVOKED", " ".join(sys.argv))
350 msgb("START TIME", self.env['start_time_str'])
351 msgb("CURRENT DIRECTORY", os.getcwd())
352
353 msgb('UNAME', str(self.env['uname']).replace(':','_'))
354 msgb('SYSTEM', self.env['system'])
355 msgb('HOSTNAME', self.env['hostname'])
356 msgb("BUILD_OS", self.env['build_os'])
357 msgb("BUILD_CPU", self.env['build_cpu'])
358 msgb("HOST_OS", self.env['host_os'])
359 msgb("HOST_CPU", self.env['host_cpu'])
360
362 s = 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment'
363 try:
364 import _winreg
365 key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, s)
366 (val, typ) = _winreg.QueryValueEx(key, env_var)
367 return val
368 except:
369 mbuild.die(("Could not read windows registry for variable %s.\n" % \
370 (env_var)) +
371 "Use win32 python and install pywin32")
372
374
375 return self._check_registry_environment('PROCESSOR_IDENTIFIER')
376
377
379 return self._check_registry_environment('NUMBER_OF_PROCESSORS')
380
381
382 - def __init__(self, init_verbose=1, default_knobs=True):
383 """Build up the environment for compilation.
384 """
385 set_verbosity(int(init_verbose))
386 self.env = {}
387 self.parsed_args = False
388 self.added_common_knobs=False
389 self.added_default_knobs=False
390 self.env['python'] = sys.executable
391 self.env['CPPPATH'] = []
392 self.env['SYSTEMINCLUDE'] = []
393 self.env['DEFINES'] = {}
394
395 self.env['LINKPATH'] = []
396 self.env['LINKDIRS'] = ''
397 self.env['LINKFLAGS'] = ' %(LINKDIRS)s '
398
399 self.env['targets'] = []
400
401
402 self.env['build_dir'] = 'obj'
403 self.env['src_dir'] = ''
404 self.env['gen_dir'] = None
405 self.env['shared'] = False
406 self.env['static'] = False
407 self.env['debug'] = False
408 self.env['separate_pdb_files'] = False
409 self.env['opt'] = 'noopt'
410
411 self.env['LIBS'] = ''
412 self.env['CXX_COMPILER'] = ''
413 self.env['CC_COMPILER'] = ''
414 self.env['ASSEMBLER'] = ''
415 self.env['LINKER'] = ''
416
417
418
419 self.env['RC'] = ''
420 self.env['RC_CMD'] = ''
421 self.env['RCFLAGS'] = ''
422
423
424
425 self.env['use_compiler_to_link'] = False
426 self.env['ARCHIVER'] = ''
427 self.env['RANLIB_CMD'] = ''
428
429 self.env['CXX'] = ''
430 self.env['CC'] = ''
431 self.env['LINK'] = ''
432 self.env['AR'] = ''
433 self.env['AS'] = ''
434 self.env['RANLIB'] = ''
435
436 self.env['uname'] = platform.uname()
437 self.env['hostname'] = platform.node()
438 self.env['system'] = platform.system()
439
440 if util.check_python_version(2,6):
441 (distro, distro_ver, distro_id) = platform.linux_distribution()
442 else:
443 distro = ''
444 distro_ver = ''
445 self.env['distro'] = distro.strip()
446 self.env['distro_version'] = distro_ver
447
448
449 if 'HOME' in os.environ:
450 self.env['home'] = os.environ['HOME']
451 else:
452 self.env['home'] = 'unknown'
453
454
455
456
457
458 self.env['start_time_str'] = re.sub(":","_",util.get_time_str())
459 self.start_time = util.get_time()
460
461
462
463
464 self.env['target_cpu']=None
465
466 if self.env['system'] in [ 'Linux', 'FreeBSD']:
467 uname = platform.uname()
468 self.env['build_os'] = self._normalize_os_name(uname[0])
469
470 self.env['build_cpu'] = \
471 self._normalize_cpu_name(uname[4])
472
473 elif self.env['system'] in [ 'Darwin']:
474 uname = platform.uname()
475 self.env['build_os'] = self._normalize_os_name(uname[0])
476 x = uname[4]
477 if self._check_mac_64b():
478 x = 'x86_64'
479 self.env['build_cpu'] = \
480 self._normalize_cpu_name(x)
481 elif self.on_windows():
482 self.env['build_os'] = self._normalize_os_name(os.environ['OS'])
483 if 'PROCESSOR_IDENTIFIER' in os.environ:
484 p = os.environ['PROCESSOR_IDENTIFIER']
485 else:
486 p = self._check_processor_identifier_windows()
487 self.env['build_cpu'] = \
488 self._normalize_cpu_name(p)
489
490 else:
491 die("Unknown platform")
492
493
494
495 self.env['host_cpu'] = self.env['build_cpu']
496 self.env['host_os'] = self.env['build_os']
497
498 self._add_compilation_support()
499
500
501 self._emitted_startup_msg = False
502
503 mbuild_env_defaults = dict(
504 args = [],
505 mbuild_version=False,
506 jobs='4',
507 build_dir='obj',
508 src_dir='',
509 gen_dir=None,
510 verbose= -1,
511 arg_host_cpu=None,
512 arg_host_os=None,
513 compiler=self.default_compiler(),
514 debug=False,
515 shared=False,
516 static=False,
517 opt='noopt',
518 silent=False,
519 extra_defines=[],
520 extra_flags=[],
521 extra_cxxflags=[],
522 extra_ccflags=[],
523 extra_linkflags=[],
524 extra_libs=[],
525 toolchain='',
526 ignorable_files=[],
527 required_files=[],
528 vc_dir='',
529 msvs_version='',
530 setup_msvc=False,
531 icc_version='',
532 gcc_version='',
533 cc='',
534 cxx='',
535 linker='',
536 ar='',
537
538 use_yasm=False,
539 cygwin_limit_jobs=True
540 )
541
542
543 mbuild_env_defaults['as']=''
544
545
546 self.env_defaults = mbuild_env_defaults
547
548 self.update_dict(mbuild_env_defaults)
549
550 self.parser = optparse.OptionParser()
551
552 self.parser.set_defaults(**mbuild_env_defaults)
553
554 if default_knobs:
555 self.add_common_knobs()
556 self.add_default_knobs()
557
558
560 if self.added_common_knobs:
561 return
562 self.added_common_knobs=True
563 self.parser.add_option(
564 "-j", "--jobs",
565 dest="jobs",
566 action="store",
567 help="Number of concurrent worker threads to use.")
568
570 if self.added_default_knobs:
571 return
572 self.added_default_knobs=True
573 self.parser.add_option(
574 "--mbuild-version",
575 dest="mbuild_version",
576 action="store_true",
577 help="Emit the version information")
578 self.parser.add_option(
579 "--build-dir",
580 dest="build_dir",
581 action="store",
582 help="Build directory, default is 'obj'")
583 self.parser.add_option(
584 "--src-dir",
585 action="store",
586 dest="src_dir",
587 help="The directory where the sources are located.")
588 self.parser.add_option(
589 "--gen-dir",
590 action="store",
591 dest="gen_dir",
592 help="The directory where generated sources are assumed" +
593 " to be located.")
594 self.parser.add_option(
595 "-v",
596 "--verbose",
597 action="store",
598 dest="verbose",
599 help="Verbosity level. Defaults to value passed to env_t()")
600 self.parser.add_option(
601 "--compiler",
602 dest="compiler",
603 action="store",
604 help="Compiler (ms,gnu,clang,icc,icl,iclang)." +
605 " Default is gnu on linux and" +
606 " ms on windows. Default is: %s" % (self.default_compiler()))
607 self.parser.add_option(
608 "--debug",
609 dest="debug",
610 action="store_true",
611 help="Debug build")
612 self.parser.add_option(
613 "--shared",
614 dest="shared",
615 action="store_true",
616 help="Shared DLL build")
617 self.parser.add_option(
618 "--static",
619 dest="static",
620 action="store_true",
621 help="Statically link executables")
622 self.parser.add_option(
623 "--opt",
624 dest="opt",
625 action="store",
626 help="Optimization level noopt, 0, 1, 2, 3")
627 self.parser.add_option(
628 "-s",
629 "--silent",
630 dest="silent",
631 action="store_true",
632 help="Silence all but the most important messages")
633 self.parser.add_option(
634 "--extra-defines",
635 dest="extra_defines",
636 action="append",
637 help="Extra preprocessor defines")
638 self.parser.add_option(
639 "--extra-flags",
640 dest="extra_flags",
641 action="append",
642 help="Extra values for CXXFLAGS and CCFLAGS")
643 self.parser.add_option(
644 "--extra-cxxflags",
645 dest="extra_cxxflags",
646 action="append",
647 help="Extra values for CXXFLAGS")
648 self.parser.add_option(
649 "--extra-ccflags",
650 dest="extra_ccflags",
651 action="append",
652 help="Extra values for CCFLAGS")
653 self.parser.add_option(
654 "--extra-linkflags",
655 dest="extra_linkflags",
656 action="append",
657 help="Extra values for LINKFLAGS")
658 self.parser.add_option(
659 "--extra-libs",
660 dest="extra_libs",
661 action="append",
662 help="Extra values for LIBS")
663 self.parser.add_option(
664 "--toolchain",
665 dest="toolchain",
666 action="store",
667 help="Compiler toolchain")
668 self.parser.add_option(
669 "--vc-dir",
670 dest="vc_dir",
671 action="store",
672 help="MSVS Compiler VC directory. For finding libraries " +
673 " and setting the toolchain")
674 self.parser.add_option(
675 '--msvs-version',
676 '--msvc-version',
677 '--msvsversion',
678 '--msvcversion',
679 dest='msvs_version',
680 action='store',
681 help="MSVS version 6=VC98, 7=VS .Net 2003, 8=VS 2005," +
682 " 9=VS 2008, 10=VS 2010/DEV10, 11=VS2012/DEV11" +
683 "This sets certain flags and idioms for quirks in some compilers.")
684 self.parser.add_option(
685 '--setup-msvc',
686 '--setup-msvs',
687 '--msvs-setup',
688 '--msvc-setup',
689 dest='setup_msvc',
690 action='store_true',
691 help="Use the value of the --msvc-version to initialize" +
692 " the MSVC configuration.")
693 self.parser.add_option(
694 '--icc-version',
695 '--iccver',
696 '--icc-ver',
697 dest='icc_version',
698 action='store',
699 help="ICC/ICL version 7, 8, 9, 10, 11")
700 self.parser.add_option(
701 '--gcc-version',
702 '--gccversion',
703 '--gcc-ver',
704 dest='gcc_version',
705 action='store',
706 help="GCC version, with dots as in 2.96, 3.4.3, 4.2.0, etc. ")
707
708 self.parser.add_option(
709 "--cc",
710 dest="cc",
711 action="store",
712 help="full path to C compiler")
713 self.parser.add_option(
714 "--cxx",
715 dest="cxx",
716 action="store",
717 help="full path to C++ compiler")
718 self.parser.add_option(
719 "--linker",
720 dest="linker",
721 action="store",
722 help="full path to linker")
723 self.parser.add_option(
724 "--ar",
725 dest="ar",
726 action="store",
727 help="full path to archiver (lib/ar)")
728 self.parser.add_option(
729 "--as",
730 dest="as",
731 action="store",
732 help="full path to assembler (gas/as/ml/ml64)")
733
734 self.parser.add_option(
735 "--yasm",
736 dest="use_yasm",
737 action="store_true",
738 help="Use yasm")
739 self.parser.add_option(
740 "--no-cygwin-limit",
741 dest="cygwin_limit_jobs",
742 action="store_false",
743 help="Do not limit cygwin to one job at a time. " +
744 " Default is to limit cygwin to one job.")
745
746 self.parser.add_option(
747 "--host-cpu",
748 dest="arg_host_cpu",
749 action="store",
750 help="Host CPU, typically ia32, intel64 or x86-64")
751
752 self.parser.add_option(
753 "--host-os",
754 dest="arg_host_os",
755 action="store",
756 help="Host OS (where the binary runs)")
757
759 """If one of the icc_version, gcc_version_ or msvs_version
760 variables are set, deduce the compiler variable setting."""
761
762
763 if dct['icc_version'] != '':
764 if self.on_windows():
765 dct['compiler'] = 'icl'
766 else:
767 dct['compiler'] = 'icc'
768 if dct['gcc_version'] != '':
769 dct['compiler'] = 'gnu'
770
772 """How many CPUs on a mac"""
773
774 cmd = "/usr/sbin/sysctl hw.ncpu"
775 (retval,output, error_output) = util.run_command(cmd)
776 if retval == 0 and len(output)>0:
777 if re.match('hw.ncpu', output[0]):
778 n = int(re.sub('hw.ncpu: ','',output[0]))
779 return n
780 return 0
781
783 """Return the number of CPUs or 0 if we don't know anything for sure"""
784 n = 0
785 if self.on_mac():
786 n = self._check_mac_ncpu()
787 elif self.on_windows():
788 ns = "NUMBER_OF_PROCESSORS"
789 if ns in os.environ:
790 nsv = os.environ[ns]
791 else:
792 nsv = self._check_number_of_processors_windows()
793 n = int(nsv)
794 elif self.on_freebsd():
795 getconf = "/usr/bin/getconf"
796 if os.path.exists(getconf):
797 cmd = "%s NPROCESSORS_ONLN" % (getconf)
798 (retval, output, error_output) = util.run_command(cmd)
799 if retval == 0 and len(output)>0:
800 n = int(output[0])
801 else:
802 f = '/proc/cpuinfo'
803 proc_pat= re.compile(r'proces')
804 if os.path.exists(f):
805 for line in file(f).readlines():
806 if proc_pat.search(line):
807 n += 1
808 return n
809
811 """Update the environment dictionary with another dictionary."""
812 self.env.update(dct)
813
815
816 """Update the environment dictionary with elements of kwds
817 from the dictionary in the incoming_env. Lists are extended with the
818 incoming elements and other types of elements are assigned directly.
819
820 @type incoming_env: env_t
821 @param incoming_env: the source environment
822
823 @type kwds: list of strings
824 @param kwds: elements to copy from the source enviornment
825
826 @type replace: bool
827 @param replace: if True, replace lists in the source environment
828 """
829 for k in kwds:
830 if k in incoming_env:
831 t = incoming_env[k]
832 if isinstance(t,types.ListType) and replace==False:
833 self.env[k].extend(t)
834 else:
835 self.env[k] = t
836 else:
837 die("copy_settings() could not read key %s from incoming environment" % k)
838
839 - def update(self, targets=None):
840 """Post process the current environment, setting targets and bindings"""
841
842
843
844
845 if targets == None:
846 targets = []
847
848 if not isinstance(targets,types.ListType):
849 die("The 'targets' environment option must be a list")
850
851 if 'args' in self.env:
852 args = self.env['args']
853 if isinstance(args,types.ListType):
854 targets.extend(args)
855 else:
856 die("The 'args' environment option must be a list")
857
858
859
860 just_targets = []
861 bindings = []
862 for t in targets:
863 ap = env_t.assignment_pattern.match(t)
864 if ap:
865 msgb("BINDING", "%s --> [%s]" %
866 (ap.group('name'), ap.group('value')))
867 bindings.append( (ap.group('name'),
868 ap.group('value'), 'equals' ))
869 continue
870 sp = env_t.supplement_pattern.match(t)
871 if ap:
872 msgb("BINDING", "%s --> [%s]" %
873 (ap.group('name'), ap.group('value')))
874 bindings.append( (ap.group('name'),
875 ap.group('value'), 'plusequals') )
876 continue
877 just_targets.append(t)
878
879
880 for (var,value, how) in bindings:
881 if how == 'equals':
882 self.env[var] = value
883
884
885
886
887 if var == 'target_cpu':
888 self.env['host_cpu'] = value
889
890 elif how == 'plusequals':
891 self.add_to_var(var,value)
892
893
894
895 if self.env['arg_host_cpu']:
896 self.env['host_cpu'] = self.env['arg_host_cpu']
897 if self.env['arg_host_os']:
898 self.env['host_os'] = self.env['arg_host_os']
899
900
901
902
903
904 self.env['host_cpu'] = self._normalize_cpu_name(self.env['host_cpu'])
905 self.env['host_os'] = self._normalize_os_name(self.env['host_os'])
906 self.add_to_var('targets',just_targets)
907
908
909
910
911
912
913
914
915 if self.env['target_cpu']:
916 if self.env['target_cpu'] != self.env['host_cpu']:
917
918
919 if self.env['build_cpu'] == self.env['host_cpu']:
920 self.env['host_cpu'] = self.env['target_cpu']
921
922
924 """Set the initial derived environment settings"""
925
926 self.update()
927
928 if self.env['mbuild_version']:
929 self.version()
930 sys.exit(0)
931
932 self._implied_compiler(self.env)
933
934 if self.env['silent']:
935 set_verbosity(0)
936 else:
937 arg_verbosity = int(self.env['verbose'])
938 if arg_verbosity >= 0:
939 set_verbosity( arg_verbosity )
940 self.verbose_startup()
941
942
943 for f in ['extra_cxxflags', 'extra_ccflags', 'extra_linkflags',
944 'extra_libs', 'extra_flags']:
945 self._flatten_list_to_string(f,self.env)
946
947 if self.env['extra_flags']:
948 self.env['extra_cxxflags'] += ' ' + self.env['extra_flags']
949 self.env['extra_ccflags'] += ' ' + self.env['extra_flags']
950
951
952 self.set_compiler_env()
953
954
955
956
957
958
959 if self.env['src_dir'] == '':
960 (path_to_src, this_file) = os.path.split(sys.argv[0])
961 if path_to_src == '':
962 path_to_src = '.'
963 self.env['src_dir'] = util.posix_slashes(path_to_src)
964
965
966
967 if self.on_windows():
968 try:
969 import win32api
970 except:
971 if self.env['cygwin_limit_jobs'] and self.on_cygwin():
972 msgb('NOTE',
973 'Using just one worker thread to avoid' + \
974 ' a cygwin threading problem.')
975 self.env['jobs'] = "1"
976
977
978 if self.env['jobs'] == '0':
979 n = self.number_of_cpus()
980 if n:
981 self.env['jobs'] = str(2*n)
982 msgb('NOTE',
983 'Setting jobs to %d, 2x the detected number of CPUs (%d)' %
984 (2*n,n))
985 else:
986 self.env['jobs'] = "1"
987 msgb('NOTE',
988 'Setting jobs to 1 because we could not detect' +
989 ' the number of CPUs')
990
991 if verbose(1):
992
993
994 msgb("HOST_CPU", self.env['host_cpu'])
995
996
997
998
1000 """See if options has a field named field. If it does and its
1001 value is a list, flatten the list, joining the substrings with
1002 spaces."""
1003 if field in dct:
1004 v = dct[field]
1005 if isinstance(v,types.ListType):
1006 vflat = ' '.join(v)
1007 dct[field]= vflat
1008
1010
1011 """Take the dictionary of defaults and apply to the
1012 environment. Any extra bindings and targets should be listed
1013 in the 'args' list option of the dictionary"""
1014
1015 self.parser.set_defaults(**dct)
1016 self.update_dict(dct)
1017
1018
1019
1020 - def parse_args(self, user_default_options=None):
1021 """Call this to re-initialize the environment from the command
1022 line arguments. This calls update() with the results of
1023 command line processing.
1024 @type user_default_options: dict
1025 @param user_default_options: dictionary of default options
1026 """
1027
1028
1029
1030
1031 if self.parsed_args:
1032 return
1033 self.parsed_args=True
1034
1035 if user_default_options:
1036
1037
1038
1039 self.parser.set_defaults(**user_default_options)
1040
1041 (options, args) = self.parser.parse_args()
1042 dct = vars(options)
1043 dct['args'].extend(args)
1044 self.update_dict(dct)
1045
1046 self.process_user_settings()
1047
1048
1050 """@rtype: bool
1051 @return: True iff on IA64"""
1052 if self.env['build_cpu'] == 'ipf':
1053 return True
1054 return False
1055
1057 """@rtype: bool
1058 @return: True iff on IA32"""
1059 if self.env['build_cpu'] == 'ia32':
1060 return True
1061 return False
1062
1064 """@rtype: bool
1065 @return: True iff on Intel64"""
1066 if self.env['build_cpu'] == 'x86-64':
1067 return True
1068 return False
1069
1071 """@rtype: bool
1072 @return: True iff on Mac OSX Darwin"""
1073 if self.env['system'] == 'Darwin':
1074 return True
1075 return False
1076
1078 if self.on_mac():
1079 ver = platform.mac_ver()[0]
1080 (maj,min,rev) = ver.split('.')
1081 return (int(maj),int(min),int(rev))
1082 return None
1083
1085 """@rtype: bool
1086 @return: True iff on a mac and the version is later than x.y.z"""
1087 if self.on_mac():
1088 (maj,min,rev) = self.mac_ver()
1089 if x > maj:
1090 return False
1091 if x == maj and y > min:
1092 return False
1093 if x == maj and y == min and z > rev:
1094 return False
1095 return True
1096 return False
1097
1099 """@rtype: bool
1100 @return: True iff on Mac running OS X Tiger 10.4.x"""
1101 if self.check_mac_ver(10,4,0):
1102 return True
1103 return False
1105 """@rtype: bool
1106 @return: True iff on Mac running OS X Leopard 10.5.x"""
1107 if self.check_mac_ver(10,5,0):
1108 return True
1109 return False
1110
1112 """@rtype: bool
1113 @return: True iff on freebsd"""
1114 if self.env['system'] == 'FreeBSD':
1115 return True
1116 return False
1117
1119 """@rtype: bool
1120 @return: True iff on linux"""
1121 if self.env['system'] == 'Linux':
1122 return True
1123 return False
1124
1126 """@rtype: bool
1127 @return: True iff on cygwin"""
1128 if len(self.env['system']) >= 6 and self.env['system'][0:6] == 'CYGWIN':
1129 return True
1130 return False
1131
1133 """@rtype: bool
1134 @return: True iff on windows native -- not using cygwin"""
1135 if self.env['system'] == 'Windows' or self.env['system'] == 'Microsoft':
1136 return True
1137 return False
1138
1140 """@rtype: bool
1141 @return: True iff on windows"""
1142 if self.windows_native():
1143 return True
1144 return self.on_cygwin()
1145
1147 """Return True if system supports AVX1. Does not work
1148 on windows"""
1149 if self.on_linux():
1150 lines = file('/proc/cpuinfo').readlines()
1151 for l in lines:
1152 if 'avx' in l:
1153 return True
1154 elif self.on_mac():
1155 cmd = "/usr/sbin/sysctl hw.optional.avx1_0"
1156 (retval, output, error_output) = util.run_command(cmd)
1157 if retval == 0 and len(output)>0:
1158 if re.match('hw.optional.avx1_0: 1', output[0]):
1159 return True
1160
1161
1162 return False
1163
1165 """Check to see if a mac is 64b"""
1166
1167 cmd = "/usr/sbin/sysctl hw.optional.x86_64"
1168 (retval,output, error_output) = util.run_command(cmd)
1169 if retval == 0 and len(output)>0:
1170 if re.match('hw.optional.x86_64: 1', output[0]):
1171 return True
1172 return False
1173
1175 """Internal function. Standardize various CPU identifiers"""
1176 if name in ['ia32', 'i386', 'i686','x86']:
1177 return 'ia32'
1178 elif name in ['ia32e', 'x86_64', 'amd64',
1179 'x86-64', 'Intel64','intel64']:
1180 return 'x86-64'
1181 elif name == 'ia64':
1182 return 'ipf'
1183 elif name[0:5] == 'EM64T':
1184 return 'x86-64'
1185 elif name[0:7] == 'Intel64':
1186 return 'x86-64'
1187 elif name == 'intel64':
1188 return 'x86-64'
1189 elif name[0:3] == 'x86':
1190 return 'ia32'
1191 else:
1192 die("Unknown cpu " + name)
1193
1195 """Internal function. Standardize various O/S identifiers"""
1196 if name in ['android']:
1197 return 'android'
1198 elif name in ['lin', 'Linux']:
1199 return 'lin'
1200 elif name in ['mac', 'Darwin']:
1201 return 'mac'
1202 elif name in ['bsd', 'FreeBSD']:
1203 return 'bsd'
1204 elif name[0:6] == 'CYGWIN':
1205 return 'win'
1206 elif name in ['win', 'Windows_NT']:
1207 return 'win'
1208 else:
1209 die("Unknown os " + name)
1210
1212 """Default to ms on windows and gnu everywhere else.
1213 @rtype: string
1214 @returns: "ms" on windows, "clang" on mac, otherwise "gnu"
1215 """
1216 if self.on_windows():
1217 return "ms"
1218 if self.on_mac():
1219 return "clang"
1220 return "gnu"
1221
1223 """Initialize the build environment based on the compiler
1224 environment variable setting.
1225
1226 Adds in the "extra" flags from the environment.
1227
1228 @type compiler_family: string
1229 @param compiler_family: an override for the default
1230 compiler family (gnu, ms, clang, icl, icc, iclang)
1231 """
1232
1233
1234
1235
1236
1237 if self.env['cxx'] != '':
1238 self.env['CXX'] = self.env['cxx']
1239 if self.env['cc'] != '':
1240 self.env['CC'] = self.env['cc']
1241 if self.env['linker'] != '':
1242 self.env['LINK'] = self.env['linker']
1243 if self.env['ar'] != '':
1244 self.env['AR'] = self.env['ar']
1245 if self.env['as'] != '':
1246 self.env['AS'] = self.env['as']
1247
1248 if compiler_family == None:
1249 if 'compiler' in self.env:
1250 self.env['compiler'] = self.env['compiler'].lower()
1251 compiler_family = self.env['compiler']
1252 else:
1253 die("Compiler family not specified in the environment or as an argument")
1254
1255 if compiler_family == 'gnu':
1256 build_env.set_env_gnu(self)
1257 elif compiler_family == 'clang':
1258 build_env.set_env_clang(self)
1259 elif compiler_family == 'ms':
1260 build_env.set_env_ms(self)
1261 elif compiler_family == 'icc':
1262 build_env.set_env_icc(self)
1263 elif compiler_family == 'iclang':
1264 build_env.set_env_iclang(self)
1265 elif compiler_family == 'icl':
1266 build_env.set_env_icl(self)
1267 else:
1268 die("Compiler family not recognized. Need gnu or ms")
1269
1270 if self.env['use_yasm']:
1271 if verbose(1):
1272 msgb("USE YASM")
1273 build_env.yasm_support(self)
1274
1275 self.add_to_var('CXXFLAGS', self.env['extra_cxxflags'])
1276 self.add_to_var('CCFLAGS', self.env['extra_ccflags'] )
1277 self.add_to_var('LINKFLAGS', self.env['extra_linkflags'] )
1278 self.add_to_var('LIBS', self.env['extra_libs'] )
1279 for d in self.env['extra_defines']:
1280 self.add_define(d)
1281
1283 """Replace the suffix of single fn (or list of files) with
1284 newext. newext should supply its own dot if you want one.
1285 @type fn: string (or list of strings)
1286 @param fn: a filename
1287 @type newext: string
1288 @param newext: a new extension starting with a '.'
1289 @rtype: string
1290 @return: fn with a new suffix specified by newext
1291 """
1292 if isinstance(fn,types.ListType):
1293 return map(lambda(x): self.resuffix(x,newext), fn)
1294 else:
1295 (root,ext) = os.path.splitext(fn)
1296 return root + newext
1297
1299 """Add newstring to front of the environment variable osenv if given
1300 if not given add to os.environ """
1301 environ = os.environ
1302 if osenv:
1303 environ = osenv
1304
1305 if self.on_windows():
1306 sep = ';'
1307 else:
1308 sep = ':'
1309 if evar in environ:
1310
1311 environ[evar]= newstring + sep + environ[evar]
1312 else:
1313
1314 environ[evar]= newstring
1315
1317 path = os.environ['PATH']
1318 if self.on_freebsd() or self.on_linux() or self.on_cygwin():
1319 sep = ':'
1320 else:
1321 sep = ';'
1322 for p in path.split(sep):
1323 t = util.prefix_files(p,exe)
1324 if os.path.exists(t):
1325 return t
1326 return None
1327
1328
1330 """Take file or list of files and return a file or list of
1331 files with the OBJEXT extension from the environment.
1332 @type flist: string or list of strings
1333 @param flist: a filename (or list of filenames)
1334 @rtype: string
1335 @return: fn with a suffix specified %(OBJEXT)s
1336 """
1337 return self.resuffix(flist,"%(OBJEXT)s")
1338
1339
1341 """Make the file (or list of files) with the build
1342 directory name.
1343
1344 @type files: string or list of strings
1345 @param files: filename(s)
1346
1347 @rtype: string or list of strings
1348 @return: filenames prepended with the current build_dir
1349 """
1350
1351
1352 try:
1353 objdir = self.env['build_dir']
1354 except:
1355 die("build_dir not defined in build_dir_join")
1356 if objdir == '':
1357 return files
1358 return util.prefix_files(objdir, files)
1359
1361 """Prefix file (or list of files) with the src directory name.
1362 @type files: string or list of strings
1363 @param files: filename(s)
1364
1365 @rtype: string or list of strings
1366 @return: filenames prepended with the current src_dir
1367 """
1368
1369 try:
1370 srcdir = self.env['src_dir']
1371 except:
1372 die("src_dir not defined in src_dir_join")
1373 if srcdir == '':
1374 return files
1375 return util.prefix_files(srcdir, files)
1376
1378 """Add a define or list defines to the CXXFLAGS and CCFLAGS
1379 @type newdef: string or list of strings
1380 @param newdef: string to add to the CXXFLAGS and CCFLAGS
1381 environment variables.
1382 """
1383 self.add_cc_define(newdef)
1384 self.add_cxx_define(newdef)
1385 self.add_as_define(newdef)
1386
1388 for d in dlist:
1389 if d not in self.env['DEFINES']:
1390 self.env['DEFINES'][d]=True
1391
1393 """Add a define or list defines to the ASFLAGS
1394 @type newdef: string or list of strings
1395 @param newdef: string to add to the ASFLAGS
1396 environment variable.
1397 """
1398 if isinstance(newdef,types.ListType):
1399 deflist = newdef
1400 else:
1401 deflist = [ newdef ]
1402 self._collect_defines(deflist)
1403 for d in deflist:
1404 self.add_to_var('ASFLAGS', "%(ASDOPT)s" + d )
1405
1407 """Add a define or list defines to the CCFLAGS
1408 @type newdef: string or list of strings
1409 @param newdef: string to add to the CCFLAGS
1410 environment variable.
1411 """
1412 if isinstance(newdef,types.ListType):
1413 deflist = newdef
1414 else:
1415 deflist = [ newdef ]
1416 self._collect_defines(deflist)
1417
1418 for d in deflist:
1419 self.add_to_var('CCFLAGS', "%(DOPT)s" + d )
1420
1422 """Add a define or list defines to the CXXFLAGS
1423 @type newdef: string or list of strings
1424 @param newdef: string to add to the CXXFLAGS
1425 environment variable.
1426 """
1427 if isinstance(newdef,types.ListType):
1428 deflist = newdef
1429 else:
1430 deflist = [ newdef ]
1431 self._collect_defines(deflist)
1432 for d in deflist:
1433 self.add_to_var('CXXFLAGS', "%(DOPT)s" + d )
1434
1435
1437 """Add a directory or list of directories to the CPPPATH. Just
1438 a short cut for adding things to the list of files in the
1439 env['CPPPATH']
1440 @type include_dir: string or list of strings
1441 @param include_dir: string to add to the CPPPATH environment variable
1442 """
1443 if isinstance(include_dir,types.ListType):
1444 lst = include_dir
1445 else:
1446 lst = [ include_dir ]
1447 for d in lst:
1448 p = util.posix_slashes(d)
1449 if p not in self.env['CPPPATH']:
1450 self.env['CPPPATH'].append(p)
1451
1453 """Add a directory or list of directories to the SYSTEMINCLUDE. Just
1454 a short cut for adding things to the list of files in the
1455 env['SYSTEMINCLUDE']
1456 @type sys_include_dir: string or list of strings
1457 @param sys_include_dir: string to add to the SYSTEMINCLUDE environment variable
1458 """
1459 if isinstance(sys_include_dir,types.ListType):
1460 lst = sys_include_dir
1461 else:
1462 lst = [ sys_include_dir ]
1463 for d in lst:
1464 p = util.posix_slashes(d)
1465 if p not in self.env['SYSTEMINCLUDE']:
1466 self.env['SYSTEMINCLUDE'].append(p)
1467
1469 """Add a directory or list of directories to the LINKPATH. These
1470 get included in the LINKFLAGS
1471
1472 @type link_dir: string or list of strings
1473 @param link_dir: string to add to the LINKPATH variable
1474 """
1475 if isinstance(link_dir,types.ListType):
1476 for d in link_dir:
1477 self.env['LINKPATH'].append(util.posix_slashes(d))
1478 else:
1479 self.env['LINKPATH'].append(util.posix_slashes(link_dir))
1480
1481
1483 """Remove a substring (or list entry) from env[var]. Opposite
1484 of add_to_var().
1485
1486 @type var: string
1487 @param var: name of a dictionary key
1488 @type value: string
1489 @param value: the value to remove
1490 """
1491 if var in self.env:
1492 if isinstance(self.env[var], types.ListType):
1493 try:
1494 self.env[var].remove(value)
1495 except:
1496 pass
1497 else:
1498 self.env[var] = re.sub(value,'',self.env[var])
1499
1500
1502 """Add or append value to the environment variable var. If the
1503 variable is not in the environment, then it is added as
1504 is. Otherwise if the variable is in the environment and is a
1505 list then value is appended. Otherwise, the value is appended
1506 as a string with a leading space. This will *NOT* do variable
1507 substitution when adding to a variable.
1508
1509 @type var: string
1510 @param var: name of a dictionary key
1511 @type value: string
1512 @param value: the value to add or append
1513
1514 """
1515 if var not in self.env:
1516 self.env[var] = value
1517 elif isinstance(self.env[var],types.ListType):
1518 if isinstance(value, types.ListType):
1519 self.env[var].extend(value)
1520 else:
1521 self.env[var].append(value)
1522 else:
1523 self.env[var] += ' ' + value
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1541 s = "%(CC)s %(CPPINCLUDES)s %(SYSINCLUDES)s %(CCFLAGS)s %(COPT)s %(COUT)s%(OBJNAME)s %(SRCNAME)s"
1542 return s
1543
1545 s = "%(AS)s %(CPPINCLUDES)s %(SYSINCLUDES)s %(ASFLAGS)s %(ASMOUT)s%(OBJNAME)s %(SRCNAME)s"
1546 return s
1547
1549 s = "%(CXX)s %(CPPINCLUDES)s %(SYSINCLUDES)s %(CXXFLAGS)s %(COPT)s %(COUT)s%(OBJNAME)s %(SRCNAME)s"
1550 return s
1551
1553 s = "%(LINK)s %(LINKFLAGS)s %(LINKOUT)s%(EXENAME)s %(OBJNAMES)s %(LIBS)s"
1554 return s
1555
1557 s = [ _remove_libname,
1558 "%(AR)s %(ARFLAGS)s %(LIBOUT)s%(LIBNAME)s %(OBJNAMES)s" ]
1559 return s
1560
1562 s = "%(LINK)s %(LINKFLAGS)s %(DLLOPT)s %(LIBOUT)s%(LIBNAME)s %(OBJNAMES)s %(LIBS)s"
1563 return s
1564
1566 s = "%(CXX)s %(LINKFLAGS)s %(DLLOPT)s %(COUT)s%(LIBNAME)s %(OBJNAMES)s %(LIBS)s"
1567 return s
1568
1570 s = "%(RC)s %(RCFLAGS)s /fo%(RESNAME)s %(RCNAME)s"
1571 return s
1572
1574 """Private. Part of initialization for the environment. Sets
1575 the default builders"""
1576
1577
1578 self.env['ASSEMBLE_BUILDER'] = None
1579 self.env['CXX_COMPILE_BUILDER'] = None
1580 self.env['CC_COMPILE_BUILDER'] = None
1581 self.env['LINK_BUILDER'] = None
1582 self.env['STATIC_LIBRARY_BUILDER'] = None
1583 self.env['DYNAMIC_LIBRARY_BUILDER'] = None
1584 self.env['RES_FILE_BUILDER'] = None
1585
1587 """Private. Part of initialization for the environment. Sets
1588 the default templates used by the default builders"""
1589 self.env['CC_COMPILE_COMMAND'] = self._add_c_compile()
1590 self.env['CXX_COMPILE_COMMAND'] = self._add_cxx_compile()
1591 self.env['ASSEMBLE_COMMAND'] = self._add_assemble()
1592 self.env['LINK_COMMAND'] = self._add_link()
1593 self.env['STATIC_LIB_COMMAND'] = self._add_static_lib()
1594 self.env['DYNAMIC_LIB_COMMAND'] = self._add_dynamic_lib()
1595 self.env['CXX_SHARED_LIB_COMMAND'] = self._add_cxx_shared_lib()
1596 self.env['RES_FILE_COMMAND'] = self._add_res_file_cmd()
1597
1599 """Private. Part of initialization for the environment. Sets
1600 the default builders and templates."""
1601 self._add_default_builders()
1602 self._add_default_builder_templates()
1603
1611 n = []
1612 for s in sl:
1613 n.append(self.escape_string(s))
1614 return n
1615
1617 s = []
1618
1619 iopt = self.env['IOPT']
1620
1621 for p in self.env['CPPPATH']:
1622 s.extend([iopt, self.escape_string(p), ' '])
1623 return ''.join(s)
1624
1626 s = []
1627 iopt = self.env['ISYSOPT']
1628 for p in self.env['SYSTEMINCLUDE']:
1629 s.extend([iopt, self.escape_string(p), ' '])
1630 return ''.join(s)
1631
1633 s = []
1634 lopt = self.env['LOPT']
1635 for p in self.env['LINKPATH']:
1636 s.extend([lopt, self.escape_string(p), ' '])
1637 return ''.join(s)
1638
1640 self.env['CPPINCLUDES'] = self._make_cpp_include()
1642 self.env['SYSINCLUDES'] = self._make_system_include()
1644 self.env['LINKDIRS'] = self._make_link_dirs()
1645
1647 """Put together any derived flags. This is required to be
1648 called by builder functions before they do their expansion.
1649 """
1650
1651 self._make_cpp_flags()
1652 self._make_sys_include_flags()
1653 self._make_link_flags()
1654
1655
1656
1658 """Indirection function. Reads builder function from the
1659 environment variable ASSEMBLER_BUILDER. Assemble a source file
1660 to the obj file. If no obj file name is given one will be
1661 created in the build directory.
1662 @type source: string
1663 @param source: filename to assemble
1664
1665 @type obj: string
1666 @param obj: output filename.
1667
1668 @rtype: L{plan_t}
1669 @return: an input for the DAG
1670 """
1671
1672 new_source = os.path.abspath(source)
1673
1674 f= self.env['ASSEMBLE_BUILDER']
1675 if f:
1676 return f(new_source,obj)
1677 return self._assemble_default(new_source,obj)
1678
1680 """Indirection function. Reads builder function from the
1681 environment variable CXX_COMPILE_BUILDER. C++-compile a source
1682 file to a file called obj. If no obj file name is given one
1683 will be created in the build directory.
1684 @type source: string
1685 @param source: filename to compile
1686
1687 @type obj: string
1688 @param obj: output filename.
1689
1690 @rtype: L{plan_t}
1691 @return: an input for the DAG
1692 """
1693
1694 new_source = os.path.abspath(source)
1695
1696 f = self.env['CXX_COMPILE_BUILDER']
1697 if f:
1698 return f(new_source,obj)
1699 return self._cxx_compile_default(new_source,obj)
1700
1702 """Indirection function. Reads builder function from the
1703 environment variable CC_COMPILE_BUILDER. C-compile a source
1704 file to a file named obj. If no obj file name is given one
1705 will be created in the build directory.
1706 @type source: string
1707 @param source: filename to compile
1708
1709 @type obj: string
1710 @param obj: output filename.
1711
1712 @rtype: L{plan_t}
1713 @return: an input for the DAG
1714 """
1715
1716
1717 new_source = os.path.abspath(source)
1718
1719 f = self.env['CC_COMPILE_BUILDER']
1720 if f:
1721 return f(new_source,obj)
1722 return self._cc_compile_default(new_source,obj)
1723
1724 - def link(self, objs, exename, relocate=False):
1725 """Indirection function. Reads builder function from the
1726 environment variable LINK_BUILDER. Link an executable from
1727 objs. If relocate is True, then prefix exename with the build
1728 directory name.
1729 @type objs: list of strings
1730 @param objs: filenames to link
1731
1732 @type exename: string
1733 @param exename: output filename.
1734
1735 @type relocate: bool
1736 @param relocate: If true, relocate the exename to the build directory.
1737
1738 @rtype: L{plan_t}
1739 @return: an input for the DAG
1740
1741 """
1742 f = self.env['LINK_BUILDER']
1743 if f:
1744 return f(objs,exename, relocate)
1745 return self._link_default(objs,exename,relocate)
1746
1747 - def static_lib(self, objs, libname, relocate=False):
1748 """Indirection function. Reads builder function from the
1749 environment variable STATIC_LIBRARY_BUILDER. Make a static
1750 library libname from objs. If relocate is True, then prefix
1751 libname with the build directory name
1752
1753 @type objs: list of strings
1754 @param objs: filenames to link
1755
1756 @type libname: string
1757 @param libname: output filename.
1758
1759 @type relocate: bool
1760 @param relocate: If true, relocate the library to the build directory.
1761
1762 @rtype: L{plan_t}
1763 @return: an input for the DAG
1764
1765
1766 """
1767 f = self.env['STATIC_LIBRARY_BUILDER']
1768 if f:
1769 return f(objs,libname, relocate)
1770 return self._static_lib_default(objs,libname,relocate)
1771
1773 """Build all the sources by adding them to the dag. Use the
1774 suffixes to figure out how to handle the files. The dag can be
1775 passed to a work queue. See the build function. """
1776
1777
1778 objs = self.compile(dag, sources)
1779
1780
1781 dag.add(self, self.static_lib(objs, libname, relocate=True))
1782
1785
1787 if self.on_windows():
1788 s = '{}%(DLLEXT)s'.format(base)
1789 else:
1790 s = 'lib{}%(DLLEXT)s'.format(base)
1791 return s
1793 if self.on_windows():
1794 s = '{}%(LIBEXT)s'.format(base)
1795 else:
1796 s = 'lib{}%(LIBEXT)s'.format(base)
1797 return s
1798
1799 - def dynamic_lib(self, objs, libname, relocate=False):
1800 """Indirection function. Reads builder function from the
1801 environment variable DYNAMIC_LIBRARY_BUILDER. Make a dynamic
1802 library libname from objs. If relocate is True, then prefix
1803 libname with the build directory name
1804
1805 @type objs: list of strings
1806 @param objs: filenames to link
1807
1808 @type libname: string
1809 @param libname: output filename.
1810
1811 @type relocate: bool
1812 @param relocate: If true, relocate the library to the build directory.
1813
1814 @rtype: L{plan_t}
1815 @return: an input for the DAG
1816
1817 """
1818 f = self.env['DYNAMIC_LIBRARY_BUILDER']
1819 if f:
1820 return f(objs,libname, relocate)
1821 return self._dynamic_lib_default(objs,libname,relocate)
1822
1823
1824 - def rc_file(self, rc_file, res_file=None):
1825 """Indirection function. For making RES files
1826 from RC files on windows.
1827
1828 @type rc_file: string
1829 @param rc_file: filename for RC file
1830
1831 @type res_file: string
1832 @param res_file: filename for RES file
1833
1834 """
1835 f = self.env['RES_FILE_BUILDER']
1836 if f:
1837 return f(rc_file, res_file)
1838 return self._res_file_builder_default(rc_file, res_file)
1839
1841 file_name_keys = ['SRCNAME','OBJNAME', 'LIBNAME',
1842 'SOLIBNAME', 'EXENAME',
1843 'RCNAME', 'RESNAME' ]
1844 for k in file_name_keys:
1845 if k in d:
1846 d[k] = self.escape_string(d[k])
1847
1849 """Assemble a source file to the obj file. If no obj file name
1850 is given one will be created in the build directory."""
1851 cmd = self.env['ASSEMBLE_COMMAND']
1852 d = copy.copy(self)
1853 self.make_derived_flags()
1854 d['SRCNAME'] = source
1855 if obj == None:
1856 (filepath,fullfilename) = os.path.split(source)
1857 (filename,ext) = os.path.splitext(fullfilename)
1858 obj = filename + self.env['OBJEXT']
1859 obj = self.build_dir_join(obj)
1860 d['OBJNAME'] = obj
1861 self._escape_dict(d)
1862 s = self.expand_string(cmd, d)
1863 return plan.plan_t(command=s, output=obj, input=source)
1864
1866 """If obj obj file ends in '.obj$' or '%(OBJEXT)s' replace it
1867 so it looks like: '%(PDBEXT)s'"""
1868
1869 if env_t.obj_pattern.search(obj):
1870 pdbfile = env_t.obj_pattern.sub('%(PDBEXT)s',obj)
1871 elif env_t.objext_pattern.search(obj):
1872 pdbfile = env_t.objext_pattern.sub('%(PDBEXT)s',obj)
1873 else:
1874 die("Could not make PDB file from OBJ file: %s" % obj)
1875 return pdbfile
1876
1878 """C++-compile a source file to a file called obj. If no obj file
1879 name is given one will be created in the build directory."""
1880 cmd = self.env['CXX_COMPILE_COMMAND']
1881 d = copy.copy(self)
1882 self.make_derived_flags()
1883 d['SRCNAME'] = source
1884 if obj == None:
1885 (filepath,fullfilename) = os.path.split(source)
1886 (filename,ext) = os.path.splitext(fullfilename)
1887 obj = filename + self.env['OBJEXT']
1888 obj = self.build_dir_join(obj)
1889 if d['separate_pdb_files'] and d['compiler'] == 'ms' and d['debug'] == 1:
1890 pdbfile = self._make_pdb_file(obj)
1891 d['CXXFLAGS'] += ' /Fd%s ' % pdbfile
1892
1893 d['OBJNAME'] = obj
1894 self._escape_dict(d)
1895 s = self.expand_string(cmd, d)
1896 return plan.plan_t(command=s, output=obj, input=source)
1897
1898
1900 """C-compile a source file to a file named obj. If no obj file
1901 name is given one will be created in the build directory."""
1902
1903 cmd = self.env['CC_COMPILE_COMMAND']
1904 d = copy.copy(self)
1905 self.make_derived_flags()
1906 d['SRCNAME'] = source
1907 if obj == None:
1908 (filepath,fullfilename) = os.path.split(source)
1909 (filename,ext) = os.path.splitext(fullfilename)
1910 obj = filename + self.env['OBJEXT']
1911 obj = self.build_dir_join(obj)
1912 if d['separate_pdb_files'] and d['compiler'] == 'ms' and d['debug'] == 1:
1913 pdbfile = self._make_pdb_file(obj)
1914 d['CCFLAGS'] += ' /Fd%s ' % pdbfile
1915
1916 d['OBJNAME'] = obj
1917 self._escape_dict(d)
1918 s = self.expand_string(cmd, d)
1919 return plan.plan_t(command=s, output=obj, input=source)
1920
1922 libs = []
1923 for lib in self.expand_string('%(LIBS)s').split():
1924 if lib:
1925
1926
1927
1928 if lib[0]=='-':
1929 continue
1930 if os.path.exists(lib):
1931
1932 libs.append(lib)
1933 else:
1934 for dir in self.env['LINKPATH']:
1935 t = mbuild.join(dir,lib)
1936 if os.path.exists(t):
1937
1938 libs.append(t)
1939 return libs
1940
1941
1943 """Link an executable from objs. If relocate is True,
1944 then prefix exename with the build directory name."""
1945 cmd = self.env['LINK_COMMAND']
1946 d = copy.copy(self)
1947 self.make_derived_flags()
1948 if relocate:
1949 exename = self.build_dir_join(exename)
1950 d['EXENAME'] = exename
1951
1952 if not isinstance(objs, types.ListType):
1953 objs = [ objs ]
1954 objs = self._escape_list_of_strings(objs)
1955 obj = " ".join(objs)
1956 d['OBJNAMES'] = obj
1957 self._escape_dict(d)
1958 s = self.expand_string(cmd, d)
1959 return plan.plan_t(command=s, output=exename, input=objs + self._find_libs())
1960
1961
1963 """Make a static library libname from objs. If relocate is True,
1964 then prefix libname with the build directory name"""
1965 d = copy.copy(self)
1966 self.make_derived_flags()
1967 if relocate:
1968 libname = self.build_dir_join(libname)
1969 d['LIBNAME'] = libname
1970 if not isinstance(objs,types.ListType):
1971 objs = [ objs ]
1972 objs = self._escape_list_of_strings(objs)
1973 obj = " ".join(objs)
1974
1975 d['OBJNAMES'] = obj
1976 self._escape_dict(d)
1977 n = []
1978 scmd = self.env['STATIC_LIB_COMMAND']
1979 if not isinstance(scmd,types.ListType):
1980 scmd = [ scmd ]
1981 for cmd in scmd:
1982 if isinstance(cmd,types.StringType):
1983 n.append(self.expand_string(cmd, d))
1984 else:
1985 n.append(cmd)
1986
1987
1988 args = [ self.expand_string('%(LIBNAME)s') ]
1989 return plan.plan_t(command=n, output=libname,
1990 args=args,
1991 input=objs, env=self)
1992
1993
1995 """Make a dynamic library libname from objs. If relocate is True,
1996 then prefix libname with the build directory name"""
1997 if self.env['compiler'] in [ 'gnu','icc','clang','iclang']:
1998 cmd = self.env['CXX_SHARED_LIB_COMMAND']
1999 else:
2000 cmd = self.env['DYNAMIC_LIB_COMMAND']
2001 d = copy.copy(self)
2002 self.make_derived_flags()
2003 if relocate:
2004 libname = self.build_dir_join(libname)
2005 d['LIBNAME'] = libname
2006 d['SOLIBNAME'] = os.path.basename(libname)
2007 if not isinstance(objs,types.ListType):
2008 objs = [ objs ]
2009 objs = self._escape_list_of_strings(objs)
2010 obj = " ".join(objs)
2011 d['OBJNAMES'] = obj
2012 self._escape_dict(d)
2013 s = self.expand_string(cmd, d)
2014 return plan.plan_t(command=s, output=libname,
2015 input=objs + self._find_libs())
2016
2017
2018
2020 """Make a res file from an rc file. Windows only."""
2021 cmd = self.env['RES_FILE_COMMAND']
2022 d = copy.copy(self)
2023 if not res_file:
2024 res_file = self.build_dir_join(self.resuffix(rc_file,'%(RESEXT)s'))
2025 d['RESNAME'] = res_file
2026 d['RCNAME'] = rc_file
2027 self._escape_dict(d)
2028 s = self.expand_string(cmd, d)
2029 return plan.plan_t(command=s,
2030 output=res_file,
2031 input=rc_file)
2032
2034 """Build all the sources by adding them to the dag. Use the
2035 suffixes to figure out how to handle the files. The dag can be
2036 passed to a work queue. See the build function. """
2037
2038 objs = []
2039 for s in sources:
2040 b = os.path.basename(s)
2041 (base,ext) = os.path.splitext(b)
2042 if ext in ['.rc' ]:
2043 obj = self.build_dir_join(self.resuffix(b,'%(RESEXT)s'))
2044 else:
2045 obj = self.build_dir_join(self.make_obj(b))
2046
2047 if ext in ['.asm', '.s' ]:
2048 c = self.assemble( s, obj )
2049 elif ext in ['.c']:
2050 c = self.cc_compile( s, obj )
2051 elif ext in ['.cpp', '.C' ]:
2052 c = self.cxx_compile( s, obj )
2053 elif ext in ['.rc' ]:
2054 c = self.rc_file( s, obj )
2055 else:
2056 die("Unsupported file type %s" % (s))
2057 cmd = dag.add(self,c)
2058 objs.append(self.expand_string(obj))
2059 return objs
2060
2061
2063 """Build all the sources by adding them to the dag. Use the
2064 suffixes to figure out how to handle the files. The dag can be
2065 passed to a work queue. See the build function. """
2066
2067 objs = self.compile(dag, sources)
2068
2069 if shared_object:
2070 cmd2 = dag.add(self,
2071 self.dynamic_lib(objs + libs, exe, relocate=True))
2072 else:
2073 cmd2 = dag.add(self,
2074 self.link(objs + libs , exe,relocate=True))
2075 return cmd2
2076
2077
2078 - def build(self, work_queue, dag, phase='BUILD',terminate_on_errors=False):
2079 """Build everything in the work queue"""
2080 okay = work_queue.build(dag=dag, die_on_errors=False)
2081 if not okay:
2082 if terminate_on_errors:
2083 die("[%s] failed." % phase)
2084 else:
2085 msgb(phase,"failed.")
2086 return False
2087 msgb(phase, "succeeded")
2088 return True
2089