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