/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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