OSDN Git Service

Merge commit 'origin/master' into gallium-0.2
[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 generate(env):
167     """Common environment generation code"""
168
169     # FIXME: this is already too late
170     #if env.get('quiet', False):
171     #    quietCommandLines(env)
172
173     # Toolchain
174     platform = env['platform']
175     if env['toolchain'] == 'default':
176         if platform == 'winddk':
177             env['toolchain'] = 'winddk'
178         elif platform == 'wince':
179             env['toolchain'] = 'wcesdk'
180     env.Tool(env['toolchain'])
181
182     # shortcuts
183     debug = env['debug']
184     machine = env['machine']
185     platform = env['platform']
186     x86 = env['machine'] == 'x86'
187     ppc = env['machine'] == 'ppc'
188     gcc = env['platform'] in ('linux', 'freebsd', 'darwin') or env['toolchain'] == 'crossmingw'
189     msvc = env['platform'] in ('windows', 'winddk', 'wince') and env['toolchain'] != 'crossmingw'
190
191     # Put build output in a separate dir, which depends on the current
192     # configuration. See also http://www.scons.org/wiki/AdvancedBuildExample
193     build_topdir = 'build'
194     build_subdir = env['platform']
195     if env['dri']:
196         build_subdir += "-dri"
197     if env['llvm']:
198         build_subdir += "-llvm"
199     if env['machine'] != 'generic':
200         build_subdir += '-' + env['machine']
201     if env['debug']:
202         build_subdir += "-debug"
203     if env['profile']:
204         build_subdir += "-profile"
205     build_dir = os.path.join(build_topdir, build_subdir)
206     # Place the .sconsign file in the build dir too, to avoid issues with
207     # different scons versions building the same source file
208     env['build'] = build_dir
209     env.SConsignFile(os.path.join(build_dir, '.sconsign'))
210
211     # C preprocessor options
212     cppdefines = []
213     if debug:
214         cppdefines += ['DEBUG']
215     else:
216         cppdefines += ['NDEBUG']
217     if env['profile']:
218         cppdefines += ['PROFILE']
219     if platform == 'windows':
220         cppdefines += [
221             'WIN32',
222             '_WINDOWS',
223             '_UNICODE',
224             'UNICODE',
225             # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx,
226             'WIN32_LEAN_AND_MEAN',
227             'VC_EXTRALEAN',
228             '_CRT_SECURE_NO_DEPRECATE',
229         ]
230         if debug:
231             cppdefines += ['_DEBUG']
232     if platform == 'winddk':
233         # Mimic WINDDK's builtin flags. See also:
234         # - WINDDK's bin/makefile.new i386mk.inc for more info.
235         # - buildchk_wxp_x86.log files, generated by the WINDDK's build
236         # - http://alter.org.ua/docs/nt_kernel/vc8_proj/
237         cppdefines += [
238             ('_X86_', '1'),
239             ('i386', '1'),
240             'STD_CALL',
241             ('CONDITION_HANDLING', '1'),
242             ('NT_INST', '0'),
243             ('WIN32', '100'),
244             ('_NT1X_', '100'),
245             ('WINNT', '1'),
246             ('_WIN32_WINNT', '0x0501'), # minimum required OS version
247             ('WINVER', '0x0501'),
248             ('_WIN32_IE', '0x0603'),
249             ('WIN32_LEAN_AND_MEAN', '1'),
250             ('DEVL', '1'),
251             ('__BUILDMACHINE__', 'WinDDK'),
252             ('FPO', '0'),
253         ]
254         if debug:
255             cppdefines += [('DBG', 1)]
256     if platform == 'wince':
257         cppdefines += [
258             '_CRT_SECURE_NO_DEPRECATE',
259             '_USE_32BIT_TIME_T',
260             'UNICODE',
261             '_UNICODE',
262             ('UNDER_CE', '600'),
263             ('_WIN32_WCE', '0x600'),
264             'WINCEOEM',
265             'WINCEINTERNAL',
266             'WIN32',
267             'STRICT',
268             'x86',
269             '_X86_',
270             'INTERNATIONAL',
271             ('INTLMSG_CODEPAGE', '1252'),
272         ]
273     if platform == 'windows':
274         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_USER']
275     if platform == 'winddk':
276         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_DISPLAY']
277     if platform == 'wince':
278         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_CE']
279         cppdefines += ['PIPE_SUBSYSTEM_WINDOWS_CE_OGL']
280     env.Append(CPPDEFINES = cppdefines)
281
282     # C preprocessor includes
283     if platform == 'winddk':
284         env.Append(CPPPATH = [
285             env['SDK_INC_PATH'],
286             env['DDK_INC_PATH'],
287             env['WDM_INC_PATH'],
288             env['CRT_INC_PATH'],
289         ])
290
291     # C compiler options
292     cflags = []
293     if gcc:
294         if debug:
295             cflags += ['-O0', '-g3']
296         else:
297             cflags += ['-O3', '-g3']
298         if env['profile']:
299             cflags += ['-pg']
300         if env['machine'] == 'x86':
301             cflags += [
302                 '-m32',
303                 #'-march=pentium4',
304                 '-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
305                 #'-mfpmath=sse',
306             ]
307         if env['machine'] == 'x86_64':
308             cflags += ['-m64']
309         cflags += [
310             '-Wall',
311             '-Wmissing-prototypes',
312             '-Wno-long-long',
313             '-ffast-math',
314             '-pedantic',
315             '-fmessage-length=0', # be nice to Eclipse
316         ]
317     if msvc:
318         # See also:
319         # - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
320         # - cl /?
321         if debug:
322             cflags += [
323               '/Od', # disable optimizations
324               '/Oi', # enable intrinsic functions
325               '/Oy-', # disable frame pointer omission
326             ]
327         else:
328             cflags += [
329               '/Ox', # maximum optimizations
330               '/Oi', # enable intrinsic functions
331               '/Ot', # favor code speed
332               #'/fp:fast', # fast floating point 
333             ]
334         if env['profile']:
335             cflags += [
336                 '/Gh', # enable _penter hook function
337                 '/GH', # enable _pexit hook function
338             ]
339         cflags += [
340             '/W3', # warning level
341             #'/Wp64', # enable 64 bit porting warnings
342         ]
343         if env['machine'] == 'x86':
344             cflags += [
345                 #'/QIfist', # Suppress _ftol
346                 #'/arch:SSE2', # use the SSE2 instructions
347             ]
348         if platform == 'windows':
349             cflags += [
350                 # TODO
351             ]
352         if platform == 'winddk':
353             cflags += [
354                 '/Zl', # omit default library name in .OBJ
355                 '/Zp8', # 8bytes struct member alignment
356                 '/Gy', # separate functions for linker
357                 '/Gm-', # disable minimal rebuild
358                 '/WX', # treat warnings as errors
359                 '/Gz', # __stdcall Calling convention
360                 '/GX-', # disable C++ EH
361                 '/GR-', # disable C++ RTTI
362                 '/GF', # enable read-only string pooling
363                 '/G6', # optimize for PPro, P-II, P-III
364                 '/Ze', # enable extensions
365                 '/Gi-', # disable incremental compilation
366                 '/QIfdiv-', # disable Pentium FDIV fix
367                 '/hotpatch', # prepares an image for hotpatching.
368                 #'/Z7', #enable old-style debug info
369             ]
370         if platform == 'wince':
371             # See also C:\WINCE600\public\common\oak\misc\makefile.def
372             cflags += [
373                 '/Zl', # omit default library name in .OBJ
374                 '/GF', # enable read-only string pooling
375                 '/GR-', # disable C++ RTTI
376                 '/GS', # enable security checks
377                 # Allow disabling language conformance to maintain backward compat
378                 #'/Zc:wchar_t-', # don't force wchar_t as native type, instead of typedef
379                 #'/Zc:forScope-', # don't enforce Standard C++ for scoping rules
380                 #'/wd4867',
381                 #'/wd4430',
382                 #'/MT',
383                 #'/U_MT',
384             ]
385         # Automatic pdb generation
386         # See http://scons.tigris.org/issues/show_bug.cgi?id=1656
387         env.EnsureSConsVersion(0, 98, 0)
388         env['PDB'] = '${TARGET.base}.pdb'
389     env.Append(CFLAGS = cflags)
390     env.Append(CXXFLAGS = cflags)
391
392     # Assembler options
393     if gcc:
394         if env['machine'] == 'x86':
395             env.Append(ASFLAGS = ['-m32'])
396         if env['machine'] == 'x86_64':
397             env.Append(ASFLAGS = ['-m64'])
398
399     # Linker options
400     linkflags = []
401     if gcc:
402         if env['machine'] == 'x86':
403             linkflags += ['-m32']
404         if env['machine'] == 'x86_64':
405             linkflags += ['-m64']
406     if platform == 'winddk':
407         # See also:
408         # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
409         linkflags += [
410             '/merge:_PAGE=PAGE',
411             '/merge:_TEXT=.text',
412             '/section:INIT,d',
413             '/opt:ref',
414             '/opt:icf',
415             '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
416             '/incremental:no',
417             '/fullbuild',
418             '/release',
419             '/nodefaultlib',
420             '/wx',
421             '/debug',
422             '/debugtype:cv',
423             '/version:5.1',
424             '/osversion:5.1',
425             '/functionpadmin:5',
426             '/safeseh',
427             '/pdbcompress',
428             '/stack:0x40000,0x1000',
429             '/driver',
430             '/align:0x80',
431             '/subsystem:native,5.01',
432             '/base:0x10000',
433
434             '/entry:DrvEnableDriver',
435         ]
436         if env['profile']:
437             linkflags += [
438                 '/MAP', # http://msdn.microsoft.com/en-us/library/k7xkk3e2.aspx
439             ]
440     if platform == 'wince':
441         linkflags += [
442             '/nodefaultlib',
443             #'/incremental:no',
444             #'/fullbuild',
445             '/entry:_DllMainCRTStartup',
446         ]
447     env.Append(LINKFLAGS = linkflags)
448
449     # Default libs
450     env.Append(LIBS = [])
451
452     # Custom builders and methods
453     createConvenienceLibBuilder(env)
454     createCodeGenerateMethod(env)
455     createInstallMethods(env)
456
457     # for debugging
458     #print env.Dump()
459
460
461 def exists(env):
462     return 1