/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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