/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 405 - (show annotations) (download)
Sat Apr 1 05:54:19 2006 UTC (14 years, 6 months ago) by johnpye
File size: 13997 byte(s)
Added Tk detection, improved reporting
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 tcl_test_text = open('checktcl.c').read()
297
298 def CheckTcl(context):
299 return CheckExtLib(context,'tcl',tcl_check_text)
300
301 def CheckTclVersion(context):
302 keep = KeepContext(context,'TCL')
303 context.Message("Checking Tcl version... ")
304 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
305 keep.restore(context)
306 if not is_ok:
307 context.Result("failed to run check")
308 return 0
309 context.Result(output)
310
311 major,minor,patch = tuple(int(i) for i in output.split("."))
312 if major != 8 or minor > 3:
313 # bad version
314 return 0
315
316 # good version
317 return 1
318
319 #----------------
320 # Tcl test
321
322 tk_check_text = r"""
323 #include <tk.h>
324 #include <stdio.h>
325 int main(void){
326 printf("%s",TK_PATCH_LEVEL);
327 return 0;
328 }
329 """
330 def CheckTk(context):
331 return CheckExtLib(context,'tk',tk_check_text)
332
333 def CheckTkVersion(context):
334 keep = KeepContext(context,'TK')
335 context.Message("Checking Tk version... ")
336 (is_ok,output) = context.TryRun(tk_check_text,'.c')
337 keep.restore(context)
338 if not is_ok:
339 context.Result("failed to run check")
340 return 0
341 context.Result(output)
342
343 major,minor,patch = tuple(int(i) for i in output.split("."))
344 if major != 8 or minor > 3:
345 # bad version
346 return 0
347
348 # good version
349 return 1
350
351 #------------------------------------------------------
352 # CONFIGURATION
353
354 conf = Configure(env
355 , custom_tests = {
356 'CheckSwigVersion' : CheckSwigVersion
357 , 'CheckCUnit' : CheckCUnit
358 , 'CheckTcl' : CheckTcl
359 , 'CheckTclVersion' : CheckTclVersion
360 , 'CheckTk' : CheckTk
361 , 'CheckTkVersion' : CheckTkVersion
362 # , 'CheckIsNan' : CheckIsNan
363 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
364 }
365 , config_h = "config.h"
366 )
367
368 if not conf.CheckSwigVersion():
369 print 'SWIG version is not OK'
370 Exit(1)
371
372 # Math library
373 if not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
374 print 'Did not find libm.a or m.lib, exiting!'
375 Exit(1)
376
377 # Where is 'isnan'?
378
379 if not conf.CheckFunc('isnan'):
380 print "Didn't find isnan"
381 Exit(1)
382
383 # Tcl/Tk
384
385 if conf.CheckTcl() and conf.CheckTk():
386 if with_tcltk_gui and not conf.CheckTclVersion():
387 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
388 with_tcltk_gui = False
389
390 if with_tcltk_gui and not conf.CheckTkVersion():
391 without_tcltk_reason += "Require Tk version <= 8.3. See 'scons -h'"
392 with_tcltk_gui = False
393 else:
394 without_tcltk_reason = "Tcl/Tk not found."
395 # Python... obviously we're already running python, so we just need to
396 # check that we can link to the python library OK:
397
398 if platform.system()=="Windows":
399 python_lib='python24'
400 else:
401 python_lib='python2.4'
402
403 # SWIG version
404
405 if platform.system()=="Windows":
406 #env['SWIG']=['c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe']
407 env['ENV']['SWIGFEATURES']='-O'
408 else:
409 env['ENV']['SWIGFEATURES']='-O'
410
411 # CUnit
412
413 if with_cunit_tests:
414 if not conf.CheckCUnit():
415 print "CUnit not found. Use 'scons WITH_CUNIT_TESTS=0'"
416 Exit(1)
417
418 # TODO: -D_HPUX_SOURCE is needed
419
420 # TODO: check size of void*
421
422 # TODO: detect if dynamic libraries are possible or not
423
424 conf.Finish()
425
426 env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
427 env.Append(PYTHON_LIB=[python_lib])
428 env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
429
430 if not with_python:
431 print "Can't build python interface"
432 Exit(1)
433
434 #------------------------------------------------------
435 # RECIPE: 'SubstInFile', used in pygtk SConscript
436
437 import re
438 from SCons.Script import * # the usual scons stuff you get in a SConscript
439
440 def TOOL_SUBST(env):
441 """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
442 from the source to the target.
443 The values of SUBST_DICT first have any construction variables expanded
444 (its keys are not expanded).
445 If a value of SUBST_DICT is a python callable function, it is called and
446 the result is expanded as the value.
447 If there's more than one source and more than one target, each target gets
448 substituted from the corresponding source.
449 """
450 env.Append(TOOLS = 'SUBST')
451 def do_subst_in_file(targetfile, sourcefile, dict):
452 """Replace all instances of the keys of dict with their values.
453 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
454 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
455 """
456 try:
457 f = open(sourcefile, 'rb')
458 contents = f.read()
459 f.close()
460 except:
461 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
462 for (k,v) in dict.items():
463 contents = re.sub(k, v, contents)
464 try:
465 f = open(targetfile, 'wb')
466 f.write(contents)
467 f.close()
468 except:
469 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
470 return 0 # success
471
472 def subst_in_file(target, source, env):
473 if not env.has_key('SUBST_DICT'):
474 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
475 d = dict(env['SUBST_DICT']) # copy it
476 for (k,v) in d.items():
477 if callable(v):
478 d[k] = env.subst(v())
479 elif SCons.Util.is_String(v):
480 d[k]=env.subst(v)
481 else:
482 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
483 for (t,s) in zip(target, source):
484 return do_subst_in_file(str(t), str(s), d)
485
486 def subst_in_file_string(target, source, env):
487 """This is what gets printed on the console."""
488 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
489 for (t,s) in zip(target, source)])
490
491 def subst_emitter(target, source, env):
492 """Add dependency from substituted SUBST_DICT to target.
493 Returns original target, source tuple unchanged.
494 """
495 d = env['SUBST_DICT'].copy() # copy it
496 for (k,v) in d.items():
497 if callable(v):
498 d[k] = env.subst(v())
499 elif SCons.Util.is_String(v):
500 d[k]=env.subst(v)
501 Depends(target, SCons.Node.Python.Value(d))
502 return target, source
503
504 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
505 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
506
507 TOOL_SUBST(env)
508
509 #------------------------------------------------------
510 # SUBDIRECTORIES....
511
512
513 env.Append(CPPPATH=['..'])
514
515 env.SConscript(['base/generic/general/SConscript'],'env')
516
517 env.SConscript(['base/generic/utilities/SConscript'],'env')
518
519 env.SConscript(['base/generic/compiler/SConscript'],'env')
520
521 env.SConscript(['base/generic/solver/SConscript'],'env')
522
523 env.SConscript(['base/generic/packages/SConscript'],'env')
524
525 if with_tcltk_gui:
526 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
527 else:
528 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
529
530 if with_python:
531 env.SConscript(['pygtk/interface/SConscript'],'env')
532 else:
533 print "Skipping... Python GUI isn't being built"
534
535 if with_cunit_tests:
536 testdirs = ['general','solver','utilities']
537 for testdir in testdirs:
538 path = 'base/generic/'+testdir+'/test/'
539 env.SConscript([path+'SConscript'],'env')
540 env.SConscript(['test/SConscript'],'env')
541 env.SConscript(['base/generic/test/SConscript'],'env')
542
543
544 else:
545 print "Skipping... CUnit tests aren't being built"
546
547 #------------------------------------------------------
548 # INSTALLATION
549
550 # TODO: add install options

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