/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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