/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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