/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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