/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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