scons: Do not use linker option '-Bsymbolic' on Mac OS X.
[mesa.git] / scons / gallium.py
1 """gallium
2
3 Frontend-tool for Gallium3D architecture.
4
5 """
6
7 #
8 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
9 # All Rights Reserved.
10 #
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:
18 #
19 # The above copyright notice and this permission notice (including the
20 # next paragraph) shall be included in all copies or substantial portions
21 # of the Software.
22 #
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.
30 #
31
32
33 import distutils.version
34 import os
35 import os.path
36 import re
37 import subprocess
38
39 import SCons.Action
40 import SCons.Builder
41 import SCons.Scanner
42
43
44 def symlink(target, source, env):
45 target = str(target[0])
46 source = str(source[0])
47 if os.path.islink(target) or os.path.exists(target):
48 os.remove(target)
49 os.symlink(os.path.basename(source), target)
50
51 def install(env, source, subdir):
52 target_dir = os.path.join(env.Dir('#.').srcnode().abspath, env['build'], subdir)
53 env.Install(target_dir, source)
54
55 def install_program(env, source):
56 install(env, source, 'bin')
57
58 def install_shared_library(env, sources, version = ()):
59 install_dir = os.path.join(env.Dir('#.').srcnode().abspath, env['build'])
60 version = tuple(map(str, version))
61 if env['SHLIBSUFFIX'] == '.dll':
62 dlls = env.FindIxes(sources, 'SHLIBPREFIX', 'SHLIBSUFFIX')
63 install(env, dlls, 'bin')
64 libs = env.FindIxes(sources, 'LIBPREFIX', 'LIBSUFFIX')
65 install(env, libs, 'lib')
66 else:
67 for source in sources:
68 target_dir = os.path.join(install_dir, 'lib')
69 target_name = '.'.join((str(source),) + version)
70 last = env.InstallAs(os.path.join(target_dir, target_name), source)
71 while len(version):
72 version = version[:-1]
73 target_name = '.'.join((str(source),) + version)
74 action = SCons.Action.Action(symlink, "$TARGET -> $SOURCE")
75 last = env.Command(os.path.join(target_dir, target_name), last, action)
76
77 def createInstallMethods(env):
78 env.AddMethod(install_program, 'InstallProgram')
79 env.AddMethod(install_shared_library, 'InstallSharedLibrary')
80
81
82 def num_jobs():
83 try:
84 return int(os.environ['NUMBER_OF_PROCESSORS'])
85 except (ValueError, KeyError):
86 pass
87
88 try:
89 return os.sysconf('SC_NPROCESSORS_ONLN')
90 except (ValueError, OSError, AttributeError):
91 pass
92
93 try:
94 return int(os.popen2("sysctl -n hw.ncpu")[1].read())
95 except ValueError:
96 pass
97
98 return 1
99
100
101 def generate(env):
102 """Common environment generation code"""
103
104 # Toolchain
105 platform = env['platform']
106 if env['toolchain'] == 'default':
107 if platform == 'winddk':
108 env['toolchain'] = 'winddk'
109 elif platform == 'wince':
110 env['toolchain'] = 'wcesdk'
111 env.Tool(env['toolchain'])
112
113 if os.environ.has_key('CC'):
114 env['CC'] = os.environ['CC']
115
116 env['gcc'] = 'gcc' in os.path.basename(env['CC']).split('-')
117 env['msvc'] = env['CC'] == 'cl'
118
119 # shortcuts
120 debug = env['debug']
121 machine = env['machine']
122 platform = env['platform']
123 x86 = env['machine'] == 'x86'
124 ppc = env['machine'] == 'ppc'
125 gcc = env['gcc']
126 msvc = env['msvc']
127
128 # Put build output in a separate dir, which depends on the current
129 # configuration. See also http://www.scons.org/wiki/AdvancedBuildExample
130 build_topdir = 'build'
131 build_subdir = env['platform']
132 if env['llvm']:
133 build_subdir += "-llvm"
134 if env['machine'] != 'generic':
135 build_subdir += '-' + env['machine']
136 if env['debug']:
137 build_subdir += "-debug"
138 if env['profile']:
139 build_subdir += "-profile"
140 build_dir = os.path.join(build_topdir, build_subdir)
141 # Place the .sconsign file in the build dir too, to avoid issues with
142 # different scons versions building the same source file
143 env['build'] = build_dir
144 env.SConsignFile(os.path.join(build_dir, '.sconsign'))
145 env.CacheDir('build/cache')
146 env['CONFIGUREDIR'] = os.path.join(build_dir, 'conf')
147 env['CONFIGURELOG'] = os.path.join(os.path.abspath(build_dir), 'config.log')
148
149 # Parallel build
150 if env.GetOption('num_jobs') <= 1:
151 env.SetOption('num_jobs', num_jobs())
152
153 # C preprocessor options
154 cppdefines = []
155 if debug:
156 cppdefines += ['DEBUG']
157 else:
158 cppdefines += ['NDEBUG']
159 if env['profile']:
160 cppdefines += ['PROFILE']
161 if platform == 'windows':
162 cppdefines += [
163 'WIN32',
164 '_WINDOWS',
165 #'_UNICODE',
166 #'UNICODE',
167 ('_WIN32_WINNT', '0x0501'), # minimum required OS version
168 ('WINVER', '0x0501'),
169 ]
170 if msvc and env['toolchain'] != 'winddk':
171 cppdefines += [
172 'VC_EXTRALEAN',
173 '_USE_MATH_DEFINES',
174 '_CRT_SECURE_NO_WARNINGS',
175 '_CRT_SECURE_NO_DEPRECATE',
176 '_SCL_SECURE_NO_WARNINGS',
177 '_SCL_SECURE_NO_DEPRECATE',
178 ]
179 if debug:
180 cppdefines += ['_DEBUG']
181 if env['toolchain'] == 'winddk':
182 # Mimic WINDDK's builtin flags. See also:
183 # - WINDDK's bin/makefile.new i386mk.inc for more info.
184 # - buildchk_wxp_x86.log files, generated by the WINDDK's build
185 # - http://alter.org.ua/docs/nt_kernel/vc8_proj/
186 if machine == 'x86':
187 cppdefines += ['_X86_', 'i386']
188 if machine == 'x86_64':
189 cppdefines += ['_AMD64_', 'AMD64']
190 if platform == 'winddk':
191 cppdefines += [
192 'STD_CALL',
193 ('CONDITION_HANDLING', '1'),
194 ('NT_INST', '0'),
195 ('WIN32', '100'),
196 ('_NT1X_', '100'),
197 ('WINNT', '1'),
198 ('_WIN32_WINNT', '0x0501'), # minimum required OS version
199 ('WINVER', '0x0501'),
200 ('_WIN32_IE', '0x0603'),
201 ('WIN32_LEAN_AND_MEAN', '1'),
202 ('DEVL', '1'),
203 ('__BUILDMACHINE__', 'WinDDK'),
204 ('FPO', '0'),
205 ]
206 if debug:
207 cppdefines += [('DBG', 1)]
208 if platform == 'wince':
209 cppdefines += [
210 '_CRT_SECURE_NO_DEPRECATE',
211 '_USE_32BIT_TIME_T',
212 'UNICODE',
213 '_UNICODE',
214 ('UNDER_CE', '600'),
215 ('_WIN32_WCE', '0x600'),
216 'WINCEOEM',
217 'WINCEINTERNAL',
218 'WIN32',
219 'STRICT',
220 'x86',
221 '_X86_',
222 'INTERNATIONAL',
223 ('INTLMSG_CODEPAGE', '1252'),
224 ]
225 if platform == 'windows':
226 cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_USER']
227 if platform == 'winddk':
228 cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_DISPLAY']
229 if platform == 'wince':
230 cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_CE']
231 cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_CE_OGL']
232 env.Append(CPPDEFINES = cppdefines)
233
234 # C compiler options
235 cflags = [] # C
236 cxxflags = [] # C++
237 ccflags = [] # C & C++
238 if gcc:
239 ccversion = ''
240 pipe = SCons.Action._subproc(env, [env['CC'], '--version'],
241 stdin = 'devnull',
242 stderr = 'devnull',
243 stdout = subprocess.PIPE)
244 if pipe.wait() == 0:
245 line = pipe.stdout.readline()
246 match = re.search(r'[0-9]+(\.[0-9]+)+', line)
247 if match:
248 ccversion = match.group(0)
249 if debug:
250 ccflags += ['-O0', '-g3']
251 elif ccversion.startswith('4.2.'):
252 # gcc 4.2.x optimizer is broken
253 print "warning: gcc 4.2.x optimizer is broken -- disabling optimizations"
254 ccflags += ['-O0', '-g3']
255 else:
256 ccflags += ['-O3', '-g3']
257 if env['profile']:
258 # See http://code.google.com/p/jrfonseca/wiki/Gprof2Dot#Which_options_should_I_pass_to_gcc_when_compiling_for_profiling?
259 ccflags += [
260 '-fno-omit-frame-pointer',
261 '-fno-optimize-sibling-calls',
262 ]
263 if env['machine'] == 'x86':
264 ccflags += [
265 '-m32',
266 #'-march=pentium4',
267 #'-mfpmath=sse',
268 ]
269 if platform != 'windows':
270 # XXX: -mstackrealign causes stack corruption on MinGW. Ditto
271 # for -mincoming-stack-boundary=2. Still enable it on other
272 # platforms for now, but we can't rely on it for cross platform
273 # code. We have to use __attribute__((force_align_arg_pointer))
274 # instead.
275 ccflags += [
276 '-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
277 '-mstackrealign', # ensure stack is aligned
278 ]
279 if env['machine'] == 'x86_64':
280 ccflags += ['-m64']
281 # See also:
282 # - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
283 ccflags += [
284 '-Wall',
285 '-Wmissing-field-initializers',
286 '-Wno-long-long',
287 '-ffast-math',
288 '-fmessage-length=0', # be nice to Eclipse
289 ]
290 cflags += [
291 '-Wmissing-prototypes',
292 '-std=gnu99',
293 ]
294 if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2'):
295 ccflags += [
296 '-Werror=pointer-arith',
297 ]
298 cflags += [
299 '-Werror=declaration-after-statement',
300 ]
301 if msvc:
302 # See also:
303 # - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
304 # - cl /?
305 if debug:
306 ccflags += [
307 '/Od', # disable optimizations
308 '/Oi', # enable intrinsic functions
309 '/Oy-', # disable frame pointer omission
310 '/GL-', # disable whole program optimization
311 ]
312 else:
313 ccflags += [
314 '/O2', # optimize for speed
315 '/GL', # enable whole program optimization
316 ]
317 ccflags += [
318 '/fp:fast', # fast floating point
319 '/W3', # warning level
320 #'/Wp64', # enable 64 bit porting warnings
321 ]
322 if env['machine'] == 'x86':
323 ccflags += [
324 #'/arch:SSE2', # use the SSE2 instructions
325 ]
326 if platform == 'windows':
327 ccflags += [
328 # TODO
329 ]
330 if platform == 'winddk':
331 ccflags += [
332 '/Zl', # omit default library name in .OBJ
333 '/Zp8', # 8bytes struct member alignment
334 '/Gy', # separate functions for linker
335 '/Gm-', # disable minimal rebuild
336 '/WX', # treat warnings as errors
337 '/Gz', # __stdcall Calling convention
338 '/GX-', # disable C++ EH
339 '/GR-', # disable C++ RTTI
340 '/GF', # enable read-only string pooling
341 '/G6', # optimize for PPro, P-II, P-III
342 '/Ze', # enable extensions
343 '/Gi-', # disable incremental compilation
344 '/QIfdiv-', # disable Pentium FDIV fix
345 '/hotpatch', # prepares an image for hotpatching.
346 #'/Z7', #enable old-style debug info
347 ]
348 if platform == 'wince':
349 # See also C:\WINCE600\public\common\oak\misc\makefile.def
350 ccflags += [
351 '/Zl', # omit default library name in .OBJ
352 '/GF', # enable read-only string pooling
353 '/GR-', # disable C++ RTTI
354 '/GS', # enable security checks
355 # Allow disabling language conformance to maintain backward compat
356 #'/Zc:wchar_t-', # don't force wchar_t as native type, instead of typedef
357 #'/Zc:forScope-', # don't enforce Standard C++ for scoping rules
358 #'/wd4867',
359 #'/wd4430',
360 #'/MT',
361 #'/U_MT',
362 ]
363 # Automatic pdb generation
364 # See http://scons.tigris.org/issues/show_bug.cgi?id=1656
365 env.EnsureSConsVersion(0, 98, 0)
366 env['PDB'] = '${TARGET.base}.pdb'
367 env.Append(CCFLAGS = ccflags)
368 env.Append(CFLAGS = cflags)
369 env.Append(CXXFLAGS = cxxflags)
370
371 if env['platform'] == 'windows' and msvc:
372 # Choose the appropriate MSVC CRT
373 # http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
374 if env['debug']:
375 env.Append(CCFLAGS = ['/MTd'])
376 env.Append(SHCCFLAGS = ['/LDd'])
377 else:
378 env.Append(CCFLAGS = ['/MT'])
379 env.Append(SHCCFLAGS = ['/LD'])
380
381 # Assembler options
382 if gcc:
383 if env['machine'] == 'x86':
384 env.Append(ASFLAGS = ['-m32'])
385 if env['machine'] == 'x86_64':
386 env.Append(ASFLAGS = ['-m64'])
387
388 # Linker options
389 linkflags = []
390 shlinkflags = []
391 if gcc:
392 if env['machine'] == 'x86':
393 linkflags += ['-m32']
394 if env['machine'] == 'x86_64':
395 linkflags += ['-m64']
396 if env['platform'] not in ('darwin'):
397 shlinkflags += [
398 '-Wl,-Bsymbolic',
399 ]
400 # Handle circular dependencies in the libraries
401 if env['platform'] in ('darwin'):
402 pass
403 else:
404 env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group'
405 if msvc:
406 if not env['debug']:
407 # enable Link-time Code Generation
408 linkflags += ['/LTCG']
409 env.Append(ARFLAGS = ['/LTCG'])
410 if platform == 'windows' and msvc:
411 # See also:
412 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
413 linkflags += [
414 '/fixed:no',
415 '/incremental:no',
416 ]
417 if platform == 'winddk':
418 linkflags += [
419 '/merge:_PAGE=PAGE',
420 '/merge:_TEXT=.text',
421 '/section:INIT,d',
422 '/opt:ref',
423 '/opt:icf',
424 '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
425 '/incremental:no',
426 '/fullbuild',
427 '/release',
428 '/nodefaultlib',
429 '/wx',
430 '/debug',
431 '/debugtype:cv',
432 '/version:5.1',
433 '/osversion:5.1',
434 '/functionpadmin:5',
435 '/safeseh',
436 '/pdbcompress',
437 '/stack:0x40000,0x1000',
438 '/driver',
439 '/align:0x80',
440 '/subsystem:native,5.01',
441 '/base:0x10000',
442
443 '/entry:DrvEnableDriver',
444 ]
445 if env['debug'] or env['profile']:
446 linkflags += [
447 '/MAP', # http://msdn.microsoft.com/en-us/library/k7xkk3e2.aspx
448 ]
449 if platform == 'wince':
450 linkflags += [
451 '/nodefaultlib',
452 #'/incremental:no',
453 #'/fullbuild',
454 '/entry:_DllMainCRTStartup',
455 ]
456 env.Append(LINKFLAGS = linkflags)
457 env.Append(SHLINKFLAGS = shlinkflags)
458
459 # Default libs
460 env.Append(LIBS = [])
461
462 # Custom builders and methods
463 env.Tool('custom')
464 createInstallMethods(env)
465
466 # for debugging
467 #print env.Dump()
468
469
470 def exists(env):
471 return 1