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