/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 485 - (hide annotations) (download)
Tue Apr 18 04:47:11 2006 UTC (13 years, 10 months ago) by johnpye
File size: 26836 byte(s)
Huge cleanup of file header comments (GPL notice etc).

Changed from ASC_DLLSPEC to ASC_DLLSPEC(TYPE) -- like python

Fixed up some badly export symbols (missing 'extern')

Fixed exporting of symbols from error.h

Removed ASC_DLLSPEC from .c files-- only in .h files now (hope that's right...)

Changed the way bintoken does its exporting, to take 
advantage of ASC_BUILDING_LIBASCEND (needs testing)

I wonder if the 'extern' keywork should be a part of the ASC_DLLSPEC macro?

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 johnpye 485
509     #----------------
510     # GCC Version sniffing
511    
512     # TODO FIXME
513    
514     gcc_version4 = False
515    
516 johnpye 398 #------------------------------------------------------
517 johnpye 385 # CONFIGURATION
518    
519     conf = Configure(env
520     , custom_tests = {
521 johnpye 398 'CheckSwigVersion' : CheckSwigVersion
522 johnpye 400 , 'CheckCUnit' : CheckCUnit
523 johnpye 404 , 'CheckTcl' : CheckTcl
524     , 'CheckTclVersion' : CheckTclVersion
525 johnpye 405 , 'CheckTk' : CheckTk
526     , 'CheckTkVersion' : CheckTkVersion
527 johnpye 400 # , 'CheckIsNan' : CheckIsNan
528     # , 'CheckCppUnitConfig' : CheckCppUnitConfig
529 johnpye 385 }
530 johnpye 459 # , config_h = "config.h"
531 johnpye 385 )
532    
533 johnpye 398
534 johnpye 385 # Math library
535    
536 johnpye 427 #if not conf.CheckFunc('sinh') and not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
537     # print 'Did not find math library, exiting!'
538     # Exit(1)
539    
540 johnpye 385 # Where is 'isnan'?
541    
542     if not conf.CheckFunc('isnan'):
543     print "Didn't find isnan"
544 johnpye 414 # Exit(1)
545 johnpye 385
546 johnpye 387 # Tcl/Tk
547 johnpye 386
548 johnpye 428 if conf.CheckTcl():
549     if with_tcltk_gui and conf.CheckTclVersion():
550     if conf.CheckTk():
551     if with_tcltk_gui and not conf.CheckTkVersion():
552     without_tcltk_reason = "Require Tk version <= 8.3. See 'scons -h'"
553     with_tcltk_gui = False
554     else:
555     without_tcltk_reason = "Tk not found."
556     with_tcltk_gui = False
557     else:
558 johnpye 405 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
559 johnpye 404 with_tcltk_gui = False
560 johnpye 386
561 johnpye 405 else:
562 johnpye 428 without_tcltk_reason = "Tcl not found."
563 johnpye 412 with_tcltk_gui = False
564    
565 johnpye 395 # Python... obviously we're already running python, so we just need to
566     # check that we can link to the python library OK:
567    
568 johnpye 391 if platform.system()=="Windows":
569 johnpye 395 python_lib='python24'
570 johnpye 391 else:
571 johnpye 395 python_lib='python2.4'
572 johnpye 391
573 johnpye 395 # SWIG version
574    
575 johnpye 396 if platform.system()=="Windows":
576     env['ENV']['SWIGFEATURES']='-O'
577     else:
578     env['ENV']['SWIGFEATURES']='-O'
579 johnpye 395
580 johnpye 413
581     if not conf.CheckSwigVersion():
582     without_python_reason = 'SWIG >= 1.3.24 is required'
583     with_python = False
584    
585 johnpye 400 # CUnit
586    
587     if with_cunit_tests:
588 johnpye 404 if not conf.CheckCUnit():
589 johnpye 427 without_cunit_reason = 'CUnit not found'
590    
591     # BLAS
592    
593 johnpye 459 need_blas=False
594     if with_tcltk_gui:
595     need_blas=True
596     if need_blas:
597     if conf.CheckLib('blas'):
598     print "FOUND BLAS"
599     with_local_blas = False
600     without_local_blas_reason = "Found BLAS installed on system"
601     else:
602     print "DIDN'T FIND BLAS"
603     with_local_blas = True
604     need_fortran = True
605 johnpye 427
606     # FORTRAN
607    
608     if need_fortran:
609     conf.env.Tool('f77')
610     detect_fortran = conf.env.Detect(['g77','f77'])
611     if detect_fortran:
612     # For some reason, g77 doesn't get detected properly on MinGW
613     if not env.has_key('F77'):
614     conf.env.Replace(F77=detect_fortran)
615     conf.env.Replace(F77COM='$F77 $F77FLAGS -c -o $TARGET $SOURCE')
616     conf.env.Replace(F77FLAGS='')
617 johnpye 428 #print "F77:",conf.env['F77']
618     #print "F77COM:",conf.env['F77COM']
619     #print "F77FLAGS:",conf.env['F77FLAGS']
620 johnpye 427 fortran_builder = Builder(
621     action='$F77COM'
622     , suffix='.o'
623     , src_suffix='.f'
624     )
625     conf.env.Append(BUILDERS={'Fortran':fortran_builder})
626     else:
627     print "FORTRAN-77 required but not found"
628 johnpye 404 Exit(1)
629 johnpye 464 #else:
630     # print "FORTRAN not required"
631 johnpye 400
632 johnpye 385 # TODO: -D_HPUX_SOURCE is needed
633    
634     # TODO: check size of void*
635    
636 johnpye 393 # TODO: detect if dynamic libraries are possible or not
637    
638 johnpye 427 if platform.system()=="Windows" and env.has_key('MSVS'):
639     if not conf.CheckHeader('windows.h') and env['PACKAGE_LINKING']=='DYNAMIC_PACKAGES':
640     print "Reverting to STATIC_PACKAGES since windows.h is not available. Probably you "\
641     +"need to install the Microsoft Windows Server 2003 Platform SDK, or similar."
642     env['PACKAGE_LINKING']='STATIC_PACKAGES'
643    
644     if with_python and not conf.CheckHeader('basetsd.h'):
645     with_python = 0;
646     without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
647    
648     conf.env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
649    
650 johnpye 395 conf.Finish()
651    
652     env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
653     env.Append(PYTHON_LIB=[python_lib])
654     env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
655    
656 johnpye 385 #------------------------------------------------------
657 johnpye 393 # RECIPE: 'SubstInFile', used in pygtk SConscript
658    
659     import re
660 johnpye 395 from SCons.Script import * # the usual scons stuff you get in a SConscript
661 johnpye 393
662 johnpye 395 def TOOL_SUBST(env):
663     """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
664     from the source to the target.
665     The values of SUBST_DICT first have any construction variables expanded
666     (its keys are not expanded).
667     If a value of SUBST_DICT is a python callable function, it is called and
668     the result is expanded as the value.
669     If there's more than one source and more than one target, each target gets
670     substituted from the corresponding source.
671 johnpye 393 """
672 johnpye 395 env.Append(TOOLS = 'SUBST')
673     def do_subst_in_file(targetfile, sourcefile, dict):
674     """Replace all instances of the keys of dict with their values.
675     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
676     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
677     """
678     try:
679     f = open(sourcefile, 'rb')
680     contents = f.read()
681     f.close()
682     except:
683     raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
684     for (k,v) in dict.items():
685     contents = re.sub(k, v, contents)
686     try:
687     f = open(targetfile, 'wb')
688     f.write(contents)
689     f.close()
690     except:
691     raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
692     return 0 # success
693 johnpye 393
694 johnpye 395 def subst_in_file(target, source, env):
695     if not env.has_key('SUBST_DICT'):
696     raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
697     d = dict(env['SUBST_DICT']) # copy it
698     for (k,v) in d.items():
699     if callable(v):
700     d[k] = env.subst(v())
701     elif SCons.Util.is_String(v):
702     d[k]=env.subst(v)
703     else:
704     raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
705     for (t,s) in zip(target, source):
706     return do_subst_in_file(str(t), str(s), d)
707 johnpye 393
708 johnpye 395 def subst_in_file_string(target, source, env):
709     """This is what gets printed on the console."""
710     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
711     for (t,s) in zip(target, source)])
712 johnpye 393
713 johnpye 395 def subst_emitter(target, source, env):
714     """Add dependency from substituted SUBST_DICT to target.
715     Returns original target, source tuple unchanged.
716     """
717     d = env['SUBST_DICT'].copy() # copy it
718     for (k,v) in d.items():
719     if callable(v):
720     d[k] = env.subst(v())
721     elif SCons.Util.is_String(v):
722     d[k]=env.subst(v)
723     Depends(target, SCons.Node.Python.Value(d))
724     return target, source
725 johnpye 393
726 johnpye 395 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
727     env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
728    
729     TOOL_SUBST(env)
730    
731 johnpye 393 #------------------------------------------------------
732 johnpye 463 # Recipe for 'CHMOD' ACTION
733 johnpye 439
734     import SCons
735     from SCons.Script.SConscript import SConsEnvironment
736     SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
737     lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
738    
739     def InstallPerm(env, dest, files, perm):
740     obj = env.Install(dest, files)
741     for i in obj:
742     env.AddPostAction(i, env.Chmod(str(i), perm))
743    
744     SConsEnvironment.InstallPerm = InstallPerm
745    
746     # define wrappers
747     SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
748     SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
749 johnpye 463
750 johnpye 439 #------------------------------------------------------
751 johnpye 466 # NSIS Support for SCons
752 johnpye 385
753 johnpye 466 # Adapted version by John Pye, April 2006.
754     # from http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/NsisSconsTool
755     # Written by Mike Elkins, January 2004.
756 johnpye 393
757 johnpye 466 #This tool provides SCons support for the Nullsoft Scriptable Install System
758     #a windows installer builder available at http://nsis.sourceforge.net/home
759    
760     #In addition, if you set NSISDEFINES to a dictionary, those variables will be passed
761     #to NSIS.
762    
763     import SCons.Builder
764     import SCons.Util
765     import SCons.Scanner
766     import SCons.Sig
767     import os.path
768     import glob
769    
770     def nsis_parse( sources, keyword, multiple ):
771     """
772     A function that knows how to read a .nsi file and figure
773     out what files are referenced, or find the 'OutFile' line.
774    
775    
776     sources is a list of nsi files.
777     keyword is the command ('File' or 'OutFile') to look for
778     multiple is true if you want all the args as a list, false if you
779     just want the first one.
780     """
781     stuff = []
782     for s in sources:
783     c = s.get_contents()
784     for l in c.split('\n'):
785     semi = l.find(';')
786     if (semi != -1):
787     l = l[:semi]
788     hash = l.find('#')
789     if (hash != -1):
790     l = l[:hash]
791     # Look for the keyword
792     l = l.strip()
793     spl = l.split(None,1)
794     if len(spl) > 1:
795     if spl[0].capitalize() == keyword.capitalize():
796     arg = spl[1]
797     if arg.startswith('"') and arg.endswith('"'):
798     arg = arg[1:-1]
799     if multiple:
800     stuff += [ arg ]
801     else:
802     return arg
803     return stuff
804    
805    
806     def nsis_path( filename, nsisdefines, rootdir ):
807     """
808     Do environment replacement, and prepend with the SCons root dir if
809     necessary
810     """
811     # We can't do variables defined by NSIS itself (like $INSTDIR),
812     # only user supplied ones (like ${FOO})
813     varPos = filename.find('${')
814     while varPos != -1:
815     endpos = filename.find('}',varPos)
816     assert endpos != -1
817     if not nsisdefines.has_key(filename[varPos+2:endpos]):
818     raise KeyError ("Could not find %s in NSISDEFINES" % filename[varPos+2:endpos])
819     val = nsisdefines[filename[varPos+2:endpos]]
820     if type(val) == list:
821     if varPos != 0 or endpos+1 != len(filename):
822     raise Exception("Can't use lists on variables that aren't complete filenames")
823     return val
824     filename = filename[0:varPos] + val + filename[endpos+1:]
825     varPos = filename.find('${')
826     return filename
827    
828    
829     def nsis_scanner( node, env, path ):
830     """
831     The scanner that looks through the source .nsi files and finds all lines
832     that are the 'File' command, fixes the directories etc, and returns them.
833     """
834     nodes = node.rfile()
835     if not node.exists():
836     return []
837     nodes = []
838     source_dir = node.get_dir()
839     for include in nsis_parse([node],'file',1):
840     exp = nsis_path(include,env['NSISDEFINES'],source_dir)
841     if type(exp) != list:
842     exp = [exp]
843     for p in exp:
844     for filename in glob.glob( os.path.abspath(
845     os.path.join(str(source_dir),p))):
846     # Why absolute path? Cause it breaks mysteriously without it :(
847     nodes.append(filename)
848     return nodes
849    
850    
851     def nsis_emitter( source, target, env ):
852     """
853     The emitter changes the target name to match what the command actually will
854     output, which is the argument to the OutFile command.
855     """
856     nsp = nsis_parse(source,'outfile',0)
857     if not nsp:
858     return (target,source)
859     x = (
860     nsis_path(nsp,env['NSISDEFINES'],''),
861     source)
862     return x
863    
864     def quoteIfSpaced(text):
865     if ' ' in text:
866     return '"'+text+'"'
867     else:
868     return text
869    
870     def toString(item,env):
871     if type(item) == list:
872     ret = ''
873     for i in item:
874     if ret:
875     ret += ' '
876     val = toString(i,env)
877     if ' ' in val:
878     val = "'"+val+"'"
879     ret += val
880     return ret
881     else:
882     # For convienence, handle #s here
883     if str(item).startswith('#'):
884     item = env.File(item).get_abspath()
885     return str(item)
886    
887     def runNSIS(source,target,env,for_signature):
888     ret = env['NSIS']+" "
889     if env.has_key('NSISFLAGS'):
890     for flag in env['NSISFLAGS']:
891     ret += flag
892     ret += ' '
893     if env.has_key('NSISDEFINES'):
894     for d in env['NSISDEFINES']:
895     ret += '/D'+d
896     if env['NSISDEFINES'][d]:
897     ret +='='+quoteIfSpaced(toString(env['NSISDEFINES'][d],env))
898     ret += ' '
899     for s in source:
900     ret += quoteIfSpaced(str(s))
901     return ret
902    
903     def find_nsis(env):
904     """
905     Try and figure out if NSIS is installed on this machine, and if so,
906     where.
907     """
908     if SCons.Util.can_read_reg:
909     # If we can read the registry, get the NSIS command from it
910     try:
911     k = SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
912     'SOFTWARE\\NSIS')
913     val, tok = SCons.Util.RegQueryValueEx(k,None)
914     ret = val + os.path.sep + 'makensis.exe'
915     if os.path.exists(ret):
916     return '"' + ret + '"'
917     else:
918     return None
919     except:
920     pass # Couldn't find the key, just act like we can't read the registry
921     # Hope it's on the path
922     return env.WhereIs('makensis.exe')
923    
924     def nsis_exists(env):
925     """
926     Is NSIS findable on this machine?
927     """
928     if find_nsis(env) != None:
929     return 1
930     return 0
931    
932     env['BUILDERS']['Nsis'] = SCons.Builder.Builder(generator=runNSIS,
933     src_suffix='.nsi',
934     emitter=nsis_emitter)
935    
936     env.Append(SCANNERS = SCons.Scanner.Scanner( function = nsis_scanner,
937     skeys = ['.nsi']))
938    
939     if not env.has_key('NSISDEFINES'):
940     env['NSISDEFINES'] = {}
941     env['NSIS'] = find_nsis(env)
942    
943 johnpye 463 #------------------------------------------------------
944     # BUILD...
945 johnpye 385
946 johnpye 463 # so that #include <modulename/headername.h> works across all modules...
947     env.Append(CPPPATH=['#base/generic'])
948 johnpye 385
949 johnpye 485 if gcc_version4:
950     env.Append(CCFLAGS=['-fvisibility=hidden'])
951    
952 johnpye 463 #-------------
953     # TCL/TK GUI
954 johnpye 385
955 johnpye 463 if with_tcltk_gui:
956     if with_local_blas:
957     env.SConscript(['blas/SConscript'],'env')
958     else:
959     print "Skipping... BLAS won't be build:", without_local_blas_reason
960 johnpye 385
961 johnpye 463 env.SConscript(['lsod/SConscript'],'env')
962 johnpye 385
963 johnpye 463 env.SConscript(['linpack/SConscript'],'env')
964 johnpye 386 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
965 johnpye 391 else:
966 johnpye 405 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
967 johnpye 386
968 johnpye 463 #-------------
969     # PYTHON INTERFACE
970    
971 johnpye 387 if with_python:
972     env.SConscript(['pygtk/interface/SConscript'],'env')
973 johnpye 391 else:
974 johnpye 413 print "Skipping... Python GUI isn't being built:",without_python_reason
975 johnpye 400
976 johnpye 463 #------------
977     # BASE/GENERIC SUBDIRECTORIES
978    
979     dirs = ['general','utilities','compiler','solver','packages']
980    
981     srcs = []
982     for d in dirs:
983     heresrcs = env.SConscript('base/generic/'+d+'/SConscript','env')
984     srcs += heresrcs
985    
986     #-------------
987     # LIBASCEND -- all base/generic functionality
988    
989     libascend = env.SharedLibrary('ascend',srcs)
990    
991     #-------------
992     # UNIT TESTS
993    
994 johnpye 400 if with_cunit_tests:
995     testdirs = ['general','solver','utilities']
996     for testdir in testdirs:
997     path = 'base/generic/'+testdir+'/test/'
998     env.SConscript([path+'SConscript'],'env')
999     env.SConscript(['test/SConscript'],'env')
1000     env.SConscript(['base/generic/test/SConscript'],'env')
1001    
1002    
1003     else:
1004 johnpye 427 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1005 johnpye 400
1006 johnpye 427
1007 johnpye 463 #------------------------------------------------------
1008     # INSTALLATION
1009 johnpye 427
1010 johnpye 463 if env.has_key('CAN_INSTALL') and env['CAN_INSTALL']:
1011     # the models directory only needs to be processed for installation, no other processing required.
1012     env.SConscript(['models/SConscript'],'env')
1013 johnpye 427
1014 johnpye 463 dirs = ['INSTALL_BIN','INSTALL_DATA','INSTALL_LIB']
1015     install_dirs = [env['INSTALL_ROOT']+env[d] for d in dirs]
1016 johnpye 449
1017 johnpye 463 # TODO: add install options
1018     env.Alias('install',install_dirs)
1019 johnpye 400
1020 johnpye 463 env.Install(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1021 johnpye 435
1022 johnpye 438 #------------------------------------------------------
1023     # CREATE the SPEC file for generation of RPM packages
1024    
1025 johnpye 463 if platform.system()=="Linux":
1026     env.SubstInFile('ascend.spec.in')

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