/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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