/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 508 - (hide annotations) (download)
Wed Apr 19 04:48:32 2006 UTC (13 years, 9 months ago) by johnpye
File size: 28742 byte(s)
More fixes for compiling and running on ubuntu 5.10 with GCC:
gcc version 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

Added ASC_SHLIBSUFFIX and ASC_SHLIBPREFIX which are used in packages.c in preference to platform-specific #ifdefs.

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

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