/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 526 - (show 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 import os, commands, platform, distutils.sysconfig, os.path
2
3 version = "0.9.6rc0"
4
5 #------------------------------------------------------
6 # OPTIONS
7 #
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
11 opts = Options(['options.cache', 'config.py'])
12 #print "PLATFORM = ",platform.system()
13
14 if platform.system()=="Windows":
15 default_tcl_lib = "tcl83"
16 default_tk_lib = "tk83"
17 default_tktable_lib = "Tktable28"
18 default_install_assets = "glade/"
19 icon_extension = '.png'
20 default_tcl = "c:\\Tcl"
21 else:
22 default_tcl_lib = "tcl8.3"
23 default_tk_lib = "tk8.3"
24 default_tktable_lib = "Tktable2.8"
25 default_install_assets = "$INSTALL_DATA/ascend/glade/"
26 icon_extension = '.svg'
27 default_tcl = os.path.expanduser("~/activetcl")
28
29
30 # Package linking option
31 opts.Add(EnumOption(
32 'PACKAGE_LINKING'
33 , 'Style of linking for external libraries'
34 , 'DYNAMIC_PACKAGES'
35 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
36 ))
37
38 opts.Add(BoolOption(
39 'WITH_GCCVISIBILITY'
40 ,"Whether to use GCC Visibility features (only applicable if available)"
41 ,True
42 ))
43
44 # You can turn off building of Tcl/Tk interface
45 opts.Add(BoolOption(
46 'WITHOUT_TCLTK'
47 ,"Set to True if you don't want to build the original Tcl/Tk GUI."
48 , False
49 ))
50
51 # You can turn off the building of the Python interface
52 opts.Add(BoolOption(
53 'WITHOUT_PYTHON'
54 ,"Set to True if you don't want to build Python wrappers."
55 , False
56 ))
57
58 # Which solvers will we allow?
59 opts.Add(ListOption(
60 'WITH_SOLVERS'
61 ,"List of the solvers you want to build. The default is the minimum that"
62 +" works."
63 ,["QRSLV","CMSLV"]
64 ,['QRSLV','MPS','SLV','OPTSQP'
65 ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
66 ,'LSOD','OPTSQP'
67 ]
68 ))
69
70 # 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 # What should the default ASCENDLIBRARY path be?
86 # Note: users can change it by editing their ~/.ascend.ini
87 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 ,"$INSTALL_DATA/models"
92 )
93
94 # 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 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
100 )
101
102 # 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 +" find it, or else use the CUNIT_* options to specify."
108 ,False
109 ))
110
111 # Where are the CUnit includes?
112 opts.Add(PackageOption(
113 'CUNIT_CPPPATH'
114 ,"Where are your CUnit include files?"
115 ,'off'
116 ))
117
118 # Where are the CUnit libraries?
119 opts.Add(PackageOption(
120 'CUNIT_LIBPATH'
121 ,"Where are your CUnit libraries?"
122 ,'off'
123 ))
124
125
126 opts.Add(PackageOption(
127 'TCL'
128 ,'Base of Tcl distribution'
129 ,default_tcl
130 ))
131
132 # Where are the Tcl includes?
133 opts.Add(PackageOption(
134 'TCL_CPPPATH'
135 ,"Where are your Tcl include files?"
136 ,"$TCL/include"
137 ))
138
139 # Where are the Tcl libs?
140 opts.Add(PackageOption(
141 'TCL_LIBPATH'
142 ,"Where are your Tcl libraries?"
143 ,"$TCL/lib"
144 ))
145
146 # What is the name of the Tcl lib?
147 opts.Add(
148 'TCL_LIB'
149 ,"Name of Tcl lib (eg 'tcl' or 'tcl83'), for full path to static library"
150 ,default_tcl_lib
151 )
152
153 # Where are the Tk includes?
154 opts.Add(PackageOption(
155 'TK_CPPPATH'
156 ,"Where are your Tk include files?"
157 ,'$TCL_CPPPATH'
158 ))
159
160 # Where are the Tk libs?
161 opts.Add(PackageOption(
162 'TK_LIBPATH'
163 ,"Where are your Tk libraries?"
164 ,'$TCL_LIBPATH'
165 ))
166
167 # What is the name of the Tk lib?
168 opts.Add(
169 'TK_LIB'
170 ,"Name of Tk lib (eg 'tk' or 'tk83'), or full path to static library"
171 ,default_tk_lib
172 )
173
174 # Static linking to TkTable
175
176 opts.Add(BoolOption(
177 'STATIC_TCLTK'
178 ,'Set true for static linking for Tcl/Tk and TkTable'
179 ,False
180 ))
181
182 opts.Add(
183 'TKTABLE_LIBPATH'
184 ,'Location of TkTable static library'
185 ,'$TCL_LIBPATH/Tktable2.8'
186 )
187
188 opts.Add(
189 'TKTABLE_LIB'
190 ,'Stem name of TkTable (eg tktable2.8, no ".so" or "lib") shared library, or full path of static tktable (/usr/lib/...)'
191 ,default_tktable_lib
192 )
193
194 opts.Add(
195 '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 'INSTALL_PREFIX'
226 ,'Root location for installed files'
227 ,'/usr/local'
228 )
229
230 opts.Add(
231 'INSTALL_BIN'
232 ,'Location to put binaries during installation'
233 ,"$INSTALL_PREFIX/bin"
234 )
235
236 opts.Add(
237 'INSTALL_LIB'
238 ,'Location to put binaries during installation'
239 ,"$INSTALL_PREFIX/lib"
240 )
241
242 opts.Add(
243 '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 opts.Add(
255 'PYGTK_ASSETS'
256 ,'Default location for Glade assets (placed in pygtk/interface/config.py)'
257 ,default_install_assets
258 )
259
260 opts.Add(BoolOption(
261 'DEBUG'
262 ,"Compile source with debugger symbols, eg for use with 'gdb'"
263 ,False
264 ))
265
266 opts.Add(
267 'INSTALL_ROOT'
268 ,'For use by RPM only: location of %{buildroot} during rpmbuild'
269 ,""
270 )
271
272 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 # TODO: OTHER OPTIONS?
280 # TODO: flags for optimisation
281 # TODO: turning on/off bintoken functionality
282 # TODO: Where will the 'Makefile.bt' file be installed?
283
284 # 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 env = Environment(ENV=os.environ)
290 Tool('lex')(env)
291 Tool('yacc')(env)
292 Tool('fortran')(env)
293 Tool('swig')(env)
294
295 if platform.system()=='Windows' and env.has_key('MSVS'):
296 print "INCLUDE =",env['ENV']['INCLUDE']
297 print "LIB =",env['ENV']['LIB']
298 print "PATH =",env['ENV']['PATH']
299 env.Append(CPPPATH=env['ENV']['INCLUDE'])
300 env.Append(LIBPATH=env['ENV']['LIB'])
301
302 opts.Update(env)
303 opts.Save('options.cache',env)
304
305 Help(opts.GenerateHelpText(env))
306
307 with_tcltk_gui = (env['WITHOUT_TCLTK']==False)
308 without_tcltk_reason = "disabled by options/config.py"
309
310 with_python = (env['WITHOUT_PYTHON']==False)
311 without_python_reason = "disabled by options/config.py"
312
313 with_cunit_tests = env['WITH_CUNIT_TESTS']
314 without_cunit_reason = "not requested"
315
316 #print "SOLVERS:",env['WITH_SOLVERS']
317 #print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
318 #print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
319
320 can_install = True
321 if platform.system()=='Windows':
322 can_install = False
323
324 env['CAN_INSTALL']=can_install
325
326 print "TCL_CPPPATH =",env['TCL_CPPPATH']
327 print "TCL_LIBPATH =",env['TCL_LIBPATH']
328 print "TCL_LIB =",env['TCL_LIB']
329
330 #------------------------------------------------------
331 # SPECIAL CONFIGURATION TESTS
332
333 need_fortran = False
334
335 #----------------
336 # SWIG
337
338 import os,re
339
340 def get_swig_version(env):
341 cmd = env['SWIG']+' -version'
342 (cin,coutcerr) = os.popen4(cmd)
343 output = coutcerr.read()
344
345 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 m = expr.search(output);
348 if not m:
349 return None
350 maj = int(m.group('maj'))
351 min = int(m.group('min'))
352 pat = int(m.group('pat'))
353
354 return (maj,min,pat)
355
356
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 context.env['SWIGVERSION']=tuple([maj,min,pat])
367
368 if maj == 1 and (
369 min > 3
370 or (min == 3 and pat >= 24)
371 ):
372 context.Result("ok, %d.%d.%d" % (maj,min,pat))
373 return 1;
374 else:
375 context.Result("too old, %d.%d.%d" % (maj,min,pat))
376 return 0;
377
378 #----------------
379 # General purpose library-and-header test
380
381 class KeepContext:
382 def __init__(self,context,varprefix,static=False):
383 self.keep = {}
384 for k in ['LIBS','LIBPATH','CPPPATH','LINKFLAGS']:
385 if context.env.has_key(k):
386 self.keep[k] = context.env[k]
387 else:
388 self.keep[k] = None
389
390 if context.env.has_key(varprefix+'_CPPPATH'):
391 context.env.Append(CPPPATH=[env[varprefix+'_CPPPATH']])
392 #print "Adding '"+str(cpppath_add)+"' to cpp path"
393
394 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
405 if context.env.has_key(varprefix+'_LIB'):
406 context.env.Append(LIBS=[env[varprefix+'_LIB']])
407 #print "Adding '"+str(libs_add)+"' to libs"
408
409 def restore(self,context):
410 #print "RESTORING CONTEXT"
411 #print self.keep
412 #print "..."
413 for k in self.keep:
414 if self.keep[k]==None:
415 if context.env.has_key(k):
416 #print "Clearing "+str(k)
417 del context.env[k];
418 else:
419 #print "Restoring "+str(k)+" to '"+self.keep[k]+"'"
420 context.env[k]=self.keep[k];
421
422 def CheckExtLib(context,libname,text,ext='.c',varprefix=None,static=False):
423 """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 if static:
429 context.Message( 'Checking for static '+libname+'... ' )
430 else:
431 context.Message( 'Checking for '+libname+'... ' )
432
433 if varprefix==None:
434 varprefix = libname.upper()
435
436 keep = KeepContext(context,varprefix,static)
437
438 if not context.env.has_key(varprefix+'_LIB'):
439 # if varprefix_LIB were in env, KeepContext would
440 # have appended it already
441 context.env.Append(LIBS=libname)
442
443 is_ok = context.TryLink(text,ext)
444
445 #print "Link success? ",(is_ok != 0)
446
447 keep.restore(context)
448
449 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
450 # print "Restored LIBS="+libname
451 # print "Restored LIBPATH="+str(context.env['LIBPATH'])
452
453 context.Result(is_ok)
454 return is_ok
455
456 #----------------
457 # 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 # 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
497 #----------------
498 # 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 # CUnit test
518
519 cunit_test_text = """
520 #include <CUnit/CUnit.h>
521 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 return 0;
534 }
535 """
536
537 def CheckCUnit(context):
538 return CheckExtLib(context,'cunit',cunit_test_text)
539
540 #----------------
541 # Tcl test
542
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 return CheckExtLib(context,'tcl',tcl_check_text,static=env['STATIC_TCLTK'])
554
555 def CheckTclVersion(context):
556 keep = KeepContext(context,'TCL',static=env['STATIC_TCLTK'])
557 context.Message("Checking Tcl version... ")
558 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
559 keep.restore(context)
560 if not is_ok:
561 context.Result("failed to run check")
562 return 0
563
564 major,minor,patch = tuple([int(i) for i in output.split(".")])
565 if major != 8 or minor > 3:
566 context.Result(output+" (bad version)")
567 # bad version
568 return 0
569
570 # good version
571 context.Result(output+" (good)")
572 return 1
573
574 #----------------
575 # Tk test
576
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 return CheckExtLib(context,'tk',tcl_check_text,static=env['STATIC_TCLTK'])
587
588
589 def CheckTkVersion(context):
590 keep = KeepContext(context,'TK',static=context.env['STATIC_TCLTK'])
591 context.Message("Checking Tk version... ")
592 #print "LINKFLAGS =",context.env['LINKFLAGS']
593 (is_ok,output) = context.TryRun(tk_check_text,'.c')
594 keep.restore(context)
595 if not is_ok:
596 context.Result("failed to run check")
597 return 0
598 context.Result(output)
599
600 major,minor,patch = tuple([int(i) for i in output.split(".")])
601 if major != 8 or minor > 3:
602 # bad version
603 return 0
604
605 # good version
606 return 1
607
608 #----------------
609 # 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 # GCC Version sniffing
643
644 # TODO FIXME
645
646 gcc_version4 = False
647
648 #------------------------------------------------------
649 # CONFIGURATION
650
651 conf = Configure(env
652 , custom_tests = {
653 'CheckSwigVersion' : CheckSwigVersion
654 , 'CheckCUnit' : CheckCUnit
655 , 'CheckTcl' : CheckTcl
656 , 'CheckTclVersion' : CheckTclVersion
657 , 'CheckTk' : CheckTk
658 , 'CheckTkVersion' : CheckTkVersion
659 , 'CheckGcc' : CheckGcc
660 , 'CheckGccVisibility' : CheckGccVisibility
661 , 'CheckYacc' : CheckYacc
662 , 'CheckTkTable' : CheckTkTable
663 , 'CheckX11' : CheckX11
664 # , 'CheckIsNan' : CheckIsNan
665 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
666 }
667 # , config_h = "config.h"
668 )
669
670
671 # Math library
672
673 #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 # Where is 'isnan'?
678
679 if not conf.CheckFunc('isnan'):
680 print "Didn't find isnan"
681 # Exit(1)
682
683 # GCC visibility
684
685 if conf.CheckGcc():
686 conf.env['HAVE_GCC']=True;
687 if env['WITH_GCCVISIBILITY'] and conf.CheckGccVisibility():
688 conf.env['HAVE_GCCVISIBILITY']=True;
689 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
690 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
691
692 # YACC
693
694 if not conf.CheckYacc():
695 print "YACC NOT FOUND OR NOT WORKING"
696 else:
697 conf.env['HAVE_YACC']=True
698
699 conf.env['HAVE_LEX']=True
700
701 # Tcl/Tk
702
703 if conf.CheckTcl():
704 if with_tcltk_gui and conf.CheckTclVersion():
705 if conf.CheckTk():
706 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 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 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
720 with_tcltk_gui = False
721
722 else:
723 without_tcltk_reason = "Tcl not found."
724 with_tcltk_gui = False
725
726 if env['STATIC_TCLTK']:
727 conf.CheckX11()
728
729 # 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 if platform.system()=="Windows":
733 python_lib='python24'
734 else:
735 python_lib='python2.4'
736
737 # SWIG version
738
739 if not conf.CheckSwigVersion():
740 without_python_reason = 'SWIG >= 1.3.24 is required'
741 with_python = False
742
743 # CUnit
744
745 if with_cunit_tests:
746 if not conf.CheckCUnit():
747 without_cunit_reason = 'CUnit not found'
748
749 # BLAS
750
751 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
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 #print "F77:",conf.env['F77']
776 #print "F77COM:",conf.env['F77COM']
777 #print "F77FLAGS:",conf.env['F77FLAGS']
778 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 Exit(1)
787 #else:
788 # print "FORTRAN not required"
789
790 # TODO: -D_HPUX_SOURCE is needed
791
792 # TODO: check size of void*
793
794 # TODO: detect if dynamic libraries are possible or not
795
796 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 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 #---------------------------------------
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 , '@ASC_SHLIBSUFFIX@':env['SHLIBSUFFIX']
829 , '@ASC_SHLIBPREFIX@':env['SHLIBPREFIX']
830 }
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 #------------------------------------------------------
845 # RECIPE: 'SubstInFile', used in pygtk SConscript
846
847 import re
848 from SCons.Script import * # the usual scons stuff you get in a SConscript
849
850 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 """
860 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
882 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
896 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
901 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
914 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 #------------------------------------------------------
920 # Recipe for 'CHMOD' ACTION
921
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
938 #------------------------------------------------------
939 # NSIS Support for SCons
940
941 # 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
945 #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 #------------------------------------------------------
1132 # BUILD...
1133
1134 # so that #include <modulename/headername.h> works across all modules...
1135 env.Append(CPPPATH=['#base/generic'])
1136
1137 if gcc_version4:
1138 env.Append(CCFLAGS=['-fvisibility=hidden'])
1139
1140 if env['DEBUG']:
1141 env.Append(CCFLAGS=['-g'])
1142
1143 #-------------
1144 # TCL/TK GUI
1145
1146 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
1152 env.SConscript(['lsod/SConscript'],'env')
1153
1154 env.SConscript(['linpack/SConscript'],'env')
1155 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
1156 else:
1157 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
1158
1159 #-------------
1160 # PYTHON INTERFACE
1161
1162 if with_python:
1163 env.SConscript(['pygtk/interface/SConscript'],'env')
1164 else:
1165 print "Skipping... Python GUI isn't being built:",without_python_reason
1166
1167 #------------
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 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 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1196
1197
1198 #------------------------------------------------------
1199 # INSTALLATION
1200
1201 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
1205 dirs = ['INSTALL_BIN','INSTALL_DATA','INSTALL_LIB']
1206 install_dirs = [env['INSTALL_ROOT']+env[d] for d in dirs]
1207
1208 # TODO: add install options
1209 env.Alias('install',install_dirs)
1210
1211 env.Install(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1212
1213 #------------------------------------------------------
1214 # CREATE the SPEC file for generation of RPM packages
1215
1216 if platform.system()=="Linux":
1217 env.SubstInFile('ascend.spec.in')

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