/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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