/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 405 - (hide annotations) (download)
Sat Apr 1 05:54:19 2006 UTC (13 years, 8 months ago) by johnpye
File size: 13997 byte(s)
Added Tk detection, improved reporting
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    
153 johnpye 400 with_cunit_tests = env['WITH_CUNIT_TESTS']
154    
155 johnpye 392 print "SOLVERS:",env['WITH_SOLVERS']
156 johnpye 393
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 johnpye 385 #------------------------------------------------------
175 johnpye 398 # SPECIAL CONFIGURATION TESTS
176    
177 johnpye 400 #----------------
178     # SWIG
179    
180 johnpye 398 import os,re
181    
182     def CheckSwigVersion(context):
183 johnpye 405 context.Message("Checking version of SWIG... ")
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 403 context.Result("error running SWIG or detecting SWIG version")
193 johnpye 398 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 johnpye 400 min > 3
200     or (min == 3 and pat >= 24)
201 johnpye 398 ):
202     context.Result("ok, %d.%d.%d" % (maj,min,pat))
203     return 1;
204 johnpye 401 else:
205     context.Result("too old, %d.%d.%d" % (maj,min,pat))
206     return 0;
207 johnpye 398
208 johnpye 400 #----------------
209     # General purpose library-and-header test
210    
211 johnpye 404 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 johnpye 400
222 johnpye 404 cpppath_add = []
223     if context.env.has_key(varprefix+'_CPPPATH'):
224     cpppath_add = [env[varprefix+'_CPPPATH']]
225 johnpye 405
226     context.env.Append(
227     LIBPATH = libpath_add
228     , CPPPATH = cpppath_add
229     )
230 johnpye 404
231     def restore(self,context):
232     for k in self.keep:
233     context.env[k]=self.keep[k];
234    
235 johnpye 400 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 johnpye 405 context.Message( 'Checking for '+libname+'... ' )
242 johnpye 400
243     if varprefix==None:
244     varprefix = libname.upper()
245    
246 johnpye 404 keep = KeepContext(context,varprefix)
247 johnpye 400
248 johnpye 405 context.env.Append(LIBS=[libname])
249    
250 johnpye 404 is_ok = context.TryLink(text,ext)
251 johnpye 400
252 johnpye 405 keep.restore(context)
253 johnpye 400
254 johnpye 404 context.Result(is_ok)
255     return is_ok
256    
257     #----------------
258     # CUnit test
259    
260 johnpye 400 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 johnpye 404 return 0;
275 johnpye 400 }
276     """
277    
278     def CheckCUnit(context):
279 johnpye 404 return CheckLib(context
280 johnpye 400 ,'cunit'
281     ,cunit_test_text
282     )
283    
284 johnpye 404 #----------------
285 johnpye 405 # Tcl test
286 johnpye 404
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 johnpye 405 return CheckExtLib(context,'tcl',tcl_check_text)
300    
301     def CheckTclVersion(context):
302 johnpye 404 keep = KeepContext(context,'TCL')
303 johnpye 405 context.Message("Checking Tcl version... ")
304     (is_ok,output) = context.TryRun(tcl_check_text,'.c')
305 johnpye 404 keep.restore(context)
306     if not is_ok:
307 johnpye 405 context.Result("failed to run check")
308 johnpye 404 return 0
309 johnpye 405 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 johnpye 404 return 1
318    
319 johnpye 405 #----------------
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 johnpye 404 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 johnpye 400
348 johnpye 404 # good version
349     return 1
350    
351 johnpye 398 #------------------------------------------------------
352 johnpye 385 # CONFIGURATION
353    
354     conf = Configure(env
355     , custom_tests = {
356 johnpye 398 'CheckSwigVersion' : CheckSwigVersion
357 johnpye 400 , 'CheckCUnit' : CheckCUnit
358 johnpye 404 , 'CheckTcl' : CheckTcl
359     , 'CheckTclVersion' : CheckTclVersion
360 johnpye 405 , 'CheckTk' : CheckTk
361     , 'CheckTkVersion' : CheckTkVersion
362 johnpye 400 # , 'CheckIsNan' : CheckIsNan
363     # , 'CheckCppUnitConfig' : CheckCppUnitConfig
364 johnpye 385 }
365     , config_h = "config.h"
366     )
367    
368 johnpye 398 if not conf.CheckSwigVersion():
369     print 'SWIG version is not OK'
370     Exit(1)
371    
372 johnpye 385 # 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 johnpye 387 # Tcl/Tk
384 johnpye 386
385 johnpye 405 if conf.CheckTcl() and conf.CheckTk():
386 johnpye 404 if with_tcltk_gui and not conf.CheckTclVersion():
387 johnpye 405 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
388 johnpye 404 with_tcltk_gui = False
389 johnpye 386
390 johnpye 405 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 johnpye 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 johnpye 391 if platform.system()=="Windows":
399 johnpye 395 python_lib='python24'
400 johnpye 391 else:
401 johnpye 395 python_lib='python2.4'
402 johnpye 391
403 johnpye 395 # SWIG version
404    
405 johnpye 396 if platform.system()=="Windows":
406 johnpye 398 #env['SWIG']=['c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe']
407 johnpye 396 env['ENV']['SWIGFEATURES']='-O'
408     else:
409     env['ENV']['SWIGFEATURES']='-O'
410 johnpye 395
411 johnpye 400 # CUnit
412    
413     if with_cunit_tests:
414 johnpye 404 if not conf.CheckCUnit():
415     print "CUnit not found. Use 'scons WITH_CUNIT_TESTS=0'"
416     Exit(1)
417 johnpye 400
418 johnpye 385 # TODO: -D_HPUX_SOURCE is needed
419    
420     # TODO: check size of void*
421    
422 johnpye 393 # TODO: detect if dynamic libraries are possible or not
423    
424 johnpye 395 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 johnpye 396 if not with_python:
431     print "Can't build python interface"
432     Exit(1)
433    
434 johnpye 385 #------------------------------------------------------
435 johnpye 393 # RECIPE: 'SubstInFile', used in pygtk SConscript
436    
437     import re
438 johnpye 395 from SCons.Script import * # the usual scons stuff you get in a SConscript
439 johnpye 393
440 johnpye 395 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 johnpye 393 """
450 johnpye 395 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 johnpye 393
472 johnpye 395 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 johnpye 393
486 johnpye 395 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 johnpye 393
491 johnpye 395 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 johnpye 393
504 johnpye 395 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 johnpye 393 #------------------------------------------------------
510 johnpye 385 # SUBDIRECTORIES....
511    
512 johnpye 393
513 johnpye 385 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 johnpye 386
525     if with_tcltk_gui:
526     env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
527 johnpye 391 else:
528 johnpye 405 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
529 johnpye 386
530 johnpye 387 if with_python:
531     env.SConscript(['pygtk/interface/SConscript'],'env')
532 johnpye 391 else:
533     print "Skipping... Python GUI isn't being built"
534 johnpye 400
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