/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 551 - (show annotations) (download)
Sat Apr 29 04:19:17 2006 UTC (13 years, 7 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 import os, commands, platform, distutils.sysconfig, os.path
2
3 version = "0.svn"
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 default_tcl_libpath = "$TCL\\bin"
22 else:
23 default_tcl_lib = "tcl8.3"
24 default_tk_lib = "tk8.3"
25 default_tktable_lib = "Tktable2.8"
26 default_install_assets = "$INSTALL_DATA/ascend/glade/"
27 icon_extension = '.svg'
28 default_tcl = os.path.expanduser("~/activetcl")
29 default_tcl_libpath = "$TCL/lib"
30
31 if not os.path.isdir(default_tcl):
32 default_tcl = '/usr'
33
34 # Package linking option
35 opts.Add(EnumOption(
36 'PACKAGE_LINKING'
37 , 'Style of linking for external libraries'
38 , 'DYNAMIC_PACKAGES'
39 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
40 ))
41
42 opts.Add(BoolOption(
43 'WITH_GCCVISIBILITY'
44 ,"Whether to use GCC Visibility features (only applicable if available)"
45 ,True
46 ))
47
48 # You can turn off building of Tcl/Tk interface
49 opts.Add(BoolOption(
50 'WITH_TCLTK'
51 ,"Set to True if you don't want to build the original Tcl/Tk GUI."
52 , True
53 ))
54
55 # You can turn off the building of the Python interface
56 opts.Add(BoolOption(
57 'WITH_PYTHON'
58 ,"Set to True if you don't want to build Python wrappers."
59 , True
60 ))
61
62 # Which solvers will we allow?
63 opts.Add(ListOption(
64 'WITH_SOLVERS'
65 ,"List of the solvers you want to build. The default is the minimum that"
66 +" works."
67 ,["QRSLV","CMSLV"]
68 ,['QRSLV','MPS','SLV','OPTSQP'
69 ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
70 ,'LSOD','OPTSQP'
71 ]
72 ))
73
74 # 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 # What should the default ASCENDLIBRARY path be?
90 # Note: users can change it by editing their ~/.ascend.ini
91 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 ,"$INSTALL_DATA/models"
96 )
97
98 # 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 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
104 )
105
106 # 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 +" find it, or else use the CUNIT_* options to specify."
112 ,False
113 ))
114
115 # Where are the CUnit includes?
116 opts.Add(PackageOption(
117 'CUNIT_CPPPATH'
118 ,"Where are your CUnit include files?"
119 ,'off'
120 ))
121
122 # Where are the CUnit libraries?
123 opts.Add(PackageOption(
124 'CUNIT_LIBPATH'
125 ,"Where are your CUnit libraries?"
126 ,'off'
127 ))
128
129
130 opts.Add(
131 'TCL'
132 ,'Base of Tcl distribution'
133 ,default_tcl
134 )
135
136 # Where are the Tcl includes?
137 opts.Add(
138 'TCL_CPPPATH'
139 ,"Where are your Tcl include files?"
140 ,"$TCL/include"
141 )
142
143 # Where are the Tcl libs?
144 opts.Add(
145 'TCL_LIBPATH'
146 ,"Where are your Tcl libraries?"
147 ,default_tcl_libpath
148 )
149
150 # What is the name of the Tcl lib?
151 opts.Add(
152 'TCL_LIB'
153 ,"Name of Tcl lib (eg 'tcl' or 'tcl83'), for full path to static library"
154 ,default_tcl_lib
155 )
156
157 # Where are the Tk includes?
158 opts.Add(
159 'TK_CPPPATH'
160 ,"Where are your Tk include files?"
161 ,'$TCL_CPPPATH'
162 )
163
164 # Where are the Tk libs?
165 opts.Add(
166 'TK_LIBPATH'
167 ,"Where are your Tk libraries?"
168 ,'$TCL_LIBPATH'
169 )
170
171 # What is the name of the Tk lib?
172 opts.Add(
173 'TK_LIB'
174 ,"Name of Tk lib (eg 'tk' or 'tk83'), or full path to static library"
175 ,default_tk_lib
176 )
177
178 # Static linking to TkTable
179
180 opts.Add(BoolOption(
181 'STATIC_TCLTK'
182 ,'Set true for static linking for Tcl/Tk and TkTable'
183 ,False
184 ))
185
186 opts.Add(
187 'TKTABLE_LIBPATH'
188 ,'Location of TkTable static library'
189 ,'$TCL_LIBPATH/Tktable2.8'
190 )
191
192 opts.Add(
193 'TKTABLE_LIB'
194 ,'Stem name of TkTable (eg tktable2.8, no ".so" or "lib") shared library, or full path of static tktable (/usr/lib/...)'
195 ,default_tktable_lib
196 )
197
198 opts.Add(
199 '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 'INSTALL_PREFIX'
230 ,'Root location for installed files'
231 ,'/usr/local'
232 )
233
234 opts.Add(
235 'INSTALL_BIN'
236 ,'Location to put binaries during installation'
237 ,"$INSTALL_PREFIX/bin"
238 )
239
240 opts.Add(
241 'INSTALL_LIB'
242 ,'Location to put binaries during installation'
243 ,"$INSTALL_PREFIX/lib"
244 )
245
246 opts.Add(
247 '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 opts.Add(
259 'PYGTK_ASSETS'
260 ,'Default location for Glade assets (placed in pygtk/config.py)'
261 ,default_install_assets
262 )
263
264 opts.Add(BoolOption(
265 'DEBUG'
266 ,"Compile source with debugger symbols, eg for use with 'gdb'"
267 ,False
268 ))
269
270 opts.Add(
271 'INSTALL_ROOT'
272 ,'For use by RPM only: location of %{buildroot} during rpmbuild'
273 ,""
274 )
275
276 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 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 # TODO: OTHER OPTIONS?
291 # TODO: flags for optimisation
292 # TODO: turning on/off bintoken functionality
293 # TODO: Where will the 'Makefile.bt' file be installed?
294
295 # 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 env['IS_MINGW']=True
300 else:
301 env = Environment(ENV=os.environ)
302 Tool('lex')(env)
303 Tool('yacc')(env)
304 Tool('fortran')(env)
305 Tool('swig')(env)
306
307 if platform.system()=='Windows' and env.has_key('MSVS'):
308 print "INCLUDE =",env['ENV']['INCLUDE']
309 print "LIB =",env['ENV']['LIB']
310 print "PATH =",env['ENV']['PATH']
311 env.Append(CPPPATH=env['ENV']['INCLUDE'])
312 env.Append(LIBPATH=env['ENV']['LIB'])
313
314 opts.Update(env)
315 opts.Save('options.cache',env)
316
317 Help(opts.GenerateHelpText(env))
318
319 with_tcltk = env.get('WITH_TCLTK')
320 without_tcltk_reason = "disabled by options/config.py"
321
322 with_python = env.get('WITH_PYTHON')
323 without_python_reason = "disabled by options/config.py"
324
325 with_cunit_tests = env.get('WITH_CUNIT_TESTS')
326 without_cunit_reason = "not requested"
327
328 #print "SOLVERS:",env['WITH_SOLVERS']
329 #print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
330 #print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
331
332 can_install = True
333 if platform.system()=='Windows':
334 can_install = False
335
336 env['CAN_INSTALL']=can_install
337
338 print "TCL_CPPPATH =",env['TCL_CPPPATH']
339 print "TCL_LIBPATH =",env['TCL_LIBPATH']
340 print "TCL_LIB =",env['TCL_LIB']
341
342 #------------------------------------------------------
343 # SPECIAL CONFIGURATION TESTS
344
345 need_fortran = False
346
347 #----------------
348 # SWIG
349
350 import os,re
351
352 def get_swig_version(env):
353 cmd = env['SWIG']+' -version'
354 (cin,coutcerr) = os.popen4(cmd)
355 output = coutcerr.read()
356
357 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 m = expr.search(output);
360 if not m:
361 return None
362 maj = int(m.group('maj'))
363 min = int(m.group('min'))
364 pat = int(m.group('pat'))
365
366 return (maj,min,pat)
367
368
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 context.env['SWIGVERSION']=tuple([maj,min,pat])
379
380 if maj == 1 and (
381 min > 3
382 or (min == 3 and pat >= 24)
383 ):
384 context.Result("ok, %d.%d.%d" % (maj,min,pat))
385 return 1;
386 else:
387 context.Result("too old, %d.%d.%d" % (maj,min,pat))
388 return 0;
389
390 #----------------
391 # General purpose library-and-header test
392
393 class KeepContext:
394 def __init__(self,context,varprefix,static=False):
395 self.keep = {}
396 for k in ['LIBS','LIBPATH','CPPPATH','LINKFLAGS']:
397 if context.env.has_key(k):
398 self.keep[k] = context.env[k]
399 else:
400 self.keep[k] = None
401
402 if context.env.has_key(varprefix+'_CPPPATH'):
403 context.env.Append(CPPPATH=[env[varprefix+'_CPPPATH']])
404 #print "Adding '"+str(cpppath_add)+"' to cpp path"
405
406 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
417 if context.env.has_key(varprefix+'_LIB'):
418 context.env.Append(LIBS=[env[varprefix+'_LIB']])
419 #print "Adding '"+str(libs_add)+"' to libs"
420
421 def restore(self,context):
422 #print "RESTORING CONTEXT"
423 #print self.keep
424 #print "..."
425 for k in self.keep:
426 if self.keep[k]==None:
427 if context.env.has_key(k):
428 #print "Clearing "+str(k)
429 del context.env[k];
430 else:
431 #print "Restoring "+str(k)+" to '"+self.keep[k]+"'"
432 context.env[k]=self.keep[k];
433
434 def CheckExtLib(context,libname,text,ext='.c',varprefix=None,static=False):
435 """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 if static:
441 context.Message( 'Checking for static '+libname+'... ' )
442 else:
443 context.Message( 'Checking for '+libname+'... ' )
444
445 if varprefix==None:
446 varprefix = libname.upper()
447
448 keep = KeepContext(context,varprefix,static)
449
450 if not context.env.has_key(varprefix+'_LIB'):
451 # if varprefix_LIB were in env, KeepContext would
452 # have appended it already
453 context.env.Append(LIBS=libname)
454
455 is_ok = context.TryLink(text,ext)
456
457 #print "Link success? ",(is_ok != 0)
458
459 keep.restore(context)
460
461 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
462 # print "Restored LIBS="+libname
463 # print "Restored LIBPATH="+str(context.env['LIBPATH'])
464
465 context.Result(is_ok)
466 return is_ok
467
468 #----------------
469 # 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 # 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 if not context.env.has_key('WITH_GCCVISIBILITY') or not env['WITH_GCCVISIBILITY']:
506 context.Result("disabled")
507 return 0
508 is_ok = context.TryCompile(gccvisibility_test_text,".c")
509 context.Result(is_ok)
510 return is_ok
511
512 #----------------
513 # 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 # CUnit test
533
534 cunit_test_text = """
535 #include <CUnit/CUnit.h>
536 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 return 0;
549 }
550 """
551
552 def CheckCUnit(context):
553 return CheckExtLib(context,'cunit',cunit_test_text)
554
555 #----------------
556 # Tcl test
557
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 return CheckExtLib(context,'tcl',tcl_check_text,static=env['STATIC_TCLTK'])
569
570 def CheckTclVersion(context):
571 keep = KeepContext(context,'TCL',static=env['STATIC_TCLTK'])
572 context.Message("Checking Tcl version... ")
573 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
574 keep.restore(context)
575 if not is_ok:
576 context.Result("failed to run check")
577 return 0
578
579 major,minor,patch = tuple([int(i) for i in output.split(".")])
580 if major != 8 or minor > 3:
581 context.Result(output+" (bad version)")
582 # bad version
583 return 0
584
585 # good version
586 context.Result(output+" (good)")
587 return 1
588
589 #----------------
590 # Tk test
591
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 return CheckExtLib(context,'tk',tcl_check_text,static=env['STATIC_TCLTK'])
602
603
604 def CheckTkVersion(context):
605 keep = KeepContext(context,'TK',static=context.env['STATIC_TCLTK'])
606 context.Message("Checking Tk version... ")
607 #print "LINKFLAGS =",context.env['LINKFLAGS']
608 (is_ok,output) = context.TryRun(tk_check_text,'.c')
609 keep.restore(context)
610 if not is_ok:
611 context.Result("failed to run check")
612 return 0
613 context.Result(output)
614
615 major,minor,patch = tuple([int(i) for i in output.split(".")])
616 if major != 8 or minor > 3:
617 # bad version
618 return 0
619
620 # good version
621 return 1
622
623 #----------------
624 # 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 # GCC Version sniffing
658
659 # TODO FIXME
660
661 gcc_version4 = False
662
663 #------------------------------------------------------
664 # CONFIGURATION
665
666 conf = Configure(env
667 , custom_tests = {
668 'CheckSwigVersion' : CheckSwigVersion
669 , 'CheckCUnit' : CheckCUnit
670 , 'CheckTcl' : CheckTcl
671 , 'CheckTclVersion' : CheckTclVersion
672 , 'CheckTk' : CheckTk
673 , 'CheckTkVersion' : CheckTkVersion
674 , 'CheckGcc' : CheckGcc
675 , 'CheckGccVisibility' : CheckGccVisibility
676 , 'CheckYacc' : CheckYacc
677 , 'CheckTkTable' : CheckTkTable
678 , 'CheckX11' : CheckX11
679 # , 'CheckIsNan' : CheckIsNan
680 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
681 }
682 # , config_h = "config.h"
683 )
684
685
686 # Math library
687
688 #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 # Where is 'isnan'?
693
694 if not conf.CheckFunc('isnan'):
695 print "Didn't find isnan"
696 # Exit(1)
697
698 # GCC visibility
699
700 if conf.CheckGcc():
701 conf.env['HAVE_GCC']=True;
702 if env['WITH_GCCVISIBILITY'] and conf.CheckGccVisibility():
703 conf.env['HAVE_GCCVISIBILITY']=True;
704 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
705 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
706
707 # YACC
708
709 if not conf.CheckYacc():
710 print "YACC NOT FOUND OR NOT WORKING"
711 else:
712 conf.env['HAVE_YACC']=True
713
714 conf.env['HAVE_LEX']=True
715
716 # Tcl/Tk
717
718 if conf.CheckTcl():
719 if with_tcltk and conf.CheckTclVersion():
720 if conf.CheckTk():
721 if with_tcltk and conf.CheckTkVersion():
722 if conf.CheckTkTable():
723 pass
724 else:
725 without_tcltk_reason = "TkTable not found"
726 with_tcltk = False
727 else:
728 without_tcltk_reason = "Require Tk version <= 8.3. See 'scons -h'"
729 with_tcltk = False
730 else:
731 without_tcltk_reason = "Tk not found."
732 with_tcltk = False
733 else:
734 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
735 with_tcltk = False
736
737 else:
738 without_tcltk_reason = "Tcl not found."
739 with_tcltk = False
740
741 if env['STATIC_TCLTK']:
742 conf.CheckX11()
743
744 # 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 if platform.system()=="Windows":
748 python_lib='python24'
749 else:
750 python_lib='python2.4'
751
752 # SWIG version
753
754 if not conf.CheckSwigVersion():
755 without_python_reason = 'SWIG >= 1.3.24 is required'
756 with_python = False
757
758 # CUnit
759
760 if with_cunit_tests:
761 if not conf.CheckCUnit():
762 without_cunit_reason = 'CUnit not found'
763
764 # BLAS
765
766 need_blas=False
767 if with_tcltk:
768 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
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 #print "F77:",conf.env['F77']
789 #print "F77COM:",conf.env['F77COM']
790 #print "F77FLAGS:",conf.env['F77FLAGS']
791 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 Exit(1)
800 #else:
801 # print "FORTRAN not required"
802
803 # TODO: -D_HPUX_SOURCE is needed
804
805 # TODO: check size of void*
806
807 # TODO: detect if dynamic libraries are possible or not
808
809 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 if with_python and not conf.CheckHeader(['basetsd.h','BaseTsd.h']):
816 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 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 #---------------------------------------
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 , '@ASC_SHLIBSUFFIX@':env['SHLIBSUFFIX']
842 , '@ASC_SHLIBPREFIX@':env['SHLIBPREFIX']
843 }
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 #------------------------------------------------------
858 # RECIPE: 'SubstInFile', used in pygtk SConscript
859
860 import re
861 from SCons.Script import * # the usual scons stuff you get in a SConscript
862
863 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 """
873 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
895 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
909 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
914 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
927 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 #------------------------------------------------------
933 # Recipe for 'CHMOD' ACTION
934
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
951 #------------------------------------------------------
952 # NSIS Support for SCons
953
954 # 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
958 #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 #------------------------------------------------------
1145 # BUILD...
1146
1147 # so that #include <modulename/headername.h> works across all modules...
1148 env.Append(CPPPATH=['#base/generic'])
1149
1150 if gcc_version4:
1151 env.Append(CCFLAGS=['-fvisibility=hidden'])
1152
1153 if env['DEBUG']:
1154 env.Append(CCFLAGS=['-g'])
1155
1156 #-------------
1157 # TCL/TK GUI
1158
1159 if with_tcltk:
1160 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
1165 env.SConscript(['lsod/SConscript'],'env')
1166
1167 env.SConscript(['linpack/SConscript'],'env')
1168 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
1169 else:
1170 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
1171
1172 #-------------
1173 # PYTHON INTERFACE
1174
1175 if with_python:
1176 env.SConscript(['pygtk/SConscript'],'env')
1177 else:
1178 print "Skipping... Python GUI isn't being built:",without_python_reason
1179
1180 #------------
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 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 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1209
1210
1211 #------------------------------------------------------
1212 # INSTALLATION
1213
1214 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
1218 dirs = ['INSTALL_BIN','INSTALL_DATA','INSTALL_LIB']
1219 install_dirs = [env['INSTALL_ROOT']+env[d] for d in dirs]
1220
1221 # TODO: add install options
1222 env.Alias('install',install_dirs)
1223
1224 env.Install(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1225
1226 #------------------------------------------------------
1227 # CREATE the SPEC file for generation of RPM packages
1228
1229 if platform.system()=="Linux":
1230 env.SubstInFile('ascend.spec.in')

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