/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 413 - (hide 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 johnpye 393 import os, commands, platform, distutils.sysconfig, os.path
2 johnpye 385
3     #------------------------------------------------------
4     # OPTIONS
5 johnpye 392 #
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 johnpye 385
9     opts = Options(['options.cache', 'config.py'])
10     print "PLATFORM = ",platform.system()
11    
12 johnpye 392 # Import the outside environment
13     env = Environment(ENV=os.environ)
14 johnpye 385
15     # Package linking option
16 johnpye 386 opts.Add(EnumOption(
17     'PACKAGE_LINKING'
18 johnpye 385 , 'Style of linking for external libraries'
19     , 'DYNAMIC_PACKAGES'
20 johnpye 386 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
21     ))
22 johnpye 385
23 johnpye 392 # You can turn off building of Tcl/Tk interface
24 johnpye 386 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 johnpye 392 # You can turn off the building of the Python interface
31 johnpye 387 opts.Add(BoolOption(
32     'WITHOUT_PYTHON'
33     ,"Set to True if you don't want to build Python wrappers."
34     , False
35     ))
36    
37 johnpye 392 # Which solvers will we allow?
38     opts.Add(ListOption(
39     'WITH_SOLVERS'
40 johnpye 393 ,"List of the solvers you want to build. The default is the minimum that"
41     +" works."
42 johnpye 392 ,["QRSLV","CMSLV"]
43     ,['QRSLV','MPS','SLV','OPTSQP'
44     ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
45     ,'LSOD','OPTSQP'
46     ]
47     ))
48    
49 johnpye 393 # 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 johnpye 398 # What should the default ASCENDLIBRARY path be?
65     # Note: users can change it by editing their ~/.ascend.ini
66 johnpye 393 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 johnpye 398 # 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 johnpye 404 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
79 johnpye 398 )
80    
81 johnpye 400 # 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 johnpye 393
90 johnpye 400 # Where are the CUnit includes?
91     opts.Add(PackageOption(
92     'CUNIT_CPPPATH'
93     ,"Where are your CUnit include files?"
94     ,"off"
95     ))
96 johnpye 392
97 johnpye 404 # Where are the CUnit libraries?
98 johnpye 400 opts.Add(PackageOption(
99     'CUNIT_LIBPATH'
100 johnpye 404 ,"Where are your CUnit libraries?"
101 johnpye 400 ,"off"
102     ))
103    
104 johnpye 404 # 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 johnpye 405 # Where are the Tk includes?
119     opts.Add(PackageOption(
120     'TK_CPPPATH'
121     ,"Where are your Tk include files?"
122     ,None
123     ))
124 johnpye 404
125 johnpye 405 # Where are the Tk libs?
126     opts.Add(PackageOption(
127     'TK_LIBPATH'
128     ,"Where are your Tk libraries?"
129     ,None
130     ))
131    
132    
133 johnpye 392 # TODO: OTHER OPTIONS?
134    
135     # TODO: flags for optimisation
136    
137 johnpye 393 # TODO: turning on/off bintoken functionality
138    
139 johnpye 400 # TODO: Where will the 'Makefile.bt' file be installed
140     # ....
141    
142 johnpye 385 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 johnpye 386 with_tcltk_gui = (env['WITHOUT_TCLTK_GUI']==False)
150    
151 johnpye 387 with_python = (env['WITHOUT_PYTHON']==False)
152 johnpye 413 without_python_reason = None
153 johnpye 387
154 johnpye 400 with_cunit_tests = env['WITH_CUNIT_TESTS']
155    
156 johnpye 392 print "SOLVERS:",env['WITH_SOLVERS']
157 johnpye 393
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 johnpye 385 #------------------------------------------------------
176 johnpye 398 # SPECIAL CONFIGURATION TESTS
177    
178 johnpye 400 #----------------
179     # SWIG
180    
181 johnpye 398 import os,re
182    
183 johnpye 413 def get_swig_version(env):
184 johnpye 403 cmd = env['SWIG']+' -version'
185     (cin,coutcerr) = os.popen4(cmd);
186     output = coutcerr.read()
187 johnpye 398
188 johnpye 403 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 johnpye 398 m = expr.search(output);
191     if not m:
192 johnpye 413 return None
193 johnpye 398 maj = int(m.group('maj'))
194     min = int(m.group('min'))
195     pat = int(m.group('pat'))
196 johnpye 413
197     return (maj,min,pat)
198 johnpye 398
199 johnpye 413
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 johnpye 398 if maj == 1 and (
210 johnpye 400 min > 3
211     or (min == 3 and pat >= 24)
212 johnpye 398 ):
213     context.Result("ok, %d.%d.%d" % (maj,min,pat))
214     return 1;
215 johnpye 401 else:
216     context.Result("too old, %d.%d.%d" % (maj,min,pat))
217     return 0;
218 johnpye 398
219 johnpye 400 #----------------
220     # General purpose library-and-header test
221    
222 johnpye 404 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 johnpye 400
233 johnpye 404 cpppath_add = []
234     if context.env.has_key(varprefix+'_CPPPATH'):
235     cpppath_add = [env[varprefix+'_CPPPATH']]
236 johnpye 405
237     context.env.Append(
238     LIBPATH = libpath_add
239     , CPPPATH = cpppath_add
240     )
241 johnpye 404
242     def restore(self,context):
243     for k in self.keep:
244     context.env[k]=self.keep[k];
245    
246 johnpye 400 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 johnpye 405 context.Message( 'Checking for '+libname+'... ' )
253 johnpye 400
254     if varprefix==None:
255     varprefix = libname.upper()
256    
257 johnpye 404 keep = KeepContext(context,varprefix)
258 johnpye 400
259 johnpye 405 context.env.Append(LIBS=[libname])
260    
261 johnpye 404 is_ok = context.TryLink(text,ext)
262 johnpye 400
263 johnpye 405 keep.restore(context)
264 johnpye 400
265 johnpye 404 context.Result(is_ok)
266     return is_ok
267    
268     #----------------
269     # CUnit test
270    
271 johnpye 400 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 johnpye 404 return 0;
286 johnpye 400 }
287     """
288    
289     def CheckCUnit(context):
290 johnpye 412 return context.CheckExtLib(context
291 johnpye 400 ,'cunit'
292     ,cunit_test_text
293     )
294    
295 johnpye 404 #----------------
296 johnpye 405 # Tcl test
297 johnpye 404
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 johnpye 405 return CheckExtLib(context,'tcl',tcl_check_text)
309    
310     def CheckTclVersion(context):
311 johnpye 404 keep = KeepContext(context,'TCL')
312 johnpye 405 context.Message("Checking Tcl version... ")
313     (is_ok,output) = context.TryRun(tcl_check_text,'.c')
314 johnpye 404 keep.restore(context)
315     if not is_ok:
316 johnpye 405 context.Result("failed to run check")
317 johnpye 404 return 0
318 johnpye 405 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 johnpye 404 return 1
327    
328 johnpye 405 #----------------
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 johnpye 404 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 johnpye 400
357 johnpye 404 # good version
358     return 1
359    
360 johnpye 398 #------------------------------------------------------
361 johnpye 385 # CONFIGURATION
362    
363     conf = Configure(env
364     , custom_tests = {
365 johnpye 398 'CheckSwigVersion' : CheckSwigVersion
366 johnpye 400 , 'CheckCUnit' : CheckCUnit
367 johnpye 404 , 'CheckTcl' : CheckTcl
368     , 'CheckTclVersion' : CheckTclVersion
369 johnpye 405 , 'CheckTk' : CheckTk
370     , 'CheckTkVersion' : CheckTkVersion
371 johnpye 400 # , 'CheckIsNan' : CheckIsNan
372     # , 'CheckCppUnitConfig' : CheckCppUnitConfig
373 johnpye 385 }
374     , config_h = "config.h"
375     )
376    
377 johnpye 398
378 johnpye 385 # Math library
379 johnpye 412 #if not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
380     # print 'Did not find math library, exiting!'
381     # Exit(1)
382 johnpye 385
383     # Where is 'isnan'?
384    
385     if not conf.CheckFunc('isnan'):
386     print "Didn't find isnan"
387     Exit(1)
388    
389 johnpye 387 # Tcl/Tk
390 johnpye 386
391 johnpye 405 if conf.CheckTcl() and conf.CheckTk():
392 johnpye 404 if with_tcltk_gui and not conf.CheckTclVersion():
393 johnpye 405 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
394 johnpye 404 with_tcltk_gui = False
395 johnpye 386
396 johnpye 405 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 johnpye 412 with_tcltk_gui = False
402    
403 johnpye 395 # 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 johnpye 391 if platform.system()=="Windows":
407 johnpye 395 python_lib='python24'
408 johnpye 391 else:
409 johnpye 395 python_lib='python2.4'
410 johnpye 391
411 johnpye 395 # SWIG version
412    
413 johnpye 396 if platform.system()=="Windows":
414     env['ENV']['SWIGFEATURES']='-O'
415     else:
416     env['ENV']['SWIGFEATURES']='-O'
417 johnpye 395
418 johnpye 413
419     if not conf.CheckSwigVersion():
420     without_python_reason = 'SWIG >= 1.3.24 is required'
421     with_python = False
422    
423 johnpye 400 # CUnit
424    
425     if with_cunit_tests:
426 johnpye 404 if not conf.CheckCUnit():
427     print "CUnit not found. Use 'scons WITH_CUNIT_TESTS=0'"
428     Exit(1)
429 johnpye 400
430 johnpye 385 # TODO: -D_HPUX_SOURCE is needed
431    
432     # TODO: check size of void*
433    
434 johnpye 393 # TODO: detect if dynamic libraries are possible or not
435    
436 johnpye 395 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 johnpye 385 #------------------------------------------------------
443 johnpye 393 # RECIPE: 'SubstInFile', used in pygtk SConscript
444    
445     import re
446 johnpye 395 from SCons.Script import * # the usual scons stuff you get in a SConscript
447 johnpye 393
448 johnpye 395 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 johnpye 393 """
458 johnpye 395 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 johnpye 393
480 johnpye 395 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 johnpye 393
494 johnpye 395 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 johnpye 393
499 johnpye 395 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 johnpye 393
512 johnpye 395 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 johnpye 393 #------------------------------------------------------
518 johnpye 385 # SUBDIRECTORIES....
519    
520 johnpye 393
521 johnpye 385 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 johnpye 386
533     if with_tcltk_gui:
534     env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
535 johnpye 391 else:
536 johnpye 405 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
537 johnpye 386
538 johnpye 387 if with_python:
539     env.SConscript(['pygtk/interface/SConscript'],'env')
540 johnpye 391 else:
541 johnpye 413 print "Skipping... Python GUI isn't being built:",without_python_reason
542 johnpye 400
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