/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 415 - (hide annotations) (download)
Mon Apr 3 04:56:45 2006 UTC (14 years ago) by johnpye
File size: 14254 byte(s)
Small correction to keep MinGW build working
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 johnpye 415 if platform.system()=='Windows' and env.has_key('MSVS'):
16 johnpye 414 print "INCLUDE =",env['ENV']['INCLUDE']
17     env.Append(CPPPATH=env['ENV']['INCLUDE'])
18     env.Append(LIBPATH=env['ENV']['LIB'])
19    
20 johnpye 385 # Package linking option
21 johnpye 386 opts.Add(EnumOption(
22     'PACKAGE_LINKING'
23 johnpye 385 , 'Style of linking for external libraries'
24     , 'DYNAMIC_PACKAGES'
25 johnpye 386 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
26     ))
27 johnpye 385
28 johnpye 392 # You can turn off building of Tcl/Tk interface
29 johnpye 386 opts.Add(BoolOption(
30     'WITHOUT_TCLTK_GUI'
31     ,"Set to True if you don't want to build the original Tcl/Tk GUI."
32     , False
33     ))
34    
35 johnpye 392 # You can turn off the building of the Python interface
36 johnpye 387 opts.Add(BoolOption(
37     'WITHOUT_PYTHON'
38     ,"Set to True if you don't want to build Python wrappers."
39     , False
40     ))
41    
42 johnpye 392 # Which solvers will we allow?
43     opts.Add(ListOption(
44     'WITH_SOLVERS'
45 johnpye 393 ,"List of the solvers you want to build. The default is the minimum that"
46     +" works."
47 johnpye 392 ,["QRSLV","CMSLV"]
48     ,['QRSLV','MPS','SLV','OPTSQP'
49     ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
50     ,'LSOD','OPTSQP'
51     ]
52     ))
53    
54 johnpye 393 # Where will the local copy of the help files be kept?
55     opts.Add(PackageOption(
56     'WITH_LOCAL_HELP'
57     , "Directory containing the local copy of the help files (optional)"
58     , "no"
59     ))
60    
61     # Will bintoken support be enabled?
62     opts.Add(BoolOption(
63     'WITH_BINTOKEN'
64     ,"Enable bintoken support? This means compiling models as C-code before"
65     +" running them, to increase solving speed for large models."
66     ,False
67     ))
68    
69 johnpye 398 # What should the default ASCENDLIBRARY path be?
70     # Note: users can change it by editing their ~/.ascend.ini
71 johnpye 393 opts.Add(
72     'DEFAULT_ASCENDLIBRARY'
73     ,"Set the default value of the ASCENDLIBRARY -- the location where"
74     +" ASCEND will look for models when running ASCEND"
75     ,os.path.expanduser("~/src/ascend/trunk/models")
76     )
77    
78 johnpye 398 # Where is SWIG?
79     opts.Add(
80     'SWIG'
81     ,"SWIG location, probably only required for MinGW and MSVC users."
82     +" Enter the location as a Windows-style path, for example"
83 johnpye 404 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
84 johnpye 398 )
85    
86 johnpye 400 # Build the test suite?
87     opts.Add(BoolOption(
88     'WITH_CUNIT_TESTS'
89     ,"Whether to build the CUnit tests. Default is off. If set to on,"
90     +" you must have CUnit installed somewhere that SCons can"
91     +" find it."
92     ,False
93     ))
94 johnpye 393
95 johnpye 400 # Where are the CUnit includes?
96     opts.Add(PackageOption(
97     'CUNIT_CPPPATH'
98     ,"Where are your CUnit include files?"
99     ,"off"
100     ))
101 johnpye 392
102 johnpye 404 # Where are the CUnit libraries?
103 johnpye 400 opts.Add(PackageOption(
104     'CUNIT_LIBPATH'
105 johnpye 404 ,"Where are your CUnit libraries?"
106 johnpye 400 ,"off"
107     ))
108    
109 johnpye 404 # Where are the Tcl includes?
110     opts.Add(PackageOption(
111     'TCL_CPPPATH'
112     ,"Where are your Tcl include files?"
113     ,None
114     ))
115    
116     # Where are the Tcl libs?
117     opts.Add(PackageOption(
118     'TCL_LIBPATH'
119     ,"Where are your Tcl libraries?"
120     ,None
121     ))
122    
123 johnpye 405 # Where are the Tk includes?
124     opts.Add(PackageOption(
125     'TK_CPPPATH'
126     ,"Where are your Tk include files?"
127     ,None
128     ))
129 johnpye 404
130 johnpye 405 # Where are the Tk libs?
131     opts.Add(PackageOption(
132     'TK_LIBPATH'
133     ,"Where are your Tk libraries?"
134     ,None
135     ))
136    
137    
138 johnpye 392 # TODO: OTHER OPTIONS?
139    
140     # TODO: flags for optimisation
141    
142 johnpye 393 # TODO: turning on/off bintoken functionality
143    
144 johnpye 400 # TODO: Where will the 'Makefile.bt' file be installed
145     # ....
146    
147 johnpye 385 opts.Update(env)
148     opts.Save('options.cache',env)
149    
150     Help(opts.GenerateHelpText(env))
151    
152     env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
153    
154 johnpye 386 with_tcltk_gui = (env['WITHOUT_TCLTK_GUI']==False)
155    
156 johnpye 387 with_python = (env['WITHOUT_PYTHON']==False)
157 johnpye 413 without_python_reason = None
158 johnpye 387
159 johnpye 400 with_cunit_tests = env['WITH_CUNIT_TESTS']
160    
161 johnpye 392 print "SOLVERS:",env['WITH_SOLVERS']
162 johnpye 393
163     print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
164     print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
165     print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
166    
167     subst_dict = {
168     '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
169     , '@GLADE_FILE@':'glade/ascend.glade'
170     , '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
171     , '@ASCEND_ICON@':'glade/ascend.png'
172     , '@HELP_ROOT@':''
173     }
174    
175     if env['WITH_LOCAL_HELP']:
176     subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
177    
178     env.Append(SUBST_DICT=subst_dict)
179    
180 johnpye 385 #------------------------------------------------------
181 johnpye 398 # SPECIAL CONFIGURATION TESTS
182    
183 johnpye 400 #----------------
184     # SWIG
185    
186 johnpye 398 import os,re
187    
188 johnpye 413 def get_swig_version(env):
189 johnpye 403 cmd = env['SWIG']+' -version'
190     (cin,coutcerr) = os.popen4(cmd);
191     output = coutcerr.read()
192 johnpye 398
193 johnpye 403 restr = "SWIG\\s+Version\\s+(?P<maj>[0-9]+)\\.(?P<min>[0-9]+)\\.(?P<pat>[0-9]+)\\s*$"
194     expr = re.compile(restr,re.M);
195 johnpye 398 m = expr.search(output);
196     if not m:
197 johnpye 413 return None
198 johnpye 398 maj = int(m.group('maj'))
199     min = int(m.group('min'))
200     pat = int(m.group('pat'))
201 johnpye 413
202     return (maj,min,pat)
203 johnpye 398
204 johnpye 413
205     def CheckSwigVersion(context):
206    
207     try:
208     context.Message("Checking version of SWIG... ")
209     maj,min,pat = get_swig_version(context.env)
210     except:
211     context.Result("Failed to detect version, or failed to run SWIG")
212     return 0;
213    
214 johnpye 398 if maj == 1 and (
215 johnpye 400 min > 3
216     or (min == 3 and pat >= 24)
217 johnpye 398 ):
218     context.Result("ok, %d.%d.%d" % (maj,min,pat))
219     return 1;
220 johnpye 401 else:
221     context.Result("too old, %d.%d.%d" % (maj,min,pat))
222     return 0;
223 johnpye 398
224 johnpye 400 #----------------
225     # General purpose library-and-header test
226    
227 johnpye 404 class KeepContext:
228     def __init__(self,context,varprefix):
229     self.keep = {}
230     for k in ['LIBS','LIBPATH','CPPPATH']:
231     if context.env.has_key(k):
232     self.keep[k] = context.env[k]
233    
234     libpath_add = []
235     if context.env.has_key(varprefix+'_LIBPATH'):
236     libpath_add = [env[varprefix+'_LIBPATH']]
237 johnpye 400
238 johnpye 404 cpppath_add = []
239     if context.env.has_key(varprefix+'_CPPPATH'):
240     cpppath_add = [env[varprefix+'_CPPPATH']]
241 johnpye 405
242     context.env.Append(
243     LIBPATH = libpath_add
244     , CPPPATH = cpppath_add
245     )
246 johnpye 404
247     def restore(self,context):
248     for k in self.keep:
249     context.env[k]=self.keep[k];
250    
251 johnpye 400 def CheckExtLib(context,libname,text,ext='.c',varprefix=None):
252     """This method will check for variables LIBNAME_LIBPATH
253     and LIBNAME_CPPPATH and try to compile and link the
254     file with the provided text, linking with the
255     library libname."""
256    
257 johnpye 405 context.Message( 'Checking for '+libname+'... ' )
258 johnpye 400
259     if varprefix==None:
260     varprefix = libname.upper()
261    
262 johnpye 404 keep = KeepContext(context,varprefix)
263 johnpye 400
264 johnpye 405 context.env.Append(LIBS=[libname])
265    
266 johnpye 404 is_ok = context.TryLink(text,ext)
267 johnpye 400
268 johnpye 405 keep.restore(context)
269 johnpye 400
270 johnpye 404 context.Result(is_ok)
271     return is_ok
272    
273     #----------------
274     # CUnit test
275    
276 johnpye 400 cunit_test_text = """
277     #include <CUnit/Cunit.h>
278     int maxi(int i1, int i2){
279     return (i1 > i2) ? i1 : i2;
280     }
281    
282     void test_maxi(void){
283     CU_ASSERT(maxi(0,2) == 2);
284     CU_ASSERT(maxi(0,-2) == 0);
285     CU_ASSERT(maxi(2,2) == 2);
286    
287     }
288     int main(void){
289     /* CU_initialize_registry() */
290 johnpye 404 return 0;
291 johnpye 400 }
292     """
293    
294     def CheckCUnit(context):
295 johnpye 412 return context.CheckExtLib(context
296 johnpye 400 ,'cunit'
297     ,cunit_test_text
298     )
299    
300 johnpye 404 #----------------
301 johnpye 405 # Tcl test
302 johnpye 404
303     tcl_check_text = r"""
304     #include <tcl.h>
305     #include <stdio.h>
306     int main(void){
307     printf("%s",TCL_PATCH_LEVEL);
308     return 0;
309     }
310     """
311    
312     def CheckTcl(context):
313 johnpye 405 return CheckExtLib(context,'tcl',tcl_check_text)
314    
315     def CheckTclVersion(context):
316 johnpye 404 keep = KeepContext(context,'TCL')
317 johnpye 405 context.Message("Checking Tcl version... ")
318     (is_ok,output) = context.TryRun(tcl_check_text,'.c')
319 johnpye 404 keep.restore(context)
320     if not is_ok:
321 johnpye 405 context.Result("failed to run check")
322 johnpye 404 return 0
323 johnpye 405 context.Result(output)
324    
325     major,minor,patch = tuple(int(i) for i in output.split("."))
326     if major != 8 or minor > 3:
327     # bad version
328     return 0
329    
330     # good version
331 johnpye 404 return 1
332    
333 johnpye 405 #----------------
334     # Tcl test
335    
336     tk_check_text = r"""
337     #include <tk.h>
338     #include <stdio.h>
339     int main(void){
340     printf("%s",TK_PATCH_LEVEL);
341     return 0;
342     }
343     """
344     def CheckTk(context):
345     return CheckExtLib(context,'tk',tk_check_text)
346    
347     def CheckTkVersion(context):
348     keep = KeepContext(context,'TK')
349     context.Message("Checking Tk version... ")
350     (is_ok,output) = context.TryRun(tk_check_text,'.c')
351 johnpye 404 keep.restore(context)
352     if not is_ok:
353     context.Result("failed to run check")
354     return 0
355     context.Result(output)
356    
357     major,minor,patch = tuple(int(i) for i in output.split("."))
358     if major != 8 or minor > 3:
359     # bad version
360     return 0
361 johnpye 400
362 johnpye 404 # good version
363     return 1
364    
365 johnpye 398 #------------------------------------------------------
366 johnpye 385 # CONFIGURATION
367    
368     conf = Configure(env
369     , custom_tests = {
370 johnpye 398 'CheckSwigVersion' : CheckSwigVersion
371 johnpye 400 , 'CheckCUnit' : CheckCUnit
372 johnpye 404 , 'CheckTcl' : CheckTcl
373     , 'CheckTclVersion' : CheckTclVersion
374 johnpye 405 , 'CheckTk' : CheckTk
375     , 'CheckTkVersion' : CheckTkVersion
376 johnpye 400 # , 'CheckIsNan' : CheckIsNan
377     # , 'CheckCppUnitConfig' : CheckCppUnitConfig
378 johnpye 385 }
379     , config_h = "config.h"
380     )
381    
382 johnpye 398
383 johnpye 385 # Math library
384 johnpye 414 if not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
385     print 'Did not find math library, exiting!'
386     Exit(1)
387 johnpye 385
388     # Where is 'isnan'?
389    
390     if not conf.CheckFunc('isnan'):
391     print "Didn't find isnan"
392 johnpye 414 # Exit(1)
393 johnpye 385
394 johnpye 387 # Tcl/Tk
395 johnpye 386
396 johnpye 405 if conf.CheckTcl() and conf.CheckTk():
397 johnpye 404 if with_tcltk_gui and not conf.CheckTclVersion():
398 johnpye 405 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
399 johnpye 404 with_tcltk_gui = False
400 johnpye 386
401 johnpye 405 if with_tcltk_gui and not conf.CheckTkVersion():
402     without_tcltk_reason += "Require Tk version <= 8.3. See 'scons -h'"
403     with_tcltk_gui = False
404     else:
405     without_tcltk_reason = "Tcl/Tk not found."
406 johnpye 412 with_tcltk_gui = False
407    
408 johnpye 395 # Python... obviously we're already running python, so we just need to
409     # check that we can link to the python library OK:
410    
411 johnpye 391 if platform.system()=="Windows":
412 johnpye 395 python_lib='python24'
413 johnpye 391 else:
414 johnpye 395 python_lib='python2.4'
415 johnpye 391
416 johnpye 395 # SWIG version
417    
418 johnpye 396 if platform.system()=="Windows":
419     env['ENV']['SWIGFEATURES']='-O'
420     else:
421     env['ENV']['SWIGFEATURES']='-O'
422 johnpye 395
423 johnpye 413
424     if not conf.CheckSwigVersion():
425     without_python_reason = 'SWIG >= 1.3.24 is required'
426     with_python = False
427    
428 johnpye 400 # CUnit
429    
430     if with_cunit_tests:
431 johnpye 404 if not conf.CheckCUnit():
432     print "CUnit not found. Use 'scons WITH_CUNIT_TESTS=0'"
433     Exit(1)
434 johnpye 400
435 johnpye 385 # TODO: -D_HPUX_SOURCE is needed
436    
437     # TODO: check size of void*
438    
439 johnpye 393 # TODO: detect if dynamic libraries are possible or not
440    
441 johnpye 395 conf.Finish()
442    
443     env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
444     env.Append(PYTHON_LIB=[python_lib])
445     env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
446    
447 johnpye 385 #------------------------------------------------------
448 johnpye 393 # RECIPE: 'SubstInFile', used in pygtk SConscript
449    
450     import re
451 johnpye 395 from SCons.Script import * # the usual scons stuff you get in a SConscript
452 johnpye 393
453 johnpye 395 def TOOL_SUBST(env):
454     """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
455     from the source to the target.
456     The values of SUBST_DICT first have any construction variables expanded
457     (its keys are not expanded).
458     If a value of SUBST_DICT is a python callable function, it is called and
459     the result is expanded as the value.
460     If there's more than one source and more than one target, each target gets
461     substituted from the corresponding source.
462 johnpye 393 """
463 johnpye 395 env.Append(TOOLS = 'SUBST')
464     def do_subst_in_file(targetfile, sourcefile, dict):
465     """Replace all instances of the keys of dict with their values.
466     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
467     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
468     """
469     try:
470     f = open(sourcefile, 'rb')
471     contents = f.read()
472     f.close()
473     except:
474     raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
475     for (k,v) in dict.items():
476     contents = re.sub(k, v, contents)
477     try:
478     f = open(targetfile, 'wb')
479     f.write(contents)
480     f.close()
481     except:
482     raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
483     return 0 # success
484 johnpye 393
485 johnpye 395 def subst_in_file(target, source, env):
486     if not env.has_key('SUBST_DICT'):
487     raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
488     d = dict(env['SUBST_DICT']) # copy it
489     for (k,v) in d.items():
490     if callable(v):
491     d[k] = env.subst(v())
492     elif SCons.Util.is_String(v):
493     d[k]=env.subst(v)
494     else:
495     raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
496     for (t,s) in zip(target, source):
497     return do_subst_in_file(str(t), str(s), d)
498 johnpye 393
499 johnpye 395 def subst_in_file_string(target, source, env):
500     """This is what gets printed on the console."""
501     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
502     for (t,s) in zip(target, source)])
503 johnpye 393
504 johnpye 395 def subst_emitter(target, source, env):
505     """Add dependency from substituted SUBST_DICT to target.
506     Returns original target, source tuple unchanged.
507     """
508     d = env['SUBST_DICT'].copy() # copy it
509     for (k,v) in d.items():
510     if callable(v):
511     d[k] = env.subst(v())
512     elif SCons.Util.is_String(v):
513     d[k]=env.subst(v)
514     Depends(target, SCons.Node.Python.Value(d))
515     return target, source
516 johnpye 393
517 johnpye 395 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
518     env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
519    
520     TOOL_SUBST(env)
521    
522 johnpye 393 #------------------------------------------------------
523 johnpye 385 # SUBDIRECTORIES....
524    
525 johnpye 393
526 johnpye 385 env.Append(CPPPATH=['..'])
527    
528     env.SConscript(['base/generic/general/SConscript'],'env')
529    
530     env.SConscript(['base/generic/utilities/SConscript'],'env')
531    
532     env.SConscript(['base/generic/compiler/SConscript'],'env')
533    
534     env.SConscript(['base/generic/solver/SConscript'],'env')
535    
536     env.SConscript(['base/generic/packages/SConscript'],'env')
537 johnpye 386
538     if with_tcltk_gui:
539     env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
540 johnpye 391 else:
541 johnpye 405 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
542 johnpye 386
543 johnpye 387 if with_python:
544     env.SConscript(['pygtk/interface/SConscript'],'env')
545 johnpye 391 else:
546 johnpye 413 print "Skipping... Python GUI isn't being built:",without_python_reason
547 johnpye 400
548     if with_cunit_tests:
549     testdirs = ['general','solver','utilities']
550     for testdir in testdirs:
551     path = 'base/generic/'+testdir+'/test/'
552     env.SConscript([path+'SConscript'],'env')
553     env.SConscript(['test/SConscript'],'env')
554     env.SConscript(['base/generic/test/SConscript'],'env')
555    
556    
557     else:
558     print "Skipping... CUnit tests aren't being built"
559    
560     #------------------------------------------------------
561     # INSTALLATION
562    
563     # TODO: add install options

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