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