/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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