3 Generic tool that provides a commmon ground for all platforms.
8 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
11 # Permission is hereby granted, free of charge, to any person obtaining a
12 # copy of this software and associated documentation files (the
13 # "Software"), to deal in the Software without restriction, including
14 # without limitation the rights to use, copy, modify, merge, publish,
15 # distribute, sub license, and/or sell copies of the Software, and to
16 # permit persons to whom the Software is furnished to do so, subject to
17 # the following conditions:
19 # The above copyright notice and this permission notice (including the
20 # next paragraph) shall be included in all copies or substantial portions
23 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
26 # IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
27 # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 import platform
as _platform
44 def quietCommandLines(env
):
46 # See also http://www.scons.org/wiki/HidingCommandLinesInOutput
47 env
['CCCOMSTR'] = "Compiling $SOURCE ..."
48 env
['CXXCOMSTR'] = "Compiling $SOURCE ..."
49 env
['ARCOMSTR'] = "Archiving $TARGET ..."
50 env
['RANLIBCOMSTR'] = ""
51 env
['LINKCOMSTR'] = "Linking $TARGET ..."
54 def createConvenienceLibBuilder(env
):
55 """This is a utility function that creates the ConvenienceLibrary
56 Builder in an Environment if it is not there already.
58 If it is already there, we return the existing one.
60 Based on the stock StaticLibrary and SharedLibrary builders.
64 convenience_lib
= env
['BUILDERS']['ConvenienceLibrary']
66 action_list
= [ SCons
.Action
.Action("$ARCOM", "$ARCOMSTR") ]
67 if env
.Detect('ranlib'):
68 ranlib_action
= SCons
.Action
.Action("$RANLIBCOM", "$RANLIBCOMSTR")
69 action_list
.append(ranlib_action
)
71 convenience_lib
= SCons
.Builder
.Builder(action
= action_list
,
72 emitter
= '$LIBEMITTER',
73 prefix
= '$LIBPREFIX',
74 suffix
= '$LIBSUFFIX',
75 src_suffix
= '$SHOBJSUFFIX',
76 src_builder
= 'SharedObject')
77 env
['BUILDERS']['ConvenienceLibrary'] = convenience_lib
79 return convenience_lib
82 # TODO: handle import statements with multiple modules
83 # TODO: handle from import statements
84 import_re
= re
.compile(r
'^import\s+(\S+)$', re
.M
)
86 def python_scan(node
, env
, path
):
87 # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
88 contents
= node
.get_contents()
89 source_dir
= node
.get_dir()
90 imports
= import_re
.findall(contents
)
94 file = os
.path
.join(str(dir), imp
.replace('.', os
.sep
) + '.py')
95 if os
.path
.exists(file):
96 results
.append(env
.File(file))
98 file = os
.path
.join(str(dir), imp
.replace('.', os
.sep
), '__init__.py')
99 if os
.path
.exists(file):
100 results
.append(env
.File(file))
104 python_scanner
= SCons
.Scanner
.Scanner(function
= python_scan
, skeys
= ['.py'])
107 def code_generate(env
, script
, target
, source
, command
):
108 """Method to simplify code generation via python scripts.
110 http://www.scons.org/wiki/UsingCodeGenerators
111 http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
114 # We're generating code using Python scripts, so we have to be
115 # careful with our scons elements. This entry represents
116 # the generator file *in the source directory*.
117 script_src
= env
.File(script
).srcnode()
119 # This command creates generated code *in the build directory*.
120 command
= command
.replace('$SCRIPT', script_src
.path
)
121 code
= env
.Command(target
, source
, command
)
123 # Explicitly mark that the generated code depends on the generator,
124 # and on implicitly imported python modules
125 path
= (script_src
.get_dir(),)
127 deps
+= script_src
.get_implicit_deps(env
, python_scanner
, path
)
128 env
.Depends(code
, deps
)
130 # Running the Python script causes .pyc files to be generated in the
131 # source directory. When we clean up, they should go too. So add side
132 # effects for .pyc files
134 pyc
= env
.File(str(dep
) + 'c')
135 env
.SideEffect(pyc
, code
)
140 def createCodeGenerateMethod(env
):
141 env
.Append(SCANNERS
= python_scanner
)
142 env
.AddMethod(code_generate
, 'CodeGenerate')
145 def symlink(target
, source
, env
):
146 target
= str(target
[0])
147 source
= str(source
[0])
148 if os
.path
.islink(target
) or os
.path
.exists(target
):
150 os
.symlink(os
.path
.basename(source
), target
)
152 def install_shared_library(env
, source
, version
= ()):
153 source
= str(source
[0])
154 version
= tuple(map(str, version
))
155 target_dir
= os
.path
.join(env
.Dir('#.').srcnode().abspath
, env
['build'], 'lib')
156 target_name
= '.'.join((str(source
),) + version
)
157 last
= env
.InstallAs(os
.path
.join(target_dir
, target_name
), source
)
159 version
= version
[:-1]
160 target_name
= '.'.join((str(source
),) + version
)
161 action
= SCons
.Action
.Action(symlink
, "$TARGET -> $SOURCE")
162 last
= env
.Command(os
.path
.join(target_dir
, target_name
), last
, action
)
164 def createInstallMethods(env
):
165 env
.AddMethod(install_shared_library
, 'InstallSharedLibrary')
210 """Common environment generation code"""
212 from SCons
.Script
import ARGUMENTS
214 # FIXME: this is already too late
215 #if env.get('quiet', False):
216 # quietCommandLines(env)
221 env
['platform'] = ARGUMENTS
['platform']
223 env
['platform'] = _platform_map
.get(sys
.platform
, sys
.platform
)
227 env
['machine'] = ARGUMENTS
['machine']
229 env
['machine'] = _machine_map
.get(os
.environ
.get('PROCESSOR_ARCHITECTURE', _platform
.machine()), 'generic')
233 env
['toolchain'] = ARGUMENTS
['toolchain']
235 if env
['platform'] in ('windows', 'winddk', 'wince') and sys
.platform
!= 'win32':
236 env
['toolchain'] = 'crossmingw'
238 env
['toolchain'] = _toolchain_map
.get(env
['platform'], 'default')
239 if env
['toolchain'] == 'crossmingw' and env
['machine'] not in ('generic', 'x86'):
240 env
['machine'] = 'x86'
243 env
['debug'] = _bool_map
[ARGUMENTS
.get('debug', 'no')]
244 env
['profile'] = _bool_map
[ARGUMENTS
.get('profile', 'no')]
246 # Put build output in a separate dir, which depends on the current
247 # configuration. See also http://www.scons.org/wiki/AdvancedBuildExample
249 env
['variant_dir'] = ARGUMENTS
['variant_dir']
251 build_topdir
= 'build'
252 build_subdir
= env
['platform']
253 if env
['machine'] != 'generic':
254 build_subdir
+= '-' + env
['machine']
256 build_subdir
+= "-debug"
258 build_subdir
+= "-profile"
259 env
['variant_dir'] = os
.path
.join(build_topdir
, build_subdir
)
260 # Place the .sconsign file in the build dir too, to avoid issues with
261 # different scons versions building the same source file
262 #env.VariantDir(env['variant_dir']
263 #env.SConsignFile(os.path.join(env['variant_dir'], '.sconsign'))
267 print ' platform=%s' % env
['platform']
268 print ' machine=%s' % env
['machine']
269 print ' toolchain=%s' % env
['toolchain']
270 print ' debug=%s' % ['no', 'yes'][env
['debug']]
271 print ' profile=%s' % ['no', 'yes'][env
['profile']]
272 #print ' variant_dir=%s' % env['variant_dir']
276 env
.Tool(env
['toolchain'])
280 machine
= env
['machine']
281 platform
= env
['platform']
282 x86
= env
['machine'] == 'x86'
283 ppc
= env
['machine'] == 'ppc'
284 gcc
= env
['platform'] in ('linux', 'freebsd', 'darwin') or env
['toolchain'] == 'crossmingw'
285 msvc
= env
['platform'] in ('windows', 'winddk', 'wince') and env
['toolchain'] != 'crossmingw'
287 # C preprocessor options
290 cppdefines
+= ['DEBUG']
292 cppdefines
+= ['NDEBUG']
294 cppdefines
+= ['PROFILE']
295 if platform
== 'windows':
301 # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx,
302 'WIN32_LEAN_AND_MEAN',
304 '_CRT_SECURE_NO_DEPRECATE',
307 cppdefines
+= ['_DEBUG']
308 if platform
== 'winddk':
309 # Mimic WINDDK's builtin flags. See also:
310 # - WINDDK's bin/makefile.new i386mk.inc for more info.
311 # - buildchk_wxp_x86.log files, generated by the WINDDK's build
312 # - http://alter.org.ua/docs/nt_kernel/vc8_proj/
317 ('CONDITION_HANDLING', '1'),
322 ('_WIN32_WINNT', '0x0501'), # minimum required OS version
323 ('WINVER', '0x0501'),
324 ('_WIN32_IE', '0x0603'),
325 ('WIN32_LEAN_AND_MEAN', '1'),
327 ('__BUILDMACHINE__', 'WinDDK'),
331 cppdefines
+= [('DBG', 1)]
332 if platform
== 'wince':
334 '_CRT_SECURE_NO_DEPRECATE',
339 ('_WIN32_WCE', '0x600'),
347 ('INTLMSG_CODEPAGE', '1252'),
349 env
.Append(CPPDEFINES
= cppdefines
)
351 # C preprocessor includes
352 if platform
== 'winddk':
353 env
.Append(CPPPATH
= [
364 cflags
+= ['-O0', '-g3']
366 cflags
+= ['-O3', '-g0']
369 if env
['machine'] == 'x86':
373 '-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
376 if env
['machine'] == 'x86_64':
380 '-Wmissing-prototypes',
384 '-fmessage-length=0', # be nice to Eclipse
388 # - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
392 '/Od', # disable optimizations
393 '/Oi', # enable intrinsic functions
394 '/Oy-', # disable frame pointer omission
398 '/Ox', # maximum optimizations
399 '/Oi', # enable intrinsic functions
400 '/Ot', # favor code speed
401 #'/fp:fast', # fast floating point
405 '/Gh', # enable _penter hook function
406 '/GH', # enable _pexit hook function
409 '/W3', # warning level
410 #'/Wp64', # enable 64 bit porting warnings
412 if env
['machine'] == 'x86':
414 #'/QIfist', # Suppress _ftol
415 #'/arch:SSE2', # use the SSE2 instructions
417 if platform
== 'windows':
421 if platform
== 'winddk':
423 '/Zl', # omit default library name in .OBJ
424 '/Zp8', # 8bytes struct member alignment
425 '/Gy', # separate functions for linker
426 '/Gm-', # disable minimal rebuild
427 '/WX', # treat warnings as errors
428 '/Gz', # __stdcall Calling convention
429 '/GX-', # disable C++ EH
430 '/GR-', # disable C++ RTTI
431 '/GF', # enable read-only string pooling
432 '/G6', # optimize for PPro, P-II, P-III
433 '/Ze', # enable extensions
434 '/Gi-', # disable incremental compilation
435 '/QIfdiv-', # disable Pentium FDIV fix
436 '/hotpatch', # prepares an image for hotpatching.
437 #'/Z7', #enable old-style debug info
439 if platform
== 'wince':
440 # See also C:\WINCE600\public\common\oak\misc\makefile.def
442 '/Zl', # omit default library name in .OBJ
443 '/GF', # enable read-only string pooling
444 '/GR-', # disable C++ RTTI
445 '/GS', # enable security checks
446 # Allow disabling language conformance to maintain backward compat
447 #'/Zc:wchar_t-', # don't force wchar_t as native type, instead of typedef
448 #'/Zc:forScope-', # don't enforce Standard C++ for scoping rules
454 # Automatic pdb generation
455 # See http://scons.tigris.org/issues/show_bug.cgi?id=1656
456 env
.EnsureSConsVersion(0, 98, 0)
457 env
['PDB'] = '${TARGET.base}.pdb'
458 env
.Append(CFLAGS
= cflags
)
459 env
.Append(CXXFLAGS
= cflags
)
463 if env
['machine'] == 'x86':
464 env
.Append(ASFLAGS
= ['-m32'])
465 if env
['machine'] == 'x86_64':
466 env
.Append(ASFLAGS
= ['-m64'])
471 if env
['machine'] == 'x86':
472 linkflags
+= ['-m32']
473 if env
['machine'] == 'x86_64':
474 linkflags
+= ['-m64']
475 if platform
== 'winddk':
477 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
480 '/merge:_TEXT=.text',
484 '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
497 '/stack:0x40000,0x1000',
500 '/subsystem:native,5.01',
503 '/entry:DrvEnableDriver',
507 '/MAP', # http://msdn.microsoft.com/en-us/library/k7xkk3e2.aspx
509 if platform
== 'wince':
514 '/entry:_DllMainCRTStartup',
516 env
.Append(LINKFLAGS
= linkflags
)
519 env
.Append(LIBS
= [])
521 # Custom builders and methods
522 createConvenienceLibBuilder(env
)
523 createCodeGenerateMethod(env
)
524 createInstallMethods(env
)