2 # http://scons.sourceforge.net
\r
4 import commands, re, sys, os, pickle, string, popen2
\r
5 from makeversion import radiant_makeversion, get_version
\r
6 from osx_setup import do_osx_setup
\r
8 # to access some internal stuff
\r
11 conf_filename='site.conf'
\r
12 # there is a default hardcoded value, you can override on command line, those are saved between runs
\r
13 # we only handle strings
\r
14 serialized=['CC', 'CXX', 'JOBS', 'BUILD', 'SETUP']
\r
16 # help -------------------------------------------
\r
19 Usage: scons [OPTIONS] [TARGET] [CONFIG]
\r
21 [OPTIONS] and [TARGET] are covered in command line options, use scons -H
\r
23 [CONFIG]: KEY="VALUE" [...]
\r
24 a number of configuration options saved between runs in the """ + conf_filename + """ file
\r
25 erase """ + conf_filename + """ to start with default settings again
\r
29 Specify C and C++ compilers (defaults gcc and g++)
\r
31 You can use ccache and distcc, for instance:
\r
32 CC="ccache distcc gcc" CXX="ccache distcc g++"
\r
36 ex: JOBS="4" is a good setting on SMP machines
\r
39 Use debug/release to select build settings
\r
40 ex: BUILD="release" - default is debug
\r
41 OSX: use BUILD="info" to generate the set of release files
\r
44 Build a setup - default 0
\r
48 # end help ---------------------------------------
\r
50 # sanity -----------------------------------------
\r
52 # use q decently recent python release
\r
53 EnsurePythonVersion( 2, 1 )
\r
55 EnsureSConsVersion( 0, 95 )
\r
56 print 'SCons ' + SCons.__version__
\r
58 # end sanity -------------------------------------
\r
60 # system detection -------------------------------
\r
63 g_cpu = commands.getoutput('uname -m')
\r
64 exp = re.compile('.*i?86.*')
\r
65 if (g_cpu == 'Power Macintosh'):
\r
67 elif exp.match(g_cpu):
\r
73 OS = commands.getoutput('uname')
\r
76 # libc .. do the little magic!
\r
77 # NOTE: this used to work fine up to libc 2.3
\r
78 libc = commands.getoutput('/lib/libc.so.6 |grep "GNU C "|grep version|awk -F "version " \'{ print $2 }\'|cut -b -3')
\r
80 # end system detection ---------------------------
\r
82 # default settings -------------------------------
\r
90 g_build_root = 'build'
\r
92 # end default settings ---------------------------
\r
94 # site settings ----------------------------------
\r
97 if (os.path.exists(conf_filename)):
\r
98 site_file = open(conf_filename, 'r')
\r
99 p = pickle.Unpickler(site_file)
\r
100 site_dict = p.load()
\r
101 print 'Loading build configuration from ' + conf_filename
\r
102 for k, v in site_dict.items():
\r
103 exec_cmd = k + '=\"' + v + '\"'
\r
107 # end site settings ------------------------------
\r
109 # command line settings --------------------------
\r
111 for k in serialized:
\r
112 if (ARGUMENTS.has_key(k)):
\r
113 exec_cmd = k + '=\"' + ARGUMENTS[k] + '\"'
\r
114 print 'Command line: ' + exec_cmd
\r
117 # end command line settings ----------------------
\r
119 # sanity check -----------------------------------
\r
121 if (SETUP == '1' and BUILD != 'release' and BUILD != 'info'):
\r
122 print 'Forcing release build for setup'
\r
125 def GetGCCVersion(name):
\r
126 ret = commands.getstatusoutput('%s -dumpversion' % name)
\r
127 if ( ret[0] != 0 ):
\r
129 vers = string.split(ret[1], '.')
\r
130 if ( len(vers) == 2 ):
\r
131 return [ vers[0], vers[1], 0 ]
\r
132 elif ( len(vers) == 3 ):
\r
136 ver_cc = GetGCCVersion(CC)
\r
137 ver_cxx = GetGCCVersion(CXX)
\r
139 # end sanity check -------------------------------
\r
141 # save site configuration ----------------------
\r
143 for k in serialized:
\r
144 exec_cmd = 'site_dict[\'' + k + '\'] = ' + k
\r
147 site_file = open(conf_filename, 'w')
\r
148 p = pickle.Pickler(site_file)
\r
152 # end save site configuration ------------------
\r
154 # general configuration, target selection --------
\r
156 SConsignFile( "scons.signatures" )
\r
158 g_build = g_build_root + '/' + BUILD
\r
160 SetOption('num_jobs', JOBS)
\r
165 CXXFLAGS = '-pipe -DQ_NO_STLPORT '
\r
167 if (BUILD == 'debug'):
\r
168 CXXFLAGS += '-g -D_DEBUG '
\r
169 CCFLAGS += '-g -D_DEBUG '
\r
170 elif (BUILD == 'release'):
\r
171 CXXFLAGS += '-g -O2 '
\r
172 CCFLAGS += '-g -O2 '
\r
173 elif ( BUILD == 'info' ):
\r
174 print 'Preparing OSX release'
\r
175 ( line, major, minor ) = get_version()
\r
176 do_osx_setup( major, minor, 'osx-radiant-%s.run' % line )
\r
179 print 'Unknown build configuration ' + BUILD
\r
183 if ( OS == 'Linux' ):
\r
184 LINKFLAGS += '-Wl,-fini,fini_stub '
\r
185 if ( OS == 'Darwin' ):
\r
186 CCFLAGS += '-force_cpusubtype_ALL -fPIC '
\r
187 CXXFLAGS += '-force_cpusubtype_ALL -fPIC -fno-exceptions -fno-rtti '
\r
188 CPPPATH.append('/sw/include')
\r
189 CPPPATH.append('/usr/X11R6/include')
\r
190 LINKFLAGS += '-L/sw/lib -L/usr/lib -L/usr/X11R6/lib '
\r
192 CPPPATH.append('libs')
\r
194 # extend the standard Environment a bit
\r
195 class idEnvironment(Environment):
\r
197 def useGlib2(self):
\r
198 self['CXXFLAGS'] += '`pkg-config glib-2.0 --cflags` '
\r
199 self['CCFLAGS'] += '`pkg-config glib-2.0 --cflags` '
\r
200 self['LINKFLAGS'] += '`pkg-config glib-2.0 --libs` '
\r
203 self['CXXFLAGS'] += '`xml2-config --cflags` '
\r
204 self['CCFLAGS'] += '`xml2-config --cflags` '
\r
205 self['LINKFLAGS'] += '`xml2-config --libs` '
\r
208 self['CXXFLAGS'] += '`pkg-config gtk+-2.0 --cflags` '
\r
209 self['CCFLAGS'] += '`pkg-config gtk+-2.0 --cflags` '
\r
210 self['LINKFLAGS'] += '`pkg-config gtk+-2.0 --libs-only-L` `pkg-config gtk+-2.0 --libs-only-l` '
\r
212 def useGtkGLExt(self):
\r
213 self['CXXFLAGS'] += '`pkg-config gtkglext-1.0 --cflags` '
\r
214 self['CCFLAGS'] += '`pkg-config gtkglext-1.0 --cflags` '
\r
215 self['LINKFLAGS'] += '`pkg-config gtkglext-1.0 --libs-only-L` `pkg-config gtkglext-1.0 --libs-only-l` '
\r
218 self['CXXFLAGS'] += '`libpng-config --cflags` '
\r
219 self['CCFLAGS'] += '`libpng-config --cflags` '
\r
220 self['LINKFLAGS'] += '`libpng-config --ldflags` '
\r
222 def usePThread(self):
\r
223 if ( OS == 'Darwin' ):
\r
224 self['LINKFLAGS'] += '-lpthread -Wl,-stack_size,0x400000 '
\r
226 self['LINKFLAGS'] += '-lpthread '
\r
228 def CheckLDD(self, target, source, env):
\r
230 if (not os.path.isfile(file.abspath)):
\r
231 print('ERROR: CheckLDD: target %s not found\n' % target[0])
\r
233 # not using os.popen3 as I want to check the return code
\r
234 ldd = popen2.Popen3('`which ldd` -r %s' % target[0], 1)
\r
235 stdout_lines = ldd.fromchild.readlines()
\r
236 stderr_lines = ldd.childerr.readlines()
\r
237 ldd_ret = ldd.wait()
\r
240 if ( ldd_ret != 0 ):
\r
241 print "ERROR: ldd command returned with exit code %d" % ldd_ret
\r
242 os.system('rm %s' % target[0])
\r
244 for i_line in stderr_lines:
\r
246 regex = re.compile('undefined symbol: (.*)\t\\((.*)\\)\n')
\r
247 if ( regex.match(i_line) ):
\r
248 symbol = regex.sub('\\1', i_line)
\r
250 env['ALLOWED_SYMBOLS'].index(symbol)
\r
254 print "ERROR: failed to parse ldd stderr line: %s" % i_line
\r
255 os.system('rm %s' % target[0])
\r
258 print "ERROR: undefined symbols"
\r
259 os.system('rm %s' % target[0])
\r
262 def SharedLibrarySafe(self, target, source):
\r
263 self.SharedLibrary(target, source)
\r
264 if (OS != 'Darwin'):
\r
265 AddPostAction(target + '.so', self.CheckLDD)
\r
267 g_env = idEnvironment(ENV = os.environ,
\r
272 CXXFLAGS = CXXFLAGS,
\r
274 LINKFLAGS = LINKFLAGS)
\r
276 # export the globals
\r
277 GLOBALS = 'g_env INSTALL SETUP g_cpu'
\r
279 radiant_makeversion('\\ngcc version: %s.%s.%s' % ( ver_cc[0], ver_cc[1], ver_cc[2] ) )
\r
281 # end general configuration ----------------------
\r
283 # targets ----------------------------------------
\r
287 Export('GLOBALS ' + GLOBALS)
\r
288 BuildDir(g_build, '.', duplicate = 0)
\r
289 SConscript(g_build + '/SConscript')
\r
291 # end targets ------------------------------------
\r