/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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