/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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