OSDN Git Service

scons: Promote declaration-after-statement to error. Detect more warnings.
[android-x86/external-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 os
34 import os.path
35 import re
36
37 import SCons.Action
38 import SCons.Builder
39 import SCons.Scanner
40
41
42 def quietCommandLines(env):
43     # Quiet command lines
44     # See also http://www.scons.org/wiki/HidingCommandLinesInOutput
45     env['CCCOMSTR'] = "Compiling $SOURCE ..."
46     env['CXXCOMSTR'] = "Compiling $SOURCE ..."
47     env['ARCOMSTR'] = "Archiving $TARGET ..."
48     env['RANLIBCOMSTR'] = ""
49     env['LINKCOMSTR'] = "Linking $TARGET ..."
50
51
52 def createConvenienceLibBuilder(env):
53     """This is a utility function that creates the ConvenienceLibrary
54     Builder in an Environment if it is not there already.
55
56     If it is already there, we return the existing one.
57
58     Based on the stock StaticLibrary and SharedLibrary builders.
59     """
60
61     try:
62         convenience_lib = env['BUILDERS']['ConvenienceLibrary']
63     except KeyError:
64         action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
65         if env.Detect('ranlib'):
66             ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
67             action_list.append(ranlib_action)
68
69         convenience_lib = SCons.Builder.Builder(action = action_list,
70                                   emitter = '$LIBEMITTER',
71                                   prefix = '$LIBPREFIX',
72                                   suffix = '$LIBSUFFIX',
73                                   src_suffix = '$SHOBJSUFFIX',
74                                   src_builder = 'SharedObject')
75         env['BUILDERS']['ConvenienceLibrary'] = convenience_lib
76
77     return convenience_lib
78
79
80 # TODO: handle import statements with multiple modules
81 # TODO: handle from import statements
82 import_re = re.compile(r'^import\s+(\S+)$', re.M)
83
84 def python_scan(node, env, path):
85     # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
86     contents = node.get_contents()
87     source_dir = node.get_dir()
88     imports = import_re.findall(contents)
89     results = []
90     for imp in imports:
91         for dir in path:
92             file = os.path.join(str(dir), imp.replace('.', os.sep) + '.py')
93             if os.path.exists(file):
94                 results.append(env.File(file))
95                 break
96             file = os.path.join(str(dir), imp.replace('.', os.sep), '__init__.py')
97             if os.path.exists(file):
98                 results.append(env.File(file))
99                 break
100     return results
101
102 python_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py'])
103
104
105 def code_generate(env, script, target, source, command):
106     """Method to simplify code generation via python scripts.
107
108     http://www.scons.org/wiki/UsingCodeGenerators
109     http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
110     """
111
112     # We're generating code using Python scripts, so we have to be
113     # careful with our scons elements.  This entry represents
114     # the generator file *in the source directory*.
115     script_src = env.File(script).srcnode()
116
117     # This command creates generated code *in the build directory*.
118     command = command.replace('$SCRIPT', script_src.path)
119     code = env.Command(target, source, command)
120
121     # Explicitly mark that the generated code depends on the generator,
122     # and on implicitly imported python modules
123     path = (script_src.get_dir(),)
124     deps = [script_src]
125     deps += script_src.get_implicit_deps(env, python_scanner, path)
126     env.Depends(code, deps)
127
128     # Running the Python script causes .pyc files to be generated in the
129     # source directory.  When we clean up, they should go too. So add side
130     # effects for .pyc files
131     for dep in deps:
132         pyc = env.File(str(dep) + 'c')
133         env.SideEffect(pyc, code)
134
135     return code
136
137
138 def createCodeGenerateMethod(env):
139     env.Append(SCANNERS = python_scanner)
140     env.AddMethod(code_generate, 'CodeGenerate')
141
142
143 def symlink(target, source, env):
144     target = str(target[0])
145     source = str(source[0])
146     if os.path.islink(target) or os.path.exists(target):
147         os.remove(target)
148     os.symlink(os.path.basename(source), target)
149
150 def install_shared_library(env, source, version = ()):
151     source = str(source[0])
152     version = tuple(map(str, version))
153     target_dir =  os.path.join(env.Dir('#.').srcnode().abspath, env['build'], 'lib')
154     target_name = '.'.join((str(source),) + version)
155     last = env.InstallAs(os.path.join(target_dir, target_name), source)
156     while len(version):
157         version = version[:-1]
158         target_name = '.'.join((str(source),) + version)
159         action = SCons.Action.Action(symlink, "$TARGET -> $SOURCE")
160         last = env.Command(os.path.join(target_dir, target_name), last, action) 
161
162 def createInstallMethods(env):
163     env.AddMethod(install_shared_library, 'InstallSharedLibrary')
164
165
166 def num_jobs():
167     try:
168         return int(os.environ['NUMBER_OF_PROCESSORS'])
169     except (ValueError, KeyError):
170         pass
171
172     try:
173         return os.sysconf('SC_NPROCESSORS_ONLN')
174     except (ValueError, OSError, AttributeError):
175         pass
176
177     try:
178         return int(os.popen2("sysctl -n hw.ncpu")[1].read())
179     except ValueError:
180         pass
181
182     return 1
183
184
185 def generate(env):
186     """Common environment generation code"""
187
188     # FIXME: this is already too late
189     #if env.get('quiet', False):
190     #    quietCommandLines(env)
191
192     # Toolchain
193     platform = env['platform']
194     if env['toolchain'] == 'default':
195         if platform == 'winddk':
196             env['toolchain'] = 'winddk'
197         elif platform == 'wince':
198             env['toolchain'] = 'wcesdk'
199     env.Tool(env['toolchain'])
200
201     # shortcuts
202     debug = env['debug']
203     machine = env['machine']
204     platform = env['platform']
205     x86 = env['machine'] == 'x86'
206     ppc = env['machine'] == 'ppc'
207     gcc = env['platform'] in ('linux', 'freebsd', 'darwin') or env['toolchain'] == 'crossmingw'
208     msvc = env['platform'] in ('windows', 'winddk', 'wince') and env['toolchain'] != 'crossmingw'
209
210     # Put build output in a separate dir, which depends on the current
211     # configuration. See also http://www.scons.org/wiki/AdvancedBuildExample
212     build_topdir = 'build'
213     build_subdir = env['platform']
214     if env['llvm']:
215         build_subdir += "-llvm"
216     if env['machine'] != 'generic':
217         build_subdir += '-' + env['machine']
218     if env['debug']:
219         build_subdir += "-debug"
220     if env['profile']:
221         build_subdir += "-profile"
222     build_dir = os.path.join(build_topdir, build_subdir)
223     # Place the .sconsign file in the build dir too, to avoid issues with
224     # different scons versions building the same source file
225     env['build'] = build_dir
226     env.SConsignFile(os.path.join(build_dir, '.sconsign'))
227     env.CacheDir('build/cache')
228
229     # Parallel build
230     if env.GetOption('num_jobs') <= 1:
231         env.SetOption('num_jobs', num_jobs())
232
233     # C preprocessor options
234     cppdefines = []
235     if debug:
236         cppdefines += ['DEBUG']
237     else:
238         cppdefines += ['NDEBUG']
239     if env['profile']:
240         cppdefines += ['PROFILE']
241     if platform == 'windows':
242         cppdefines += [
243             'WIN32',
244             '_WINDOWS',
245             #'_UNICODE',
246             #'UNICODE',
247             ('_WIN32_WINNT', '0x0501'), # minimum required OS version
248             ('WINVER', '0x0501'),
249             # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx,
250             'WIN32_LEAN_AND_MEAN',
251             'VC_EXTRALEAN',
252             '_CRT_SECURE_NO_DEPRECATE',
253         ]
254         if debug:
255             cppdefines += ['_DEBUG']
256     if platform == 'winddk':
257         # Mimic WINDDK's builtin flags. See also:
258         # - WINDDK's bin/makefile.new i386mk.inc for more info.
259         # - buildchk_wxp_x86.log files, generated by the WINDDK's build
260         # - http://alter.org.ua/docs/nt_kernel/vc8_proj/
261         cppdefines += [
262             ('_X86_', '1'),
263             ('i386', '1'),
264             'STD_CALL',
265             ('CONDITION_HANDLING', '1'),
266             ('NT_INST', '0'),
267             ('WIN32', '100'),
268             ('_NT1X_', '100'),
269             ('WINNT', '1'),
270             ('_WIN32_WINNT', '0x0501'), # minimum required OS version
271             ('WINVER', '0x0501'),
272             ('_WIN32_IE', '0x0603'),
273             ('WIN32_LEAN_AND_MEAN', '1'),
274             ('DEVL', '1'),
275             ('__BUILDMACHINE__', 'WinDDK'),
276             ('FPO', '0'),
277         ]
278         if debug:
279             cppdefines += [('DBG', 1)]
280     if platform == 'wince':
281         cppdefines += [
282             '_CRT_SECURE_NO_DEPRECATE',
283             '_USE_32BIT_TIME_T',
284             'UNICODE',
285             '_UNICODE',
286             ('UNDER_CE', '600'),
287             ('_WIN32_WCE', '0x600'),
288             'WINCEOEM',
289             'WINCEINTERNAL',
290             'WIN32',
291             'STRICT',
292             'x86',
293             '_X86_',
294             'INTERNATIONAL',
295             ('INTLMSG_CODEPAGE', '1252'),
296         ]
297     if platform == 'windows':
298         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_USER']
299     if platform == 'winddk':
300         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_DISPLAY']
301     if platform == 'wince':
302         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_CE']
303         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_CE_OGL']
304     env.Append(CPPDEFINES = cppdefines)
305
306     # C preprocessor includes
307     if platform == 'winddk':
308         env.Append(CPPPATH = [
309             env['SDK_INC_PATH'],
310             env['DDK_INC_PATH'],
311             env['WDM_INC_PATH'],
312             env['CRT_INC_PATH'],
313         ])
314
315     # C compiler options
316     cflags = []
317     if gcc:
318         if debug:
319             cflags += ['-O0', '-g3']
320         else:
321             cflags += ['-O3', '-g3']
322         if env['profile']:
323             cflags += ['-pg']
324         if env['machine'] == 'x86':
325             cflags += [
326                 '-m32',
327                 #'-march=pentium4',
328                 '-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
329                 #'-mfpmath=sse',
330             ]
331         if env['machine'] == 'x86_64':
332             cflags += ['-m64']
333         # See also:
334         # - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
335         cflags += [
336             '-Werror=declaration-after-statement',
337             '-Wall',
338             '-Wmissing-prototypes',
339             '-Wmissing-field-initializers',
340             '-Wpointer-arith',
341             '-Wno-long-long',
342             '-ffast-math',
343             '-std=gnu99',
344             '-fmessage-length=0', # be nice to Eclipse
345         ]
346     if msvc:
347         # See also:
348         # - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
349         # - cl /?
350         if debug:
351             cflags += [
352               '/Od', # disable optimizations
353               '/Oi', # enable intrinsic functions
354               '/Oy-', # disable frame pointer omission
355               '/GL-', # disable whole program optimization
356             ]
357         else:
358             cflags += [
359               '/Ox', # maximum optimizations
360               '/Oi', # enable intrinsic functions
361               '/Ot', # favor code speed
362               #'/fp:fast', # fast floating point 
363             ]
364         if env['profile']:
365             cflags += [
366                 '/Gh', # enable _penter hook function
367                 '/GH', # enable _pexit hook function
368             ]
369         cflags += [
370             '/W3', # warning level
371             #'/Wp64', # enable 64 bit porting warnings
372         ]
373         if env['machine'] == 'x86':
374             cflags += [
375                 #'/QIfist', # Suppress _ftol
376                 #'/arch:SSE2', # use the SSE2 instructions
377             ]
378         if platform == 'windows':
379             cflags += [
380                 # TODO
381             ]
382         if platform == 'winddk':
383             cflags += [
384                 '/Zl', # omit default library name in .OBJ
385                 '/Zp8', # 8bytes struct member alignment
386                 '/Gy', # separate functions for linker
387                 '/Gm-', # disable minimal rebuild
388                 '/WX', # treat warnings as errors
389                 '/Gz', # __stdcall Calling convention
390                 '/GX-', # disable C++ EH
391                 '/GR-', # disable C++ RTTI
392                 '/GF', # enable read-only string pooling
393                 '/G6', # optimize for PPro, P-II, P-III
394                 '/Ze', # enable extensions
395                 '/Gi-', # disable incremental compilation
396                 '/QIfdiv-', # disable Pentium FDIV fix
397                 '/hotpatch', # prepares an image for hotpatching.
398                 #'/Z7', #enable old-style debug info
399             ]
400         if platform == 'wince':
401             # See also C:\WINCE600\public\common\oak\misc\makefile.def
402             cflags += [
403                 '/Zl', # omit default library name in .OBJ
404                 '/GF', # enable read-only string pooling
405                 '/GR-', # disable C++ RTTI
406                 '/GS', # enable security checks
407                 # Allow disabling language conformance to maintain backward compat
408                 #'/Zc:wchar_t-', # don't force wchar_t as native type, instead of typedef
409                 #'/Zc:forScope-', # don't enforce Standard C++ for scoping rules
410                 #'/wd4867',
411                 #'/wd4430',
412                 #'/MT',
413                 #'/U_MT',
414             ]
415         # Automatic pdb generation
416         # See http://scons.tigris.org/issues/show_bug.cgi?id=1656
417         env.EnsureSConsVersion(0, 98, 0)
418         env['PDB'] = '${TARGET.base}.pdb'
419     env.Append(CFLAGS = cflags)
420     env.Append(CXXFLAGS = cflags)
421
422     if env['platform'] == 'windows' and msvc:
423         # Choose the appropriate MSVC CRT
424         # http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
425         if env['debug']:
426             env.Append(CCFLAGS = ['/MTd'])
427             env.Append(SHCCFLAGS = ['/LDd'])
428         else:
429             env.Append(CCFLAGS = ['/MT'])
430             env.Append(SHCCFLAGS = ['/LD'])
431     
432     # Assembler options
433     if gcc:
434         if env['machine'] == 'x86':
435             env.Append(ASFLAGS = ['-m32'])
436         if env['machine'] == 'x86_64':
437             env.Append(ASFLAGS = ['-m64'])
438
439     # Linker options
440     linkflags = []
441     if gcc:
442         if env['machine'] == 'x86':
443             linkflags += ['-m32']
444         if env['machine'] == 'x86_64':
445             linkflags += ['-m64']
446     if platform == 'windows' and msvc:
447         # See also:
448         # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
449         linkflags += [
450             '/fixed:no',
451             '/incremental:no',
452         ]
453     if platform == 'winddk':
454         linkflags += [
455             '/merge:_PAGE=PAGE',
456             '/merge:_TEXT=.text',
457             '/section:INIT,d',
458             '/opt:ref',
459             '/opt:icf',
460             '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
461             '/incremental:no',
462             '/fullbuild',
463             '/release',
464             '/nodefaultlib',
465             '/wx',
466             '/debug',
467             '/debugtype:cv',
468             '/version:5.1',
469             '/osversion:5.1',
470             '/functionpadmin:5',
471             '/safeseh',
472             '/pdbcompress',
473             '/stack:0x40000,0x1000',
474             '/driver',
475             '/align:0x80',
476             '/subsystem:native,5.01',
477             '/base:0x10000',
478
479             '/entry:DrvEnableDriver',
480         ]
481         if env['debug'] or env['profile']:
482             linkflags += [
483                 '/MAP', # http://msdn.microsoft.com/en-us/library/k7xkk3e2.aspx
484             ]
485     if platform == 'wince':
486         linkflags += [
487             '/nodefaultlib',
488             #'/incremental:no',
489             #'/fullbuild',
490             '/entry:_DllMainCRTStartup',
491         ]
492     env.Append(LINKFLAGS = linkflags)
493
494     # Default libs
495     env.Append(LIBS = [])
496
497     # Custom builders and methods
498     createConvenienceLibBuilder(env)
499     createCodeGenerateMethod(env)
500     createInstallMethods(env)
501
502     # for debugging
503     #print env.Dump()
504
505
506 def exists(env):
507     return 1