/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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