-# scons build script\r
+# -*- mode: python -*-\r
+# ZeroRadiant build scripts\r
+# TTimo <ttimo@idsoftware.com>\r
# http://scons.sourceforge.net\r
\r
-import commands, re, sys, os, pickle, string, popen2\r
-from makeversion import radiant_makeversion, get_version\r
-from osx_setup import do_osx_setup\r
+import sys, os, platform, cPickle\r
\r
-# to access some internal stuff\r
-import SCons\r
+import utils, config\r
\r
-conf_filename='site.conf'\r
-# there is a default hardcoded value, you can override on command line, those are saved between runs\r
-# we only handle strings\r
-serialized=['CC', 'CXX', 'JOBS', 'BUILD', 'SETUP']\r
+conf_filename = 'site.sconf'\r
\r
-# help -------------------------------------------\r
-\r
-Help("""\r
-Usage: scons [OPTIONS] [TARGET] [CONFIG]\r
-\r
-[OPTIONS] and [TARGET] are covered in command line options, use scons -H\r
-\r
-[CONFIG]: KEY="VALUE" [...]\r
-a number of configuration options saved between runs in the """ + conf_filename + """ file\r
-erase """ + conf_filename + """ to start with default settings again\r
-\r
-CC\r
-CXX\r
- Specify C and C++ compilers (defaults gcc and g++)\r
- ex: CC="gcc-3.2"\r
- You can use ccache and distcc, for instance:\r
- CC="ccache distcc gcc" CXX="ccache distcc g++"\r
-\r
-JOBS\r
- Parallel build\r
- ex: JOBS="4" is a good setting on SMP machines\r
-\r
-BUILD\r
- Use debug/release to select build settings\r
- ex: BUILD="release" - default is debug\r
- OSX: use BUILD="info" to generate the set of release files\r
-\r
-SETUP\r
- Build a setup - default 0\r
-"""\r
-)\r
-\r
-# end help ---------------------------------------\r
- \r
-# sanity -----------------------------------------\r
-\r
-# use q decently recent python release\r
-EnsurePythonVersion( 2, 1 )\r
-# above 0.90\r
-EnsureSConsVersion( 0, 95 )\r
-print 'SCons ' + SCons.__version__\r
-\r
-# end sanity -------------------------------------\r
-\r
-# system detection -------------------------------\r
-\r
-# CPU type\r
-g_cpu = commands.getoutput('uname -m')\r
-exp = re.compile('.*i?86.*')\r
-if (g_cpu == 'Power Macintosh'):\r
- g_cpu = 'ppc'\r
-elif exp.match(g_cpu):\r
- g_cpu = 'x86'\r
-else:\r
- g_cpu = 'cpu'\r
-\r
-# OS\r
-OS = commands.getoutput('uname')\r
-\r
-if (OS == 'Linux'):\r
- # libc .. do the little magic!\r
- # NOTE: this used to work fine up to libc 2.3\r
- libc = commands.getoutput('/lib/libc.so.6 |grep "GNU C "|grep version|awk -F "version " \'{ print $2 }\'|cut -b -3')\r
-\r
-# end system detection ---------------------------\r
-\r
-# default settings -------------------------------\r
-\r
-CC='gcc'\r
-CXX='g++'\r
-JOBS='1'\r
-BUILD='debug'\r
-INSTALL='#install'\r
-SETUP='0'\r
-g_build_root = 'build'\r
-\r
-# end default settings ---------------------------\r
-\r
-# site settings ----------------------------------\r
-\r
-site_dict = {}\r
-if (os.path.exists(conf_filename)):\r
- site_file = open(conf_filename, 'r')\r
- p = pickle.Unpickler(site_file)\r
- site_dict = p.load()\r
- print 'Loading build configuration from ' + conf_filename\r
- for k, v in site_dict.items():\r
- exec_cmd = k + '=\"' + v + '\"'\r
- print exec_cmd\r
- exec(exec_cmd)\r
-\r
-# end site settings ------------------------------\r
-\r
-# command line settings --------------------------\r
-\r
-for k in serialized:\r
- if (ARGUMENTS.has_key(k)):\r
- exec_cmd = k + '=\"' + ARGUMENTS[k] + '\"'\r
- print 'Command line: ' + exec_cmd\r
- exec(exec_cmd)\r
-\r
-# end command line settings ----------------------\r
-\r
-# sanity check -----------------------------------\r
-\r
-if (SETUP == '1' and BUILD != 'release' and BUILD != 'info'):\r
- print 'Forcing release build for setup'\r
- BUILD = 'release'\r
-\r
-def GetGCCVersion(name):\r
- ret = commands.getstatusoutput('%s -dumpversion' % name)\r
- if ( ret[0] != 0 ):\r
- return None\r
- vers = string.split(ret[1], '.')\r
- if ( len(vers) == 2 ):\r
- return [ vers[0], vers[1], 0 ]\r
- elif ( len(vers) == 3 ):\r
- return vers\r
- return None\r
-\r
-ver_cc = GetGCCVersion(CC)\r
-ver_cxx = GetGCCVersion(CXX)\r
-\r
-# end sanity check -------------------------------\r
-\r
-# save site configuration ----------------------\r
-\r
-for k in serialized:\r
- exec_cmd = 'site_dict[\'' + k + '\'] = ' + k\r
- exec(exec_cmd)\r
-\r
-site_file = open(conf_filename, 'w')\r
-p = pickle.Pickler(site_file)\r
-p.dump(site_dict)\r
-site_file.close()\r
-\r
-# end save site configuration ------------------\r
-\r
-# general configuration, target selection --------\r
-\r
-SConsignFile( "scons.signatures" )\r
-\r
-g_build = g_build_root + '/' + BUILD\r
-\r
-SetOption('num_jobs', JOBS)\r
-\r
-LINK = CXX\r
-# common flags\r
-CCFLAGS = ''\r
-CXXFLAGS = '-pipe -DQ_NO_STLPORT '\r
-CPPPATH = []\r
-if (BUILD == 'debug'):\r
- CXXFLAGS += '-g -D_DEBUG '\r
- CCFLAGS += '-g -D_DEBUG '\r
-elif (BUILD == 'release'):\r
- CXXFLAGS += '-g -O2 '\r
- CCFLAGS += '-g -O2 '\r
-elif ( BUILD == 'info' ):\r
- print 'Preparing OSX release'\r
- ( line, major, minor ) = get_version()\r
- do_osx_setup( major, minor, 'osx-radiant-%s.run' % line )\r
- sys.exit( 0 )\r
+try:\r
+ sys.argv.index( '-h' )\r
+except:\r
+ pass\r
else:\r
- print 'Unknown build configuration ' + BUILD\r
- sys.exit( 0 )\r
-\r
-LINKFLAGS = ''\r
-if ( OS == 'Linux' ):\r
- LINKFLAGS += '-Wl,-fini,fini_stub '\r
-if ( OS == 'Darwin' ):\r
- CCFLAGS += '-force_cpusubtype_ALL -fPIC '\r
- CXXFLAGS += '-force_cpusubtype_ALL -fPIC -fno-exceptions -fno-rtti '\r
- CPPPATH.append('/sw/include')\r
- CPPPATH.append('/usr/X11R6/include')\r
- LINKFLAGS += '-L/sw/lib -L/usr/lib -L/usr/X11R6/lib '\r
-\r
-CPPPATH.append('libs')\r
-\r
-# extend the standard Environment a bit\r
-class idEnvironment(Environment):\r
-\r
- def useGlib2(self):\r
- self['CXXFLAGS'] += '`pkg-config glib-2.0 --cflags` '\r
- self['CCFLAGS'] += '`pkg-config glib-2.0 --cflags` '\r
- self['LINKFLAGS'] += '`pkg-config glib-2.0 --libs` '\r
- \r
- def useXML2(self):\r
- self['CXXFLAGS'] += '`xml2-config --cflags` ' \r
- self['CCFLAGS'] += '`xml2-config --cflags` ' \r
- self['LINKFLAGS'] += '`xml2-config --libs` '\r
-\r
- def useGtk2(self):\r
- self['CXXFLAGS'] += '`pkg-config gtk+-2.0 --cflags` '\r
- self['CCFLAGS'] += '`pkg-config gtk+-2.0 --cflags` '\r
- self['LINKFLAGS'] += '`pkg-config gtk+-2.0 --libs-only-L` `pkg-config gtk+-2.0 --libs-only-l` '\r
- \r
- def useGtkGLExt(self):\r
- self['CXXFLAGS'] += '`pkg-config gtkglext-1.0 --cflags` '\r
- self['CCFLAGS'] += '`pkg-config gtkglext-1.0 --cflags` '\r
- self['LINKFLAGS'] += '`pkg-config gtkglext-1.0 --libs-only-L` `pkg-config gtkglext-1.0 --libs-only-l` ' \r
- \r
- def usePNG(self):\r
- self['CXXFLAGS'] += '`libpng-config --cflags` '\r
- self['CCFLAGS'] += '`libpng-config --cflags` '\r
- self['LINKFLAGS'] += '`libpng-config --ldflags` '\r
-\r
- def usePThread(self):\r
- if ( OS == 'Darwin' ):\r
- self['LINKFLAGS'] += '-lpthread -Wl,-stack_size,0x400000 '\r
- else:\r
- self['LINKFLAGS'] += '-lpthread '\r
-\r
- def CheckLDD(self, target, source, env):\r
- file = target[0]\r
- if (not os.path.isfile(file.abspath)):\r
- print('ERROR: CheckLDD: target %s not found\n' % target[0])\r
- Exit(1)\r
- # not using os.popen3 as I want to check the return code\r
- ldd = popen2.Popen3('`which ldd` -r %s' % target[0], 1)\r
- stdout_lines = ldd.fromchild.readlines()\r
- stderr_lines = ldd.childerr.readlines()\r
- ldd_ret = ldd.wait()\r
- del ldd\r
- have_undef = 0\r
- if ( ldd_ret != 0 ):\r
- print "ERROR: ldd command returned with exit code %d" % ldd_ret\r
- os.system('rm %s' % target[0])\r
- Exit()\r
- for i_line in stderr_lines:\r
- print repr(i_line)\r
- regex = re.compile('undefined symbol: (.*)\t\\((.*)\\)\n')\r
- if ( regex.match(i_line) ):\r
- symbol = regex.sub('\\1', i_line)\r
- try:\r
- env['ALLOWED_SYMBOLS'].index(symbol)\r
- except:\r
- have_undef = 1\r
- else:\r
- print "ERROR: failed to parse ldd stderr line: %s" % i_line\r
- os.system('rm %s' % target[0])\r
- Exit(1)\r
- if ( have_undef ):\r
- print "ERROR: undefined symbols"\r
- os.system('rm %s' % target[0])\r
- Exit(1)\r
- \r
- def SharedLibrarySafe(self, target, source):\r
- self.SharedLibrary(target, source)\r
- if (OS != 'Darwin'):\r
- AddPostAction(target + '.so', self.CheckLDD)\r
-\r
-g_env = idEnvironment(ENV = os.environ, \r
- CC = CC,\r
- CXX = CXX,\r
- LINK = LINK,\r
- CCFLAGS = CCFLAGS,\r
- CXXFLAGS = CXXFLAGS,\r
- CPPPATH = CPPPATH,\r
- LINKFLAGS = LINKFLAGS)\r
-\r
-# export the globals\r
-GLOBALS = 'g_env INSTALL SETUP g_cpu'\r
-\r
-radiant_makeversion('\\ngcc version: %s.%s.%s' % ( ver_cc[0], ver_cc[1], ver_cc[2] ) )\r
-\r
-# end general configuration ----------------------\r
-\r
-# targets ----------------------------------------\r
-\r
-Default('.')\r
-\r
-Export('GLOBALS ' + GLOBALS)\r
-BuildDir(g_build, '.', duplicate = 0)\r
-SConscript(g_build + '/SConscript')\r
-\r
-# end targets ------------------------------------\r
+ Help(\r
+"""\r
+======================================================================\r
+ZeroRadiant build system quick help\r
+\r
+You need scons v0.97.0d20070918.r2446 or newer\r
+\r
+Default build (release), just run scons at the toplevel\r
+\r
+debug build:\r
+$ scons config=debug\r
+======================================================================\r
+""" )\r
+ Return()\r
+\r
+active_configs = []\r
+\r
+# load up configurations from the save file\r
+if ( os.path.exists( conf_filename ) ):\r
+ f = open( conf_filename )\r
+ print 'reading saved configuration from site.conf'\r
+ try:\r
+ while ( True ):\r
+ c = cPickle.load( f )\r
+ active_configs.append( c )\r
+ except:\r
+ pass\r
+\r
+# read the command line and build configs\r
+config_statements = sys.argv[1:]\r
+active_configs = config.ConfigParser().parseStatements( active_configs, config_statements )\r
+assert( len( active_configs ) >= 1 )\r
+\r
+# save the config\r
+print 'saving updated configuration'\r
+f = open( conf_filename, 'wb' )\r
+for c in active_configs:\r
+ cPickle.dump( c, f, -1 )\r
+\r
+print 'emit build rules'\r
+for c in active_configs:\r
+ print 'emit configuration: %s' % repr( c )\r
+ c.emit()\r