Merge commit 'origin/perrtblend'
[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 if platform == 'embedded':
233 cppdefines += ['PIPE_SUBSYSTEM_EMBEDDED']
234 env.Append(CPPDEFINES = cppdefines)
235
236 # C compiler options
237 cflags = [] # C
238 cxxflags = [] # C++
239 ccflags = [] # C & C++
240 if gcc:
241 ccversion = ''
242 pipe = SCons.Action._subproc(env, [env['CC'], '--version'],
243 stdin = 'devnull',
244 stderr = 'devnull',
245 stdout = subprocess.PIPE)
246 if pipe.wait() == 0:
247 line = pipe.stdout.readline()
248 match = re.search(r'[0-9]+(\.[0-9]+)+', line)
249 if match:
250 ccversion = match.group(0)
251 if debug:
252 ccflags += ['-O0', '-g3']
253 elif ccversion.startswith('4.2.'):
254 # gcc 4.2.x optimizer is broken
255 print "warning: gcc 4.2.x optimizer is broken -- disabling optimizations"
256 ccflags += ['-O0', '-g3']
257 else:
258 ccflags += ['-O3', '-g3']
259 if env['profile']:
260 # See http://code.google.com/p/jrfonseca/wiki/Gprof2Dot#Which_options_should_I_pass_to_gcc_when_compiling_for_profiling?
261 ccflags += [
262 '-fno-omit-frame-pointer',
263 '-fno-optimize-sibling-calls',
264 ]
265 if env['machine'] == 'x86':
266 ccflags += [
267 '-m32',
268 #'-march=pentium4',
269 #'-mfpmath=sse',
270 ]
271 if platform != 'windows':
272 # XXX: -mstackrealign causes stack corruption on MinGW. Ditto
273 # for -mincoming-stack-boundary=2. Still enable it on other
274 # platforms for now, but we can't rely on it for cross platform
275 # code. We have to use __attribute__((force_align_arg_pointer))
276 # instead.
277 ccflags += [
278 '-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
279 '-mstackrealign', # ensure stack is aligned
280 ]
281 if env['machine'] == 'x86_64':
282 ccflags += ['-m64']
283 # See also:
284 # - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
285 ccflags += [
286 '-Wall',
287 '-Wmissing-field-initializers',
288 '-Wno-long-long',
289 '-ffast-math',
290 '-fmessage-length=0', # be nice to Eclipse
291 ]
292 cflags += [
293 '-Wmissing-prototypes',
294 '-std=gnu99',
295 ]
296 if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2'):
297 ccflags += [
298 '-Werror=pointer-arith',
299 ]
300 cflags += [
301 '-Werror=declaration-after-statement',
302 ]
303 if msvc:
304 # See also:
305 # - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
306 # - cl /?
307 if debug:
308 ccflags += [
309 '/Od', # disable optimizations
310 '/Oi', # enable intrinsic functions
311 '/Oy-', # disable frame pointer omission
312 '/GL-', # disable whole program optimization
313 ]
314 else:
315 ccflags += [
316 '/O2', # optimize for speed
317 '/GL', # enable whole program optimization
318 ]
319 ccflags += [
320 '/fp:fast', # fast floating point
321 '/W3', # warning level
322 #'/Wp64', # enable 64 bit porting warnings
323 ]
324 if env['machine'] == 'x86':
325 ccflags += [
326 #'/arch:SSE2', # use the SSE2 instructions
327 ]
328 if platform == 'windows':
329 ccflags += [
330 # TODO
331 ]
332 if platform == 'winddk':
333 ccflags += [
334 '/Zl', # omit default library name in .OBJ
335 '/Zp8', # 8bytes struct member alignment
336 '/Gy', # separate functions for linker
337 '/Gm-', # disable minimal rebuild
338 '/WX', # treat warnings as errors
339 '/Gz', # __stdcall Calling convention
340 '/GX-', # disable C++ EH
341 '/GR-', # disable C++ RTTI
342 '/GF', # enable read-only string pooling
343 '/G6', # optimize for PPro, P-II, P-III
344 '/Ze', # enable extensions
345 '/Gi-', # disable incremental compilation
346 '/QIfdiv-', # disable Pentium FDIV fix
347 '/hotpatch', # prepares an image for hotpatching.
348 #'/Z7', #enable old-style debug info
349 ]
350 if platform == 'wince':
351 # See also C:\WINCE600\public\common\oak\misc\makefile.def
352 ccflags += [
353 '/Zl', # omit default library name in .OBJ
354 '/GF', # enable read-only string pooling
355 '/GR-', # disable C++ RTTI
356 '/GS', # enable security checks
357 # Allow disabling language conformance to maintain backward compat
358 #'/Zc:wchar_t-', # don't force wchar_t as native type, instead of typedef
359 #'/Zc:forScope-', # don't enforce Standard C++ for scoping rules
360 #'/wd4867',
361 #'/wd4430',
362 #'/MT',
363 #'/U_MT',
364 ]
365 # Automatic pdb generation
366 # See http://scons.tigris.org/issues/show_bug.cgi?id=1656
367 env.EnsureSConsVersion(0, 98, 0)
368 env['PDB'] = '${TARGET.base}.pdb'
369 env.Append(CCFLAGS = ccflags)
370 env.Append(CFLAGS = cflags)
371 env.Append(CXXFLAGS = cxxflags)
372
373 if env['platform'] == 'windows' and msvc:
374 # Choose the appropriate MSVC CRT
375 # http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
376 if env['debug']:
377 env.Append(CCFLAGS = ['/MTd'])
378 env.Append(SHCCFLAGS = ['/LDd'])
379 else:
380 env.Append(CCFLAGS = ['/MT'])
381 env.Append(SHCCFLAGS = ['/LD'])
382
383 # Assembler options
384 if gcc:
385 if env['machine'] == 'x86':
386 env.Append(ASFLAGS = ['-m32'])
387 if env['machine'] == 'x86_64':
388 env.Append(ASFLAGS = ['-m64'])
389
390 # Linker options
391 linkflags = []
392 shlinkflags = []
393 if gcc:
394 if env['machine'] == 'x86':
395 linkflags += ['-m32']
396 if env['machine'] == 'x86_64':
397 linkflags += ['-m64']
398 if env['platform'] not in ('darwin'):
399 shlinkflags += [
400 '-Wl,-Bsymbolic',
401 ]
402 # Handle circular dependencies in the libraries
403 if env['platform'] in ('darwin'):
404 pass
405 else:
406 env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group'
407 if msvc:
408 if not env['debug']:
409 # enable Link-time Code Generation
410 linkflags += ['/LTCG']
411 env.Append(ARFLAGS = ['/LTCG'])
412 if platform == 'windows' and msvc:
413 # See also:
414 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
415 linkflags += [
416 '/fixed:no',
417 '/incremental:no',
418 ]
419 if platform == 'winddk':
420 linkflags += [
421 '/merge:_PAGE=PAGE',
422 '/merge:_TEXT=.text',
423 '/section:INIT,d',
424 '/opt:ref',
425 '/opt:icf',
426 '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
427 '/incremental:no',
428 '/fullbuild',
429 '/release',
430 '/nodefaultlib',
431 '/wx',
432 '/debug',
433 '/debugtype:cv',
434 '/version:5.1',
435 '/osversion:5.1',
436 '/functionpadmin:5',
437 '/safeseh',
438 '/pdbcompress',
439 '/stack:0x40000,0x1000',
440 '/driver',
441 '/align:0x80',
442 '/subsystem:native,5.01',
443 '/base:0x10000',
444
445 '/entry:DrvEnableDriver',
446 ]
447 if env['debug'] or env['profile']:
448 linkflags += [
449 '/MAP', # http://msdn.microsoft.com/en-us/library/k7xkk3e2.aspx
450 ]
451 if platform == 'wince':
452 linkflags += [
453 '/nodefaultlib',
454 #'/incremental:no',
455 #'/fullbuild',
456 '/entry:_DllMainCRTStartup',
457 ]
458 env.Append(LINKFLAGS = linkflags)
459 env.Append(SHLINKFLAGS = shlinkflags)
460
461 # Default libs
462 env.Append(LIBS = [])
463
464 # Custom builders and methods
465 env.Tool('custom')
466 createInstallMethods(env)
467
468 # for debugging
469 #print env.Dump()
470
471
472 def exists(env):
473 return 1