/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 406 - (show annotations) (download)
Sat Apr 1 05:57:34 2006 UTC (14 years, 6 months ago) by johnpye
File size: 13954 byte(s)
Woops
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 # Where are the Tk includes?
119 opts.Add(PackageOption(
120 'TK_CPPPATH'
121 ,"Where are your Tk include files?"
122 ,None
123 ))
124
125 # Where are the Tk libs?
126 opts.Add(PackageOption(
127 'TK_LIBPATH'
128 ,"Where are your Tk libraries?"
129 ,None
130 ))
131
132
133 # TODO: OTHER OPTIONS?
134
135 # TODO: flags for optimisation
136
137 # TODO: turning on/off bintoken functionality
138
139 # TODO: Where will the 'Makefile.bt' file be installed
140 # ....
141
142 opts.Update(env)
143 opts.Save('options.cache',env)
144
145 Help(opts.GenerateHelpText(env))
146
147 env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
148
149 with_tcltk_gui = (env['WITHOUT_TCLTK_GUI']==False)
150
151 with_python = (env['WITHOUT_PYTHON']==False)
152
153 with_cunit_tests = env['WITH_CUNIT_TESTS']
154
155 print "SOLVERS:",env['WITH_SOLVERS']
156
157 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
158 print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
159 print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
160
161 subst_dict = {
162 '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
163 , '@GLADE_FILE@':'glade/ascend.glade'
164 , '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
165 , '@ASCEND_ICON@':'glade/ascend.png'
166 , '@HELP_ROOT@':''
167 }
168
169 if env['WITH_LOCAL_HELP']:
170 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
171
172 env.Append(SUBST_DICT=subst_dict)
173
174 #------------------------------------------------------
175 # SPECIAL CONFIGURATION TESTS
176
177 #----------------
178 # SWIG
179
180 import os,re
181
182 def CheckSwigVersion(context):
183 context.Message("Checking version of SWIG... ")
184 cmd = env['SWIG']+' -version'
185 (cin,coutcerr) = os.popen4(cmd);
186 output = coutcerr.read()
187
188 restr = "SWIG\\s+Version\\s+(?P<maj>[0-9]+)\\.(?P<min>[0-9]+)\\.(?P<pat>[0-9]+)\\s*$"
189 expr = re.compile(restr,re.M);
190 m = expr.search(output);
191 if not m:
192 context.Result("error running SWIG or detecting SWIG version")
193 return 0
194 maj = int(m.group('maj'))
195 min = int(m.group('min'))
196 pat = int(m.group('pat'))
197
198 if maj == 1 and (
199 min > 3
200 or (min == 3 and pat >= 24)
201 ):
202 context.Result("ok, %d.%d.%d" % (maj,min,pat))
203 return 1;
204 else:
205 context.Result("too old, %d.%d.%d" % (maj,min,pat))
206 return 0;
207
208 #----------------
209 # General purpose library-and-header test
210
211 class KeepContext:
212 def __init__(self,context,varprefix):
213 self.keep = {}
214 for k in ['LIBS','LIBPATH','CPPPATH']:
215 if context.env.has_key(k):
216 self.keep[k] = context.env[k]
217
218 libpath_add = []
219 if context.env.has_key(varprefix+'_LIBPATH'):
220 libpath_add = [env[varprefix+'_LIBPATH']]
221
222 cpppath_add = []
223 if context.env.has_key(varprefix+'_CPPPATH'):
224 cpppath_add = [env[varprefix+'_CPPPATH']]
225
226 context.env.Append(
227 LIBPATH = libpath_add
228 , CPPPATH = cpppath_add
229 )
230
231 def restore(self,context):
232 for k in self.keep:
233 context.env[k]=self.keep[k];
234
235 def CheckExtLib(context,libname,text,ext='.c',varprefix=None):
236 """This method will check for variables LIBNAME_LIBPATH
237 and LIBNAME_CPPPATH and try to compile and link the
238 file with the provided text, linking with the
239 library libname."""
240
241 context.Message( 'Checking for '+libname+'... ' )
242
243 if varprefix==None:
244 varprefix = libname.upper()
245
246 keep = KeepContext(context,varprefix)
247
248 context.env.Append(LIBS=[libname])
249
250 is_ok = context.TryLink(text,ext)
251
252 keep.restore(context)
253
254 context.Result(is_ok)
255 return is_ok
256
257 #----------------
258 # CUnit test
259
260 cunit_test_text = """
261 #include <CUnit/Cunit.h>
262 int maxi(int i1, int i2){
263 return (i1 > i2) ? i1 : i2;
264 }
265
266 void test_maxi(void){
267 CU_ASSERT(maxi(0,2) == 2);
268 CU_ASSERT(maxi(0,-2) == 0);
269 CU_ASSERT(maxi(2,2) == 2);
270
271 }
272 int main(void){
273 /* CU_initialize_registry() */
274 return 0;
275 }
276 """
277
278 def CheckCUnit(context):
279 return CheckLib(context
280 ,'cunit'
281 ,cunit_test_text
282 )
283
284 #----------------
285 # Tcl test
286
287 tcl_check_text = r"""
288 #include <tcl.h>
289 #include <stdio.h>
290 int main(void){
291 printf("%s",TCL_PATCH_LEVEL);
292 return 0;
293 }
294 """
295
296 def CheckTcl(context):
297 return CheckExtLib(context,'tcl',tcl_check_text)
298
299 def CheckTclVersion(context):
300 keep = KeepContext(context,'TCL')
301 context.Message("Checking Tcl version... ")
302 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
303 keep.restore(context)
304 if not is_ok:
305 context.Result("failed to run check")
306 return 0
307 context.Result(output)
308
309 major,minor,patch = tuple(int(i) for i in output.split("."))
310 if major != 8 or minor > 3:
311 # bad version
312 return 0
313
314 # good version
315 return 1
316
317 #----------------
318 # Tcl test
319
320 tk_check_text = r"""
321 #include <tk.h>
322 #include <stdio.h>
323 int main(void){
324 printf("%s",TK_PATCH_LEVEL);
325 return 0;
326 }
327 """
328 def CheckTk(context):
329 return CheckExtLib(context,'tk',tk_check_text)
330
331 def CheckTkVersion(context):
332 keep = KeepContext(context,'TK')
333 context.Message("Checking Tk version... ")
334 (is_ok,output) = context.TryRun(tk_check_text,'.c')
335 keep.restore(context)
336 if not is_ok:
337 context.Result("failed to run check")
338 return 0
339 context.Result(output)
340
341 major,minor,patch = tuple(int(i) for i in output.split("."))
342 if major != 8 or minor > 3:
343 # bad version
344 return 0
345
346 # good version
347 return 1
348
349 #------------------------------------------------------
350 # CONFIGURATION
351
352 conf = Configure(env
353 , custom_tests = {
354 'CheckSwigVersion' : CheckSwigVersion
355 , 'CheckCUnit' : CheckCUnit
356 , 'CheckTcl' : CheckTcl
357 , 'CheckTclVersion' : CheckTclVersion
358 , 'CheckTk' : CheckTk
359 , 'CheckTkVersion' : CheckTkVersion
360 # , 'CheckIsNan' : CheckIsNan
361 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
362 }
363 , config_h = "config.h"
364 )
365
366 if not conf.CheckSwigVersion():
367 print 'SWIG version is not OK'
368 Exit(1)
369
370 # Math library
371 if not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
372 print 'Did not find libm.a or m.lib, exiting!'
373 Exit(1)
374
375 # Where is 'isnan'?
376
377 if not conf.CheckFunc('isnan'):
378 print "Didn't find isnan"
379 Exit(1)
380
381 # Tcl/Tk
382
383 if conf.CheckTcl() and conf.CheckTk():
384 if with_tcltk_gui and not conf.CheckTclVersion():
385 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
386 with_tcltk_gui = False
387
388 if with_tcltk_gui and not conf.CheckTkVersion():
389 without_tcltk_reason += "Require Tk version <= 8.3. See 'scons -h'"
390 with_tcltk_gui = False
391 else:
392 without_tcltk_reason = "Tcl/Tk not found."
393 # Python... obviously we're already running python, so we just need to
394 # check that we can link to the python library OK:
395
396 if platform.system()=="Windows":
397 python_lib='python24'
398 else:
399 python_lib='python2.4'
400
401 # SWIG version
402
403 if platform.system()=="Windows":
404 #env['SWIG']=['c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe']
405 env['ENV']['SWIGFEATURES']='-O'
406 else:
407 env['ENV']['SWIGFEATURES']='-O'
408
409 # CUnit
410
411 if with_cunit_tests:
412 if not conf.CheckCUnit():
413 print "CUnit not found. Use 'scons WITH_CUNIT_TESTS=0'"
414 Exit(1)
415
416 # TODO: -D_HPUX_SOURCE is needed
417
418 # TODO: check size of void*
419
420 # TODO: detect if dynamic libraries are possible or not
421
422 conf.Finish()
423
424 env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
425 env.Append(PYTHON_LIB=[python_lib])
426 env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
427
428 if not with_python:
429 print "Can't build python interface"
430 Exit(1)
431
432 #------------------------------------------------------
433 # RECIPE: 'SubstInFile', used in pygtk SConscript
434
435 import re
436 from SCons.Script import * # the usual scons stuff you get in a SConscript
437
438 def TOOL_SUBST(env):
439 """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
440 from the source to the target.
441 The values of SUBST_DICT first have any construction variables expanded
442 (its keys are not expanded).
443 If a value of SUBST_DICT is a python callable function, it is called and
444 the result is expanded as the value.
445 If there's more than one source and more than one target, each target gets
446 substituted from the corresponding source.
447 """
448 env.Append(TOOLS = 'SUBST')
449 def do_subst_in_file(targetfile, sourcefile, dict):
450 """Replace all instances of the keys of dict with their values.
451 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
452 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
453 """
454 try:
455 f = open(sourcefile, 'rb')
456 contents = f.read()
457 f.close()
458 except:
459 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
460 for (k,v) in dict.items():
461 contents = re.sub(k, v, contents)
462 try:
463 f = open(targetfile, 'wb')
464 f.write(contents)
465 f.close()
466 except:
467 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
468 return 0 # success
469
470 def subst_in_file(target, source, env):
471 if not env.has_key('SUBST_DICT'):
472 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
473 d = dict(env['SUBST_DICT']) # copy it
474 for (k,v) in d.items():
475 if callable(v):
476 d[k] = env.subst(v())
477 elif SCons.Util.is_String(v):
478 d[k]=env.subst(v)
479 else:
480 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
481 for (t,s) in zip(target, source):
482 return do_subst_in_file(str(t), str(s), d)
483
484 def subst_in_file_string(target, source, env):
485 """This is what gets printed on the console."""
486 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
487 for (t,s) in zip(target, source)])
488
489 def subst_emitter(target, source, env):
490 """Add dependency from substituted SUBST_DICT to target.
491 Returns original target, source tuple unchanged.
492 """
493 d = env['SUBST_DICT'].copy() # copy it
494 for (k,v) in d.items():
495 if callable(v):
496 d[k] = env.subst(v())
497 elif SCons.Util.is_String(v):
498 d[k]=env.subst(v)
499 Depends(target, SCons.Node.Python.Value(d))
500 return target, source
501
502 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
503 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
504
505 TOOL_SUBST(env)
506
507 #------------------------------------------------------
508 # SUBDIRECTORIES....
509
510
511 env.Append(CPPPATH=['..'])
512
513 env.SConscript(['base/generic/general/SConscript'],'env')
514
515 env.SConscript(['base/generic/utilities/SConscript'],'env')
516
517 env.SConscript(['base/generic/compiler/SConscript'],'env')
518
519 env.SConscript(['base/generic/solver/SConscript'],'env')
520
521 env.SConscript(['base/generic/packages/SConscript'],'env')
522
523 if with_tcltk_gui:
524 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
525 else:
526 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
527
528 if with_python:
529 env.SConscript(['pygtk/interface/SConscript'],'env')
530 else:
531 print "Skipping... Python GUI isn't being built"
532
533 if with_cunit_tests:
534 testdirs = ['general','solver','utilities']
535 for testdir in testdirs:
536 path = 'base/generic/'+testdir+'/test/'
537 env.SConscript([path+'SConscript'],'env')
538 env.SConscript(['test/SConscript'],'env')
539 env.SConscript(['base/generic/test/SConscript'],'env')
540
541
542 else:
543 print "Skipping... CUnit tests aren't being built"
544
545 #------------------------------------------------------
546 # INSTALLATION
547
548 # TODO: add install options

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