/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 404 - (show annotations) (download)
Sat Apr 1 05:37:52 2006 UTC (14 years, 5 months ago) by johnpye
File size: 13911 byte(s)
Added Tcl detection. Still to do: check that Tk version matches Tcl version.
1 import os, commands, platform, distutils.sysconfig, os.path
2
3 #------------------------------------------------------
4 # OPTIONS
5 #
6 # Note that if you set the options via the command line, they will be
7 # remembered in the file 'options.cache'. It's a feature ;-)
8
9 opts = Options(['options.cache', 'config.py'])
10 print "PLATFORM = ",platform.system()
11
12 # Import the outside environment
13 env = Environment(ENV=os.environ)
14
15 # Package linking option
16 opts.Add(EnumOption(
17 'PACKAGE_LINKING'
18 , 'Style of linking for external libraries'
19 , 'DYNAMIC_PACKAGES'
20 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
21 ))
22
23 # You can turn off building of Tcl/Tk interface
24 opts.Add(BoolOption(
25 'WITHOUT_TCLTK_GUI'
26 ,"Set to True if you don't want to build the original Tcl/Tk GUI."
27 , False
28 ))
29
30 # You can turn off the building of the Python interface
31 opts.Add(BoolOption(
32 'WITHOUT_PYTHON'
33 ,"Set to True if you don't want to build Python wrappers."
34 , False
35 ))
36
37 # Which solvers will we allow?
38 opts.Add(ListOption(
39 'WITH_SOLVERS'
40 ,"List of the solvers you want to build. The default is the minimum that"
41 +" works."
42 ,["QRSLV","CMSLV"]
43 ,['QRSLV','MPS','SLV','OPTSQP'
44 ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
45 ,'LSOD','OPTSQP'
46 ]
47 ))
48
49 # Where will the local copy of the help files be kept?
50 opts.Add(PackageOption(
51 'WITH_LOCAL_HELP'
52 , "Directory containing the local copy of the help files (optional)"
53 , "no"
54 ))
55
56 # Will bintoken support be enabled?
57 opts.Add(BoolOption(
58 'WITH_BINTOKEN'
59 ,"Enable bintoken support? This means compiling models as C-code before"
60 +" running them, to increase solving speed for large models."
61 ,False
62 ))
63
64 # What should the default ASCENDLIBRARY path be?
65 # Note: users can change it by editing their ~/.ascend.ini
66 opts.Add(
67 'DEFAULT_ASCENDLIBRARY'
68 ,"Set the default value of the ASCENDLIBRARY -- the location where"
69 +" ASCEND will look for models when running ASCEND"
70 ,os.path.expanduser("~/src/ascend/trunk/models")
71 )
72
73 # Where is SWIG?
74 opts.Add(
75 'SWIG'
76 ,"SWIG location, probably only required for MinGW and MSVC users."
77 +" Enter the location as a Windows-style path, for example"
78 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
79 )
80
81 # Build the test suite?
82 opts.Add(BoolOption(
83 'WITH_CUNIT_TESTS'
84 ,"Whether to build the CUnit tests. Default is off. If set to on,"
85 +" you must have CUnit installed somewhere that SCons can"
86 +" find it."
87 ,False
88 ))
89
90 # Where are the CUnit includes?
91 opts.Add(PackageOption(
92 'CUNIT_CPPPATH'
93 ,"Where are your CUnit include files?"
94 ,"off"
95 ))
96
97 # Where are the CUnit libraries?
98 opts.Add(PackageOption(
99 'CUNIT_LIBPATH'
100 ,"Where are your CUnit libraries?"
101 ,"off"
102 ))
103
104 # Where are the Tcl includes?
105 opts.Add(PackageOption(
106 'TCL_CPPPATH'
107 ,"Where are your Tcl include files?"
108 ,None
109 ))
110
111 # Where are the Tcl libs?
112 opts.Add(PackageOption(
113 'TCL_LIBPATH'
114 ,"Where are your Tcl libraries?"
115 ,None
116 ))
117
118
119 # TODO: OTHER OPTIONS?
120
121 # TODO: flags for optimisation
122
123 # TODO: turning on/off bintoken functionality
124
125 # TODO: Where will the 'Makefile.bt' file be installed
126 # ....
127
128 opts.Update(env)
129 opts.Save('options.cache',env)
130
131 Help(opts.GenerateHelpText(env))
132
133 env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
134
135 with_tcltk_gui = (env['WITHOUT_TCLTK_GUI']==False)
136
137 with_python = (env['WITHOUT_PYTHON']==False)
138
139 with_cunit_tests = env['WITH_CUNIT_TESTS']
140
141 print "SOLVERS:",env['WITH_SOLVERS']
142
143 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
144 print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
145 print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
146
147 subst_dict = {
148 '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
149 , '@GLADE_FILE@':'glade/ascend.glade'
150 , '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
151 , '@ASCEND_ICON@':'glade/ascend.png'
152 , '@HELP_ROOT@':''
153 }
154
155 if env['WITH_LOCAL_HELP']:
156 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
157
158 env.Append(SUBST_DICT=subst_dict)
159
160 #------------------------------------------------------
161 # SPECIAL CONFIGURATION TESTS
162
163 #----------------
164 # SWIG
165
166 import os,re
167
168 def CheckSwigVersion(context):
169 context.Message("Checking version of SWIG")
170 cmd = env['SWIG']+' -version'
171 (cin,coutcerr) = os.popen4(cmd);
172 output = coutcerr.read()
173
174 restr = "SWIG\\s+Version\\s+(?P<maj>[0-9]+)\\.(?P<min>[0-9]+)\\.(?P<pat>[0-9]+)\\s*$"
175 expr = re.compile(restr,re.M);
176 m = expr.search(output);
177 if not m:
178 context.Result("error running SWIG or detecting SWIG version")
179 return 0
180 maj = int(m.group('maj'))
181 min = int(m.group('min'))
182 pat = int(m.group('pat'))
183
184 if maj == 1 and (
185 min > 3
186 or (min == 3 and pat >= 24)
187 ):
188 context.Result("ok, %d.%d.%d" % (maj,min,pat))
189 return 1;
190 else:
191 context.Result("too old, %d.%d.%d" % (maj,min,pat))
192 return 0;
193
194 #----------------
195 # General purpose library-and-header test
196
197 class KeepContext:
198 def __init__(self,context,varprefix):
199 self.keep = {}
200 for k in ['LIBS','LIBPATH','CPPPATH']:
201 if context.env.has_key(k):
202 self.keep[k] = context.env[k]
203
204 libpath_add = []
205 if context.env.has_key(varprefix+'_LIBPATH'):
206 libpath_add = [env[varprefix+'_LIBPATH']]
207
208 cpppath_add = []
209 if context.env.has_key(varprefix+'_CPPPATH'):
210 cpppath_add = [env[varprefix+'_CPPPATH']]
211
212 def restore(self,context):
213 for k in self.keep:
214 context.env[k]=self.keep[k];
215
216 def CheckExtLib(context,libname,text,ext='.c',varprefix=None):
217 """This method will check for variables LIBNAME_LIBPATH
218 and LIBNAME_CPPPATH and try to compile and link the
219 file with the provided text, linking with the
220 library libname."""
221
222 context.Message( 'Checking for '+libname+'...' )
223
224 if varprefix==None:
225 varprefix = libname.upper()
226
227 keep = KeepContext(context,varprefix)
228
229 context.env.Append(
230 LIBS = libname
231 , LIBPATH = libpath_add
232 , CPPPATH = cpppath_add
233 )
234
235 is_ok = context.TryLink(text,ext)
236
237 keep.restore()
238
239 context.Result(is_ok)
240 return is_ok
241
242 #----------------
243 # CUnit test
244
245 cunit_test_text = """
246 #include <CUnit/Cunit.h>
247 int maxi(int i1, int i2){
248 return (i1 > i2) ? i1 : i2;
249 }
250
251 void test_maxi(void){
252 CU_ASSERT(maxi(0,2) == 2);
253 CU_ASSERT(maxi(0,-2) == 0);
254 CU_ASSERT(maxi(2,2) == 2);
255
256 }
257 int main(void){
258 /* CU_initialize_registry() */
259 return 0;
260 }
261 """
262
263 def CheckCUnit(context):
264 return CheckLib(context
265 ,'cunit'
266 ,cunit_test_text
267 )
268
269 #----------------
270 # Tcl/Tk test
271
272 tcl_check_text = r"""
273 #include <tcl.h>
274 #include <stdio.h>
275 int main(void){
276 printf("%s",TCL_PATCH_LEVEL);
277 return 0;
278 }
279 """
280
281 tcl_test_text = open('checktcl.c').read()
282
283 def CheckTcl(context):
284 keep = KeepContext(context,'TCL')
285 context.Message("Checking for Tcl library... ")
286 is_ok = context.TryLink(tcl_check_text,'.c')
287 context.Result(is_ok)
288 keep.restore(context)
289 if not is_ok:
290 return 0
291 return 1
292
293 def CheckTclVersion(context):
294 keep = KeepContext(context,'TCL')
295 context.Message("Checking Tcl version... ")
296 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
297 keep.restore(context)
298 if not is_ok:
299 context.Result("failed to run check")
300 return 0
301 context.Result(output)
302
303 major,minor,patch = tuple(int(i) for i in output.split("."))
304 if major != 8 or minor > 3:
305 # bad version
306 return 0
307
308 # good version
309 return 1
310
311 #------------------------------------------------------
312 # CONFIGURATION
313
314 conf = Configure(env
315 , custom_tests = {
316 'CheckSwigVersion' : CheckSwigVersion
317 , 'CheckCUnit' : CheckCUnit
318 , 'CheckTcl' : CheckTcl
319 , 'CheckTclVersion' : CheckTclVersion
320 # , 'CheckIsNan' : CheckIsNan
321 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
322 }
323 , config_h = "config.h"
324 )
325
326 if not conf.CheckSwigVersion():
327 print 'SWIG version is not OK'
328 Exit(1)
329
330 # Math library
331 if not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
332 print 'Did not find libm.a or m.lib, exiting!'
333 Exit(1)
334
335 # Where is 'isnan'?
336
337 if not conf.CheckFunc('isnan'):
338 print "Didn't find isnan"
339 Exit(1)
340
341 # Tcl/Tk
342
343 if conf.CheckTcl():
344 if with_tcltk_gui and not conf.CheckTclVersion():
345 print "Wrong Tcl version used. Please specify you 8.3 Tcl installation"\
346 +" via the TCL_CPPPATH and TCL_LIBPATH options, or use"\
347 +" WITHOUT_TCLTK_GUI=1 to prevent build of Tcl/Tk components.\n"
348 with_tcltk_gui = False
349
350 if with_tcltk_gui and not conf.CheckHeader('tk.h'):
351 with_tcltk_gui = False
352
353 if with_tcltk_gui and not conf.CheckLib('tk'):
354 with_tcktk_gui = False
355
356 # Python... obviously we're already running python, so we just need to
357 # check that we can link to the python library OK:
358
359 if platform.system()=="Windows":
360 #conf.env.Append(LIBPATH='c:\Python24\libs')
361 #conf.env.Append(CPPPATH='c:\Python24\include')
362 #python_header='Python.h'
363 python_lib='python24'
364 #python_libpath=['c:\\Python24\\libs']
365 #python_cpppath=['c:\\Python24\\include']
366 else:
367 #python_header='python2.4/Python.h'
368 python_lib='python2.4'
369 #python_libpath=[]
370 #python_cpppath=['/usr/include/python2.4']
371
372 #if not conf.CheckLibWithHeader(python_lib,python_header,'C'
373 # , LIBPATH=[distutils.sysconfig.PREFIX+"/libs"]
374 # , CPPPATH=[distutils.sysconfig.get_python_inc()]
375 #):
376 # print "Didn't find Python 2.4 ("+python_lib+")"
377 # with_python = False
378 #else:
379
380 # SWIG version
381
382 if platform.system()=="Windows":
383 #env['SWIG']=['c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe']
384 env['ENV']['SWIGFEATURES']='-O'
385 else:
386 env['ENV']['SWIGFEATURES']='-O'
387
388 # CUnit
389
390 if with_cunit_tests:
391 if not conf.CheckCUnit():
392 print "CUnit not found. Use 'scons WITH_CUNIT_TESTS=0'"
393 Exit(1)
394
395 # TODO: -D_HPUX_SOURCE is needed
396
397 # TODO: check size of void*
398
399 # TODO: detect if dynamic libraries are possible or not
400
401 conf.Finish()
402
403 env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
404 env.Append(PYTHON_LIB=[python_lib])
405 env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
406 print "PYTHON_LIBPATH =",env['PYTHON_LIBPATH']
407 print "PYTHON_CPPPATH =",env['PYTHON_CPPPATH']
408
409 if not with_python:
410 print "Can't build python interface"
411 Exit(1)
412
413 #------------------------------------------------------
414 # RECIPE: 'SubstInFile', used in pygtk SConscript
415
416 import re
417 from SCons.Script import * # the usual scons stuff you get in a SConscript
418
419 def TOOL_SUBST(env):
420 """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
421 from the source to the target.
422 The values of SUBST_DICT first have any construction variables expanded
423 (its keys are not expanded).
424 If a value of SUBST_DICT is a python callable function, it is called and
425 the result is expanded as the value.
426 If there's more than one source and more than one target, each target gets
427 substituted from the corresponding source.
428 """
429 env.Append(TOOLS = 'SUBST')
430 def do_subst_in_file(targetfile, sourcefile, dict):
431 """Replace all instances of the keys of dict with their values.
432 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
433 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
434 """
435 try:
436 f = open(sourcefile, 'rb')
437 contents = f.read()
438 f.close()
439 except:
440 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
441 for (k,v) in dict.items():
442 contents = re.sub(k, v, contents)
443 try:
444 f = open(targetfile, 'wb')
445 f.write(contents)
446 f.close()
447 except:
448 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
449 return 0 # success
450
451 def subst_in_file(target, source, env):
452 if not env.has_key('SUBST_DICT'):
453 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
454 d = dict(env['SUBST_DICT']) # copy it
455 for (k,v) in d.items():
456 if callable(v):
457 d[k] = env.subst(v())
458 elif SCons.Util.is_String(v):
459 d[k]=env.subst(v)
460 else:
461 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
462 for (t,s) in zip(target, source):
463 return do_subst_in_file(str(t), str(s), d)
464
465 def subst_in_file_string(target, source, env):
466 """This is what gets printed on the console."""
467 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
468 for (t,s) in zip(target, source)])
469
470 def subst_emitter(target, source, env):
471 """Add dependency from substituted SUBST_DICT to target.
472 Returns original target, source tuple unchanged.
473 """
474 d = env['SUBST_DICT'].copy() # copy it
475 for (k,v) in d.items():
476 if callable(v):
477 d[k] = env.subst(v())
478 elif SCons.Util.is_String(v):
479 d[k]=env.subst(v)
480 Depends(target, SCons.Node.Python.Value(d))
481 return target, source
482
483 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
484 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
485
486 TOOL_SUBST(env)
487
488 #------------------------------------------------------
489 # SUBDIRECTORIES....
490
491
492 env.Append(CPPPATH=['..'])
493
494 env.SConscript(['base/generic/general/SConscript'],'env')
495
496 env.SConscript(['base/generic/utilities/SConscript'],'env')
497
498 env.SConscript(['base/generic/compiler/SConscript'],'env')
499
500 env.SConscript(['base/generic/solver/SConscript'],'env')
501
502 env.SConscript(['base/generic/packages/SConscript'],'env')
503
504 if with_tcltk_gui:
505 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
506 else:
507 print "Skipping... Tcl/Tk GUI isn't being built"
508
509 if with_python:
510 env.SConscript(['pygtk/interface/SConscript'],'env')
511 else:
512 print "Skipping... Python GUI isn't being built"
513
514 if with_cunit_tests:
515 testdirs = ['general','solver','utilities']
516 for testdir in testdirs:
517 path = 'base/generic/'+testdir+'/test/'
518 env.SConscript([path+'SConscript'],'env')
519 env.SConscript(['test/SConscript'],'env')
520 env.SConscript(['base/generic/test/SConscript'],'env')
521
522
523 else:
524 print "Skipping... CUnit tests aren't being built"
525
526 #------------------------------------------------------
527 # INSTALLATION
528
529 # TODO: add install options

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22