/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 478 - (hide annotations) (download)
Mon Apr 17 08:10:48 2006 UTC (13 years, 11 months ago) by johnpye
File size: 26696 byte(s)
Fixing build for SWIG 1.3.24 (no -O flag)
Adding more debug info to loading output in PyGTK interface/config.py.in
Adding SWIGVERSION flag to SCons env.
Commenting in ascDynaLoad.c and ascParse.y
Adding VERSION to config.py
1 johnpye 393 import os, commands, platform, distutils.sysconfig, os.path
2 johnpye 385
3 johnpye 439 version = "0.9.6rc0"
4    
5 johnpye 385 #------------------------------------------------------
6     # OPTIONS
7 johnpye 392 #
8     # Note that if you set the options via the command line, they will be
9     # remembered in the file 'options.cache'. It's a feature ;-)
10 johnpye 385
11     opts = Options(['options.cache', 'config.py'])
12 johnpye 464 #print "PLATFORM = ",platform.system()
13 johnpye 385
14 johnpye 392 # Import the outside environment
15     env = Environment(ENV=os.environ)
16 johnpye 463
17 johnpye 415 if platform.system()=='Windows' and env.has_key('MSVS'):
18 johnpye 414 print "INCLUDE =",env['ENV']['INCLUDE']
19 johnpye 416 print "LIB =",env['ENV']['LIB']
20     print "LINK =",env['LINK']
21     print "LINKCOM =",env['LINKCOM']
22     print "AR =",env['AR']
23     print "ARCOM =",env['ARCOM']
24 johnpye 427 #env['AR']='link /lib'
25 johnpye 414 env.Append(CPPPATH=env['ENV']['INCLUDE'])
26     env.Append(LIBPATH=env['ENV']['LIB'])
27 johnpye 427 env.Append(CPPDEFINES=['_CRT_SECURE_NO_DEPRECATED','_CRT_SECURE_NO_DEPRECATE'])
28 johnpye 414
29 johnpye 464 if platform.system()=="Windows":
30     default_tcl_lib = "tcl83"
31     default_tk_lib = "tk83"
32     default_tktable_lib = "Tktable28"
33     else:
34     default_tcl_lib = "tcl"
35     default_tk_lib = "tk"
36     default_tktable_lib = "Tktable2.8"
37 johnpye 463
38    
39 johnpye 385 # Package linking option
40 johnpye 386 opts.Add(EnumOption(
41     'PACKAGE_LINKING'
42 johnpye 385 , 'Style of linking for external libraries'
43     , 'DYNAMIC_PACKAGES'
44 johnpye 386 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
45     ))
46 johnpye 385
47 johnpye 392 # You can turn off building of Tcl/Tk interface
48 johnpye 386 opts.Add(BoolOption(
49 johnpye 465 'WITHOUT_TCLTK'
50 johnpye 386 ,"Set to True if you don't want to build the original Tcl/Tk GUI."
51     , False
52     ))
53    
54 johnpye 392 # You can turn off the building of the Python interface
55 johnpye 387 opts.Add(BoolOption(
56     'WITHOUT_PYTHON'
57     ,"Set to True if you don't want to build Python wrappers."
58     , False
59     ))
60    
61 johnpye 392 # Which solvers will we allow?
62     opts.Add(ListOption(
63     'WITH_SOLVERS'
64 johnpye 393 ,"List of the solvers you want to build. The default is the minimum that"
65     +" works."
66 johnpye 392 ,["QRSLV","CMSLV"]
67     ,['QRSLV','MPS','SLV','OPTSQP'
68     ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
69     ,'LSOD','OPTSQP'
70     ]
71     ))
72    
73 johnpye 393 # Where will the local copy of the help files be kept?
74     opts.Add(PackageOption(
75     'WITH_LOCAL_HELP'
76     , "Directory containing the local copy of the help files (optional)"
77     , "no"
78     ))
79    
80     # Will bintoken support be enabled?
81     opts.Add(BoolOption(
82     'WITH_BINTOKEN'
83     ,"Enable bintoken support? This means compiling models as C-code before"
84     +" running them, to increase solving speed for large models."
85     ,False
86     ))
87    
88 johnpye 398 # What should the default ASCENDLIBRARY path be?
89     # Note: users can change it by editing their ~/.ascend.ini
90 johnpye 393 opts.Add(
91     'DEFAULT_ASCENDLIBRARY'
92     ,"Set the default value of the ASCENDLIBRARY -- the location where"
93     +" ASCEND will look for models when running ASCEND"
94 johnpye 459 ,"$INSTALL_DATA/models"
95 johnpye 393 )
96    
97 johnpye 398 # Where is SWIG?
98     opts.Add(
99     'SWIG'
100     ,"SWIG location, probably only required for MinGW and MSVC users."
101     +" Enter the location as a Windows-style path, for example"
102 johnpye 404 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
103 johnpye 398 )
104    
105 johnpye 400 # Build the test suite?
106     opts.Add(BoolOption(
107     'WITH_CUNIT_TESTS'
108     ,"Whether to build the CUnit tests. Default is off. If set to on,"
109     +" you must have CUnit installed somewhere that SCons can"
110 johnpye 463 +" find it, or else use the CUNIT_* options to specify."
111 johnpye 400 ,False
112     ))
113 johnpye 393
114 johnpye 400 # Where are the CUnit includes?
115     opts.Add(PackageOption(
116     'CUNIT_CPPPATH'
117     ,"Where are your CUnit include files?"
118 johnpye 459 ,'off'
119 johnpye 400 ))
120 johnpye 392
121 johnpye 404 # Where are the CUnit libraries?
122 johnpye 400 opts.Add(PackageOption(
123     'CUNIT_LIBPATH'
124 johnpye 404 ,"Where are your CUnit libraries?"
125 johnpye 459 ,'off'
126 johnpye 400 ))
127    
128 johnpye 404 # Where are the Tcl includes?
129     opts.Add(PackageOption(
130     'TCL_CPPPATH'
131     ,"Where are your Tcl include files?"
132 johnpye 463 ,"disable"
133 johnpye 404 ))
134    
135     # Where are the Tcl libs?
136     opts.Add(PackageOption(
137     'TCL_LIBPATH'
138     ,"Where are your Tcl libraries?"
139 johnpye 459 ,'off'
140 johnpye 404 ))
141    
142 johnpye 428 # What is the name of the Tcl lib?
143     opts.Add(
144     'TCL_LIB'
145     ,"Name of Tcl lib (eg 'tcl' or 'tcl83')"
146 johnpye 464 ,default_tcl_lib
147 johnpye 428 )
148    
149 johnpye 405 # Where are the Tk includes?
150     opts.Add(PackageOption(
151     'TK_CPPPATH'
152     ,"Where are your Tk include files?"
153 johnpye 464 ,'$TCL_CPPPATH'
154 johnpye 405 ))
155 johnpye 404
156 johnpye 405 # Where are the Tk libs?
157     opts.Add(PackageOption(
158     'TK_LIBPATH'
159     ,"Where are your Tk libraries?"
160 johnpye 464 ,'$TCL_LIBPATH'
161 johnpye 405 ))
162    
163 johnpye 428 # What is the name of the Tk lib?
164     opts.Add(
165     'TK_LIB'
166     ,"Name of Tk lib (eg 'tk' or 'tk83')"
167 johnpye 464 ,default_tk_lib
168 johnpye 435 )
169    
170 johnpye 460 # Static linking to TkTable
171    
172     opts.Add(BoolOption(
173     'STATIC_TKTABLE'
174     ,'Use static linking to TkTable or not'
175     ,False
176     ))
177    
178 johnpye 464 opts.Add(
179 johnpye 460 'TKTABLE_LIBPATH'
180     ,'Location of TkTable static library'
181 johnpye 464 ,'$TCL_LIBPATH/Tktable2.8'
182     )
183 johnpye 460
184 johnpye 435 opts.Add(
185 johnpye 460 'TKTABLE_LIB'
186     ,'Name of TkTable static library (excluding suffix/prefix, eg libtktable2.8.so -> tktable2.8)'
187 johnpye 464 ,default_tktable_lib
188 johnpye 460 )
189    
190     opts.Add(
191 johnpye 435 'INSTALL_PREFIX'
192     ,'Root location for installed files'
193 johnpye 449 ,'/usr/local'
194 johnpye 428 )
195    
196 johnpye 435 opts.Add(
197     'INSTALL_BIN'
198     ,'Location to put binaries during installation'
199     ,"$INSTALL_PREFIX/bin"
200     )
201    
202     opts.Add(
203 johnpye 463 'INSTALL_LIB'
204     ,'Location to put binaries during installation'
205     ,"$INSTALL_PREFIX/lib"
206     )
207    
208     opts.Add(
209 johnpye 435 'INSTALL_DATA'
210     ,'Location to put data files during installation'
211     ,"$INSTALL_PREFIX/share"
212     )
213    
214     opts.Add(
215     'INSTALL_INCLUDE'
216     ,'Location to put header files during installation'
217     ,"$INSTALL_PREFIX/include"
218     )
219    
220 johnpye 455 if platform.system()=="Windows":
221     default_install_assets = "glade/"
222     icon_extension = '.png'
223     else:
224     default_install_assets = "$INSTALL_DATA/ascend/glade/"
225     icon_extension = '.svg'
226    
227 johnpye 448 opts.Add(
228 johnpye 455 'PYGTK_ASSETS'
229     ,'Default location for Glade assets (placed in pygtk/interface/config.py)'
230     ,default_install_assets
231     )
232    
233     opts.Add(
234 johnpye 448 'INSTALL_ROOT'
235     ,'For use by RPM only: location of %{buildroot} during rpmbuild'
236     ,""
237     )
238    
239 johnpye 466 if platform.system()=="Windows":
240     opts.Add(BoolOption(
241     'WITH_INSTALLER'
242     ,'Build the Windows Installer (setup program) using NSIS'
243     ,False
244     ))
245    
246 johnpye 392 # TODO: OTHER OPTIONS?
247     # TODO: flags for optimisation
248 johnpye 393 # TODO: turning on/off bintoken functionality
249 johnpye 427 # TODO: Where will the 'Makefile.bt' file be installed?
250 johnpye 393
251 johnpye 385 opts.Update(env)
252     opts.Save('options.cache',env)
253    
254     Help(opts.GenerateHelpText(env))
255    
256 johnpye 465 with_tcltk_gui = (env['WITHOUT_TCLTK']==False)
257 johnpye 427 without_tcltk_reason = "disabled by options/config.py"
258 johnpye 386
259 johnpye 387 with_python = (env['WITHOUT_PYTHON']==False)
260 johnpye 427 without_python_reason = "disabled by options/config.py"
261 johnpye 387
262 johnpye 400 with_cunit_tests = env['WITH_CUNIT_TESTS']
263 johnpye 427 without_cunit_reason = "not requested"
264 johnpye 400
265 johnpye 464 #print "SOLVERS:",env['WITH_SOLVERS']
266     #print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
267     #print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
268 johnpye 393
269     subst_dict = {
270     '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
271 johnpye 436 , '@GLADE_FILE@':'ascend.glade'
272 johnpye 393 , '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
273 johnpye 455 , '@ICON_EXTENSION@':icon_extension
274 johnpye 393 , '@HELP_ROOT@':''
275 johnpye 436 , '@INSTALL_DATA@':env['INSTALL_DATA']
276     , '@INSTALL_BIN@':env['INSTALL_BIN']
277     , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
278 johnpye 455 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
279 johnpye 439 , '@VERSION@':version
280 johnpye 393 }
281    
282     if env['WITH_LOCAL_HELP']:
283 johnpye 464 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
284 johnpye 393 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
285 johnpye 463
286     can_install = True
287     if platform.system()=='Windows':
288     can_install = False
289    
290     env['CAN_INSTALL']=can_install
291    
292 johnpye 393 env.Append(SUBST_DICT=subst_dict)
293    
294 johnpye 385 #------------------------------------------------------
295 johnpye 398 # SPECIAL CONFIGURATION TESTS
296    
297 johnpye 463 need_fortran = False
298    
299 johnpye 400 #----------------
300     # SWIG
301    
302 johnpye 398 import os,re
303    
304 johnpye 413 def get_swig_version(env):
305 johnpye 403 cmd = env['SWIG']+' -version'
306 johnpye 427 (cin,coutcerr) = os.popen4(cmd)
307 johnpye 403 output = coutcerr.read()
308 johnpye 398
309 johnpye 403 restr = "SWIG\\s+Version\\s+(?P<maj>[0-9]+)\\.(?P<min>[0-9]+)\\.(?P<pat>[0-9]+)\\s*$"
310     expr = re.compile(restr,re.M);
311 johnpye 398 m = expr.search(output);
312     if not m:
313 johnpye 413 return None
314 johnpye 398 maj = int(m.group('maj'))
315     min = int(m.group('min'))
316     pat = int(m.group('pat'))
317 johnpye 413
318     return (maj,min,pat)
319 johnpye 398
320 johnpye 413
321     def CheckSwigVersion(context):
322    
323     try:
324     context.Message("Checking version of SWIG... ")
325     maj,min,pat = get_swig_version(context.env)
326     except:
327     context.Result("Failed to detect version, or failed to run SWIG")
328     return 0;
329    
330 johnpye 478 context.env['SWIGVERSION']=tuple([maj,min,pat])
331    
332 johnpye 398 if maj == 1 and (
333 johnpye 400 min > 3
334     or (min == 3 and pat >= 24)
335 johnpye 398 ):
336     context.Result("ok, %d.%d.%d" % (maj,min,pat))
337     return 1;
338 johnpye 401 else:
339     context.Result("too old, %d.%d.%d" % (maj,min,pat))
340     return 0;
341 johnpye 398
342 johnpye 400 #----------------
343     # General purpose library-and-header test
344    
345 johnpye 404 class KeepContext:
346     def __init__(self,context,varprefix):
347     self.keep = {}
348     for k in ['LIBS','LIBPATH','CPPPATH']:
349     if context.env.has_key(k):
350     self.keep[k] = context.env[k]
351 johnpye 463 else:
352     self.keep[k] = None
353 johnpye 404
354     libpath_add = []
355     if context.env.has_key(varprefix+'_LIBPATH'):
356     libpath_add = [env[varprefix+'_LIBPATH']]
357 johnpye 428 #print "Adding '"+str(libpath_add)+"' to lib path"
358 johnpye 400
359 johnpye 404 cpppath_add = []
360     if context.env.has_key(varprefix+'_CPPPATH'):
361     cpppath_add = [env[varprefix+'_CPPPATH']]
362 johnpye 428 #print "Adding '"+str(cpppath_add)+"' to cpp path"
363    
364     libs_add = []
365     if context.env.has_key(varprefix+'_LIB'):
366     libs_add = [env[varprefix+'_LIB']]
367 johnpye 464 #print "Adding '"+str(libs_add)+"' to libs"
368 johnpye 428
369 johnpye 405 context.env.Append(
370     LIBPATH = libpath_add
371     , CPPPATH = cpppath_add
372 johnpye 428 , LIBS = libs_add
373 johnpye 405 )
374 johnpye 404
375     def restore(self,context):
376 johnpye 464 #print "RESTORING CONTEXT"
377     #print self.keep
378     #print "..."
379 johnpye 404 for k in self.keep:
380 johnpye 463 if self.keep[k]==None:
381 johnpye 464 #print "Clearing "+str(k)
382 johnpye 463 del context.env[k];
383     else:
384 johnpye 464 #print "Restoring "+str(k)+" to '"+self.keep[k]+"'"
385 johnpye 463 context.env[k]=self.keep[k];
386 johnpye 404
387 johnpye 400 def CheckExtLib(context,libname,text,ext='.c',varprefix=None):
388     """This method will check for variables LIBNAME_LIBPATH
389     and LIBNAME_CPPPATH and try to compile and link the
390     file with the provided text, linking with the
391     library libname."""
392    
393 johnpye 405 context.Message( 'Checking for '+libname+'... ' )
394 johnpye 400
395     if varprefix==None:
396     varprefix = libname.upper()
397    
398 johnpye 404 keep = KeepContext(context,varprefix)
399 johnpye 400
400 johnpye 428 if not context.env.has_key(varprefix+'_LIB'):
401 johnpye 463 # if varprefix_LIB were in env, KeepContext would
402     # have appended it already
403 johnpye 451 context.env.Append(LIBS=libname)
404 johnpye 428
405 johnpye 404 is_ok = context.TryLink(text,ext)
406 johnpye 428
407     # print "Link success? ",(is_ok != 0)
408 johnpye 400
409 johnpye 405 keep.restore(context)
410 johnpye 400
411 johnpye 428 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
412     # print "Restored LIBS="+libname
413     # print "Restored LIBPATH="+str(context.env['LIBPATH'])
414    
415 johnpye 404 context.Result(is_ok)
416     return is_ok
417    
418     #----------------
419     # CUnit test
420    
421 johnpye 400 cunit_test_text = """
422 johnpye 451 #include <CUnit/CUnit.h>
423 johnpye 400 int maxi(int i1, int i2){
424     return (i1 > i2) ? i1 : i2;
425     }
426    
427     void test_maxi(void){
428     CU_ASSERT(maxi(0,2) == 2);
429     CU_ASSERT(maxi(0,-2) == 0);
430     CU_ASSERT(maxi(2,2) == 2);
431    
432     }
433     int main(void){
434     /* CU_initialize_registry() */
435 johnpye 404 return 0;
436 johnpye 400 }
437     """
438    
439     def CheckCUnit(context):
440 johnpye 451 return CheckExtLib(context,'cunit',cunit_test_text)
441 johnpye 400
442 johnpye 404 #----------------
443 johnpye 405 # Tcl test
444 johnpye 404
445     tcl_check_text = r"""
446     #include <tcl.h>
447     #include <stdio.h>
448     int main(void){
449     printf("%s",TCL_PATCH_LEVEL);
450     return 0;
451     }
452     """
453    
454     def CheckTcl(context):
455 johnpye 405 return CheckExtLib(context,'tcl',tcl_check_text)
456    
457     def CheckTclVersion(context):
458 johnpye 404 keep = KeepContext(context,'TCL')
459 johnpye 405 context.Message("Checking Tcl version... ")
460     (is_ok,output) = context.TryRun(tcl_check_text,'.c')
461 johnpye 404 keep.restore(context)
462     if not is_ok:
463 johnpye 405 context.Result("failed to run check")
464 johnpye 404 return 0
465 johnpye 405
466     major,minor,patch = tuple(int(i) for i in output.split("."))
467     if major != 8 or minor > 3:
468 johnpye 428 context.Result(output+" (bad version)")
469 johnpye 405 # bad version
470     return 0
471    
472     # good version
473 johnpye 428 context.Result(output+" (good)")
474 johnpye 404 return 1
475    
476 johnpye 405 #----------------
477 johnpye 463 # Tk test
478 johnpye 405
479     tk_check_text = r"""
480     #include <tk.h>
481     #include <stdio.h>
482     int main(void){
483     printf("%s",TK_PATCH_LEVEL);
484     return 0;
485     }
486     """
487     def CheckTk(context):
488 johnpye 428 return CheckExtLib(context,'tk',tcl_check_text)
489 johnpye 405
490 johnpye 428
491 johnpye 405 def CheckTkVersion(context):
492     keep = KeepContext(context,'TK')
493     context.Message("Checking Tk version... ")
494     (is_ok,output) = context.TryRun(tk_check_text,'.c')
495 johnpye 404 keep.restore(context)
496     if not is_ok:
497     context.Result("failed to run check")
498     return 0
499     context.Result(output)
500    
501     major,minor,patch = tuple(int(i) for i in output.split("."))
502     if major != 8 or minor > 3:
503     # bad version
504     return 0
505 johnpye 400
506 johnpye 404 # good version
507     return 1
508    
509 johnpye 398 #------------------------------------------------------
510 johnpye 385 # CONFIGURATION
511    
512     conf = Configure(env
513     , custom_tests = {
514 johnpye 398 'CheckSwigVersion' : CheckSwigVersion
515 johnpye 400 , 'CheckCUnit' : CheckCUnit
516 johnpye 404 , 'CheckTcl' : CheckTcl
517     , 'CheckTclVersion' : CheckTclVersion
518 johnpye 405 , 'CheckTk' : CheckTk
519     , 'CheckTkVersion' : CheckTkVersion
520 johnpye 400 # , 'CheckIsNan' : CheckIsNan
521     # , 'CheckCppUnitConfig' : CheckCppUnitConfig
522 johnpye 385 }
523 johnpye 459 # , config_h = "config.h"
524 johnpye 385 )
525    
526 johnpye 398
527 johnpye 385 # Math library
528    
529 johnpye 427 #if not conf.CheckFunc('sinh') and not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
530     # print 'Did not find math library, exiting!'
531     # Exit(1)
532    
533 johnpye 385 # Where is 'isnan'?
534    
535     if not conf.CheckFunc('isnan'):
536     print "Didn't find isnan"
537 johnpye 414 # Exit(1)
538 johnpye 385
539 johnpye 387 # Tcl/Tk
540 johnpye 386
541 johnpye 428 if conf.CheckTcl():
542     if with_tcltk_gui and conf.CheckTclVersion():
543     if conf.CheckTk():
544     if with_tcltk_gui and not conf.CheckTkVersion():
545     without_tcltk_reason = "Require Tk version <= 8.3. See 'scons -h'"
546     with_tcltk_gui = False
547     else:
548     without_tcltk_reason = "Tk not found."
549     with_tcltk_gui = False
550     else:
551 johnpye 405 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
552 johnpye 404 with_tcltk_gui = False
553 johnpye 386
554 johnpye 405 else:
555 johnpye 428 without_tcltk_reason = "Tcl not found."
556 johnpye 412 with_tcltk_gui = False
557    
558 johnpye 395 # Python... obviously we're already running python, so we just need to
559     # check that we can link to the python library OK:
560    
561 johnpye 391 if platform.system()=="Windows":
562 johnpye 395 python_lib='python24'
563 johnpye 391 else:
564 johnpye 395 python_lib='python2.4'
565 johnpye 391
566 johnpye 395 # SWIG version
567    
568 johnpye 396 if platform.system()=="Windows":
569     env['ENV']['SWIGFEATURES']='-O'
570     else:
571     env['ENV']['SWIGFEATURES']='-O'
572 johnpye 395
573 johnpye 413
574     if not conf.CheckSwigVersion():
575     without_python_reason = 'SWIG >= 1.3.24 is required'
576     with_python = False
577    
578 johnpye 400 # CUnit
579    
580     if with_cunit_tests:
581 johnpye 404 if not conf.CheckCUnit():
582 johnpye 427 without_cunit_reason = 'CUnit not found'
583    
584     # BLAS
585    
586 johnpye 459 need_blas=False
587     if with_tcltk_gui:
588     need_blas=True
589     if need_blas:
590     if conf.CheckLib('blas'):
591     print "FOUND BLAS"
592     with_local_blas = False
593     without_local_blas_reason = "Found BLAS installed on system"
594     else:
595     print "DIDN'T FIND BLAS"
596     with_local_blas = True
597     need_fortran = True
598 johnpye 427
599     # FORTRAN
600    
601     if need_fortran:
602     conf.env.Tool('f77')
603     detect_fortran = conf.env.Detect(['g77','f77'])
604     if detect_fortran:
605     # For some reason, g77 doesn't get detected properly on MinGW
606     if not env.has_key('F77'):
607     conf.env.Replace(F77=detect_fortran)
608     conf.env.Replace(F77COM='$F77 $F77FLAGS -c -o $TARGET $SOURCE')
609     conf.env.Replace(F77FLAGS='')
610 johnpye 428 #print "F77:",conf.env['F77']
611     #print "F77COM:",conf.env['F77COM']
612     #print "F77FLAGS:",conf.env['F77FLAGS']
613 johnpye 427 fortran_builder = Builder(
614     action='$F77COM'
615     , suffix='.o'
616     , src_suffix='.f'
617     )
618     conf.env.Append(BUILDERS={'Fortran':fortran_builder})
619     else:
620     print "FORTRAN-77 required but not found"
621 johnpye 404 Exit(1)
622 johnpye 464 #else:
623     # print "FORTRAN not required"
624 johnpye 400
625 johnpye 385 # TODO: -D_HPUX_SOURCE is needed
626    
627     # TODO: check size of void*
628    
629 johnpye 393 # TODO: detect if dynamic libraries are possible or not
630    
631 johnpye 427 if platform.system()=="Windows" and env.has_key('MSVS'):
632     if not conf.CheckHeader('windows.h') and env['PACKAGE_LINKING']=='DYNAMIC_PACKAGES':
633     print "Reverting to STATIC_PACKAGES since windows.h is not available. Probably you "\
634     +"need to install the Microsoft Windows Server 2003 Platform SDK, or similar."
635     env['PACKAGE_LINKING']='STATIC_PACKAGES'
636    
637     if with_python and not conf.CheckHeader('basetsd.h'):
638     with_python = 0;
639     without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
640    
641     conf.env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
642    
643 johnpye 395 conf.Finish()
644    
645     env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
646     env.Append(PYTHON_LIB=[python_lib])
647     env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
648    
649 johnpye 385 #------------------------------------------------------
650 johnpye 393 # RECIPE: 'SubstInFile', used in pygtk SConscript
651    
652     import re
653 johnpye 395 from SCons.Script import * # the usual scons stuff you get in a SConscript
654 johnpye 393
655 johnpye 395 def TOOL_SUBST(env):
656     """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
657     from the source to the target.
658     The values of SUBST_DICT first have any construction variables expanded
659     (its keys are not expanded).
660     If a value of SUBST_DICT is a python callable function, it is called and
661     the result is expanded as the value.
662     If there's more than one source and more than one target, each target gets
663     substituted from the corresponding source.
664 johnpye 393 """
665 johnpye 395 env.Append(TOOLS = 'SUBST')
666     def do_subst_in_file(targetfile, sourcefile, dict):
667     """Replace all instances of the keys of dict with their values.
668     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
669     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
670     """
671     try:
672     f = open(sourcefile, 'rb')
673     contents = f.read()
674     f.close()
675     except:
676     raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
677     for (k,v) in dict.items():
678     contents = re.sub(k, v, contents)
679     try:
680     f = open(targetfile, 'wb')
681     f.write(contents)
682     f.close()
683     except:
684     raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
685     return 0 # success
686 johnpye 393
687 johnpye 395 def subst_in_file(target, source, env):
688     if not env.has_key('SUBST_DICT'):
689     raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
690     d = dict(env['SUBST_DICT']) # copy it
691     for (k,v) in d.items():
692     if callable(v):
693     d[k] = env.subst(v())
694     elif SCons.Util.is_String(v):
695     d[k]=env.subst(v)
696     else:
697     raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
698     for (t,s) in zip(target, source):
699     return do_subst_in_file(str(t), str(s), d)
700 johnpye 393
701 johnpye 395 def subst_in_file_string(target, source, env):
702     """This is what gets printed on the console."""
703     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
704     for (t,s) in zip(target, source)])
705 johnpye 393
706 johnpye 395 def subst_emitter(target, source, env):
707     """Add dependency from substituted SUBST_DICT to target.
708     Returns original target, source tuple unchanged.
709     """
710     d = env['SUBST_DICT'].copy() # copy it
711     for (k,v) in d.items():
712     if callable(v):
713     d[k] = env.subst(v())
714     elif SCons.Util.is_String(v):
715     d[k]=env.subst(v)
716     Depends(target, SCons.Node.Python.Value(d))
717     return target, source
718 johnpye 393
719 johnpye 395 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
720     env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
721    
722     TOOL_SUBST(env)
723    
724 johnpye 393 #------------------------------------------------------
725 johnpye 463 # Recipe for 'CHMOD' ACTION
726 johnpye 439
727     import SCons
728     from SCons.Script.SConscript import SConsEnvironment
729     SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
730     lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
731    
732     def InstallPerm(env, dest, files, perm):
733     obj = env.Install(dest, files)
734     for i in obj:
735     env.AddPostAction(i, env.Chmod(str(i), perm))
736    
737     SConsEnvironment.InstallPerm = InstallPerm
738    
739     # define wrappers
740     SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
741     SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
742 johnpye 463
743 johnpye 439 #------------------------------------------------------
744 johnpye 466 # NSIS Support for SCons
745 johnpye 385
746 johnpye 466 # Adapted version by John Pye, April 2006.
747     # from http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/NsisSconsTool
748     # Written by Mike Elkins, January 2004.
749 johnpye 393
750 johnpye 466 #This tool provides SCons support for the Nullsoft Scriptable Install System
751     #a windows installer builder available at http://nsis.sourceforge.net/home
752    
753     #In addition, if you set NSISDEFINES to a dictionary, those variables will be passed
754     #to NSIS.
755    
756     import SCons.Builder
757     import SCons.Util
758     import SCons.Scanner
759     import SCons.Sig
760     import os.path
761     import glob
762    
763     def nsis_parse( sources, keyword, multiple ):
764     """
765     A function that knows how to read a .nsi file and figure
766     out what files are referenced, or find the 'OutFile' line.
767    
768    
769     sources is a list of nsi files.
770     keyword is the command ('File' or 'OutFile') to look for
771     multiple is true if you want all the args as a list, false if you
772     just want the first one.
773     """
774     stuff = []
775     for s in sources:
776     c = s.get_contents()
777     for l in c.split('\n'):
778     semi = l.find(';')
779     if (semi != -1):
780     l = l[:semi]
781     hash = l.find('#')
782     if (hash != -1):
783     l = l[:hash]
784     # Look for the keyword
785     l = l.strip()
786     spl = l.split(None,1)
787     if len(spl) > 1:
788     if spl[0].capitalize() == keyword.capitalize():
789     arg = spl[1]
790     if arg.startswith('"') and arg.endswith('"'):
791     arg = arg[1:-1]
792     if multiple:
793     stuff += [ arg ]
794     else:
795     return arg
796     return stuff
797    
798    
799     def nsis_path( filename, nsisdefines, rootdir ):
800     """
801     Do environment replacement, and prepend with the SCons root dir if
802     necessary
803     """
804     # We can't do variables defined by NSIS itself (like $INSTDIR),
805     # only user supplied ones (like ${FOO})
806     varPos = filename.find('${')
807     while varPos != -1:
808     endpos = filename.find('}',varPos)
809     assert endpos != -1
810     if not nsisdefines.has_key(filename[varPos+2:endpos]):
811     raise KeyError ("Could not find %s in NSISDEFINES" % filename[varPos+2:endpos])
812     val = nsisdefines[filename[varPos+2:endpos]]
813     if type(val) == list:
814     if varPos != 0 or endpos+1 != len(filename):
815     raise Exception("Can't use lists on variables that aren't complete filenames")
816     return val
817     filename = filename[0:varPos] + val + filename[endpos+1:]
818     varPos = filename.find('${')
819     return filename
820    
821    
822     def nsis_scanner( node, env, path ):
823     """
824     The scanner that looks through the source .nsi files and finds all lines
825     that are the 'File' command, fixes the directories etc, and returns them.
826     """
827     nodes = node.rfile()
828     if not node.exists():
829     return []
830     nodes = []
831     source_dir = node.get_dir()
832     for include in nsis_parse([node],'file',1):
833     exp = nsis_path(include,env['NSISDEFINES'],source_dir)
834     if type(exp) != list:
835     exp = [exp]
836     for p in exp:
837     for filename in glob.glob( os.path.abspath(
838     os.path.join(str(source_dir),p))):
839     # Why absolute path? Cause it breaks mysteriously without it :(
840     nodes.append(filename)
841     return nodes
842    
843    
844     def nsis_emitter( source, target, env ):
845     """
846     The emitter changes the target name to match what the command actually will
847     output, which is the argument to the OutFile command.
848     """
849     nsp = nsis_parse(source,'outfile',0)
850     if not nsp:
851     return (target,source)
852     x = (
853     nsis_path(nsp,env['NSISDEFINES'],''),
854     source)
855     return x
856    
857     def quoteIfSpaced(text):
858     if ' ' in text:
859     return '"'+text+'"'
860     else:
861     return text
862    
863     def toString(item,env):
864     if type(item) == list:
865     ret = ''
866     for i in item:
867     if ret:
868     ret += ' '
869     val = toString(i,env)
870     if ' ' in val:
871     val = "'"+val+"'"
872     ret += val
873     return ret
874     else:
875     # For convienence, handle #s here
876     if str(item).startswith('#'):
877     item = env.File(item).get_abspath()
878     return str(item)
879    
880     def runNSIS(source,target,env,for_signature):
881     ret = env['NSIS']+" "
882     if env.has_key('NSISFLAGS'):
883     for flag in env['NSISFLAGS']:
884     ret += flag
885     ret += ' '
886     if env.has_key('NSISDEFINES'):
887     for d in env['NSISDEFINES']:
888     ret += '/D'+d
889     if env['NSISDEFINES'][d]:
890     ret +='='+quoteIfSpaced(toString(env['NSISDEFINES'][d],env))
891     ret += ' '
892     for s in source:
893     ret += quoteIfSpaced(str(s))
894     return ret
895    
896     def find_nsis(env):
897     """
898     Try and figure out if NSIS is installed on this machine, and if so,
899     where.
900     """
901     if SCons.Util.can_read_reg:
902     # If we can read the registry, get the NSIS command from it
903     try:
904     k = SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
905     'SOFTWARE\\NSIS')
906     val, tok = SCons.Util.RegQueryValueEx(k,None)
907     ret = val + os.path.sep + 'makensis.exe'
908     if os.path.exists(ret):
909     return '"' + ret + '"'
910     else:
911     return None
912     except:
913     pass # Couldn't find the key, just act like we can't read the registry
914     # Hope it's on the path
915     return env.WhereIs('makensis.exe')
916    
917     def nsis_exists(env):
918     """
919     Is NSIS findable on this machine?
920     """
921     if find_nsis(env) != None:
922     return 1
923     return 0
924    
925     env['BUILDERS']['Nsis'] = SCons.Builder.Builder(generator=runNSIS,
926     src_suffix='.nsi',
927     emitter=nsis_emitter)
928    
929     env.Append(SCANNERS = SCons.Scanner.Scanner( function = nsis_scanner,
930     skeys = ['.nsi']))
931    
932     if not env.has_key('NSISDEFINES'):
933     env['NSISDEFINES'] = {}
934     env['NSIS'] = find_nsis(env)
935    
936 johnpye 463 #------------------------------------------------------
937     # BUILD...
938 johnpye 385
939 johnpye 463 # so that #include <modulename/headername.h> works across all modules...
940     env.Append(CPPPATH=['#base/generic'])
941 johnpye 385
942 johnpye 463 #-------------
943     # TCL/TK GUI
944 johnpye 385
945 johnpye 463 if with_tcltk_gui:
946     if with_local_blas:
947     env.SConscript(['blas/SConscript'],'env')
948     else:
949     print "Skipping... BLAS won't be build:", without_local_blas_reason
950 johnpye 385
951 johnpye 463 env.SConscript(['lsod/SConscript'],'env')
952 johnpye 385
953 johnpye 463 env.SConscript(['linpack/SConscript'],'env')
954 johnpye 386 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
955 johnpye 391 else:
956 johnpye 405 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
957 johnpye 386
958 johnpye 463 #-------------
959     # PYTHON INTERFACE
960    
961 johnpye 387 if with_python:
962     env.SConscript(['pygtk/interface/SConscript'],'env')
963 johnpye 391 else:
964 johnpye 413 print "Skipping... Python GUI isn't being built:",without_python_reason
965 johnpye 400
966 johnpye 463 #------------
967     # BASE/GENERIC SUBDIRECTORIES
968    
969     dirs = ['general','utilities','compiler','solver','packages']
970    
971     srcs = []
972     for d in dirs:
973     heresrcs = env.SConscript('base/generic/'+d+'/SConscript','env')
974     srcs += heresrcs
975    
976     #-------------
977     # LIBASCEND -- all base/generic functionality
978    
979     libascend = env.SharedLibrary('ascend',srcs)
980    
981     #-------------
982     # UNIT TESTS
983    
984 johnpye 400 if with_cunit_tests:
985     testdirs = ['general','solver','utilities']
986     for testdir in testdirs:
987     path = 'base/generic/'+testdir+'/test/'
988     env.SConscript([path+'SConscript'],'env')
989     env.SConscript(['test/SConscript'],'env')
990     env.SConscript(['base/generic/test/SConscript'],'env')
991    
992    
993     else:
994 johnpye 427 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
995 johnpye 400
996 johnpye 427
997 johnpye 463 #------------------------------------------------------
998     # INSTALLATION
999 johnpye 427
1000 johnpye 463 if env.has_key('CAN_INSTALL') and env['CAN_INSTALL']:
1001     # the models directory only needs to be processed for installation, no other processing required.
1002     env.SConscript(['models/SConscript'],'env')
1003 johnpye 427
1004 johnpye 463 dirs = ['INSTALL_BIN','INSTALL_DATA','INSTALL_LIB']
1005     install_dirs = [env['INSTALL_ROOT']+env[d] for d in dirs]
1006 johnpye 449
1007 johnpye 463 # TODO: add install options
1008     env.Alias('install',install_dirs)
1009 johnpye 400
1010 johnpye 463 env.Install(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1011 johnpye 435
1012 johnpye 438 #------------------------------------------------------
1013     # CREATE the SPEC file for generation of RPM packages
1014    
1015 johnpye 463 if platform.system()=="Linux":
1016     env.SubstInFile('ascend.spec.in')

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