/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 705 - (show annotations) (download)
Tue Jun 27 02:37:49 2006 UTC (14 years, 3 months ago) by johnpye
File size: 34735 byte(s)
Improved detection of math library.
Fixed bug that was affecting detection of CUnit library.
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 #print "Keeping env %s = %s" % (k,context.env.get(k))
531 self.keep[k]=context.env.get(k)
532
533 if context.env.has_key(varprefix+'_CPPPATH'):
534 context.env.Append(CPPPATH=[env[varprefix+'_CPPPATH']])
535 #print "Adding '"+str(cpppath_add)+"' to cpp path"
536
537 if static:
538 staticlib=env[varprefix+'_LIB']
539 #print "STATIC LIB = ",staticlib
540 context.env.Append(
541 LINKFLAGS=[staticlib]
542 )
543 else:
544 if context.env.has_key(varprefix+'_LIBPATH'):
545 context.env.Append(LIBPATH=[env[varprefix+'_LIBPATH']])
546 #print "Adding '"+str(libpath_add)+"' to lib path"
547
548 if context.env.has_key(varprefix+'_LIB'):
549 context.env.Append(LIBS=[env[varprefix+'_LIB']])
550 #print "Adding '"+str(env[varprefix+'_LIB'])+"' to libs"
551
552 def restore(self,context):
553 #print "RESTORING CONTEXT"
554 #print self.keep
555 #print "..."
556 for k in self.keep:
557 if self.keep[k]==None:
558 if context.env.has_key(k):
559 #print "Clearing "+str(k)
560 del context.env[k];
561 else:
562 #print "Restoring %s to '%s'" %(k,self.keep.get(k))
563 context.env[k]=self.keep[k];
564
565 def CheckExtLib(context,libname,text,ext='.c',varprefix=None,static=False):
566 """This method will check for variables LIBNAME_LIBPATH
567 and LIBNAME_CPPPATH and try to compile and link the
568 file with the provided text, linking with the
569 library libname."""
570
571 if static:
572 context.Message( 'Checking for static '+libname+'... ' )
573 else:
574 context.Message( 'Checking for '+libname+'... ' )
575
576 if varprefix==None:
577 varprefix = libname.upper()
578
579 #print "LIBS is currently:",context.env.get('LIBS')
580 keep = KeepContext(context,varprefix,static)
581
582 if not context.env.has_key(varprefix+'_LIB'):
583 # if varprefix_LIB were in env, KeepContext would
584 # have appended it already
585 context.env.Append(LIBS=[libname])
586
587 is_ok = context.TryLink(text,ext)
588
589 #print "Link success? ",(is_ok != 0)
590
591 keep.restore(context)
592
593 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
594 # print "Restored LIBS="+str(context.env['LIBS'])
595 # print "Restored LIBPATH="+str(context.env['LIBPATH'])
596
597 context.Result(is_ok)
598 return is_ok
599
600 #----------------
601 # GCC
602
603 gcc_test_text = """
604 #ifndef __GNUC__
605 # error "Not using GCC"
606 #endif
607
608 int main(void){
609 return __GNUC__;
610 }
611 """
612
613 def CheckGcc(context):
614 context.Message("Checking for GCC... ")
615 is_ok = context.TryCompile(gcc_test_text,".c")
616 context.Result(is_ok)
617 return is_ok
618
619 #----------------
620 # GCC VISIBILITY feature
621
622 gccvisibility_test_text = """
623 #if __GNUC__ < 4
624 # error "Require GCC version 4 or newer"
625 #endif
626
627 __attribute__ ((visibility("default"))) int x;
628
629 int main(void){
630 extern int x;
631 x = 4;
632 }
633 """
634
635 def CheckGccVisibility(context):
636 context.Message("Checking for GCC 'visibility' capability... ")
637 if not context.env.has_key('WITH_GCCVISIBILITY') or not env['WITH_GCCVISIBILITY']:
638 context.Result("disabled")
639 return 0
640 is_ok = context.TryCompile(gccvisibility_test_text,".c")
641 context.Result(is_ok)
642 return is_ok
643
644 #----------------
645 # YACC
646
647 yacc_test_text = """
648 %{
649 #include <stdio.h>
650 %}
651 %token MSG
652 %start ROOT
653 %%
654 ROOT:
655 MSG { printf("HELLO"); }
656 ;
657 %%
658 """
659
660 def CheckYacc(context):
661 context.Message("Checking for Yacc ('%s')... " % context.env.get('YACC'))
662 is_ok = context.TryCompile(yacc_test_text,".y")
663 context.Result(is_ok)
664 return is_ok
665
666 #----------------
667 # CUnit test
668
669 cunit_test_text = """
670 #include <CUnit/CUnit.h>
671 int maxi(int i1, int i2){
672 return (i1 > i2) ? i1 : i2;
673 }
674
675 void test_maxi(void){
676 CU_ASSERT(maxi(0,2) == 2);
677 CU_ASSERT(maxi(0,-2) == 0);
678 CU_ASSERT(maxi(2,2) == 2);
679
680 }
681 int main(void){
682 /* CU_initialize_registry() */
683 return 0;
684 }
685 """
686
687 def CheckCUnit(context):
688 return CheckExtLib(context,'cunit',cunit_test_text)
689
690 #----------------
691 # MATH test
692
693 math_test_text = """
694 #ifndef _ALL_SOURCE
695 # define _ALL_SOURCE
696 #endif
697 #ifndef _XOPEN_SOURCE
698 # define _XOPEN_SOURCE
699 #endif
700 #ifndef _XOPEN_SOURCE_EXTENDED
701 # define _XOPEN_SOURCE_EXTENDED 1
702 #endif
703 #include <math.h>
704 int main(void){
705 double x = 1.0; double y = 1.0; int i = 1;
706 acosh(x); asinh(x); atanh(x); cbrt(x); expm1(x); erf(x); erfc(x); isnan(x);
707 j0(x); j1(x); jn(i,x); ilogb(x); logb(x); log1p(x); rint(x);
708 y0(x); y1(x); yn(i,x);
709 #ifdef _THREAD_SAFE
710 gamma_r(x,&i);
711 lgamma_r(x,&i);
712 #else
713 gamma(x);
714 lgamma(x);
715 #endif
716 hypot(x,y); nextafter(x,y); remainder(x,y); scalb(x,y);
717 return 0;
718 }
719 """
720
721 def CheckMath(context):
722 context.Message('Checking for IEE math library... ')
723 libsave=context.env.get('LIBS');
724 context.env.AppendUnique(LIBS=['m'])
725 is_ok=context.TryLink(math_test_text,".c")
726 context.Result(is_ok)
727 if not is_ok:
728 context.env['LIBS']=libsave
729 return is_ok
730
731 #----------------
732 # IDA test
733
734 ida_test_text = """
735 #include <ida.h>
736 #include <nvector_serial.h>
737 #include <ida_spgmr.h>
738 int main(){
739 void *ida_mem;
740 ida_mem = IDACreate();
741 }
742 """
743
744 def CheckIDA(context):
745 context.Message( 'Checking for IDA (SUNDIALS)... ' )
746
747 # add SUNDIALS subdirectories as well (what a pain)
748 if context.env.get('IDA_CPPPATH'):
749 extra = [context.env['IDA_CPPPATH']+"/ida",context.env['IDA_CPPPATH']+"/sundials"]
750 context.env.Append(CPPPATH=extra)
751
752 if ',' in context.env.get('IDA_LIB'):
753 context.env['IDA_LIB']=context.env['IDA_LIB'].split(',')
754 #print "IDA_LIB NOW =",context.env['IDA_LIB']
755 else:
756 print "NO COMMA IN IDA_LIB:",context.env['IDA_LIB']
757
758 keep = KeepContext(context,"IDA")
759
760 is_ok = context.TryLink(ida_test_text,".c")
761 context.Result(is_ok)
762
763 keep.restore(context)
764
765 if is_ok:
766 context.env.Append(IDA_CPPPATH_EXTRA=extra)
767
768 return is_ok
769
770 #----------------
771 # Tcl test
772
773 # TCL and TK required version 8.1, 8.2, 8.3, or 8.4:
774 tcltk_minor_newest_acceptable = 4
775 tcltk_major_required = 8
776
777 tcl_check_text = r"""
778 #include <tcl.h>
779 #include <stdio.h>
780 int main(void){
781 printf("%s",TCL_PATCH_LEVEL);
782 return 0;
783 }
784 """
785
786 def CheckTcl(context):
787 return CheckExtLib(context,'tcl',tcl_check_text,static=env['STATIC_TCLTK'])
788
789 def CheckTclVersion(context):
790 keep = KeepContext(context,'TCL',static=env['STATIC_TCLTK'])
791 context.Message("Checking Tcl version... ")
792 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
793 keep.restore(context)
794 if not is_ok:
795 context.Result("failed to run check")
796 return 0
797
798 major,minor,patch = tuple([int(i) for i in output.split(".")])
799 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
800 context.Result(output+" (bad version)")
801 # bad version
802 return 0
803
804 # good version
805 context.Result(output+", good")
806 return 1
807
808 #----------------
809 # Tk test
810
811 tk_check_text = r"""
812 #include <tk.h>
813 #include <stdio.h>
814 int main(void){
815 printf("%s",TK_PATCH_LEVEL);
816 return 0;
817 }
818 """
819 def CheckTk(context):
820 return CheckExtLib(context,'tk',tk_check_text,static=env['STATIC_TCLTK'])
821
822
823 def CheckTkVersion(context):
824 keep = KeepContext(context,'TK',static=context.env['STATIC_TCLTK'])
825 context.Message("Checking Tk version... ")
826 #print "LINKFLAGS =",context.env['LINKFLAGS']
827 (is_ok,output) = context.TryRun(tk_check_text,'.c')
828 keep.restore(context)
829 if not is_ok:
830 context.Result("failed to run check")
831 return 0
832
833 major,minor,patch = tuple([int(i) for i in output.split(".")])
834 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
835 # bad version
836 context.Result(output+" (bad version)")
837 return 0
838
839 # good version
840 context.Result(output+" (good)")
841 return 1
842
843 #----------------
844 # Tktable test
845
846 tktable_check_text = r"""
847 #include <tkTable.h>
848 #include <stdio.h>
849 int main(void){
850 Table mytable;
851 return 0;
852 }
853 """
854
855 def CheckTkTable(context):
856 return CheckExtLib(context,'tktable',tktable_check_text,static=env['STATIC_TCLTK'])
857
858 #---------------
859 # X11 test
860
861 x11_check_text = r"""
862 #include <X11/Xlib.h>
863 #include <X11/IntrinsicP.h>
864 #include <X11/Intrinsic.h>
865 #include <X11/ObjectP.h>
866 #include <X11/Object.h>
867 int main(void){
868 Object mything;
869 return 0;
870 }
871 """
872
873 def CheckX11(context):
874 return CheckExtLib(context,'X11',x11_check_text)
875
876 #----------------
877 # GCC Version sniffing
878
879 # TODO FIXME
880
881 gcc_version4 = False
882
883 #------------------------------------------------------
884 # CONFIGURATION
885
886 conf = Configure(env
887 , custom_tests = {
888 'CheckMath' : CheckMath
889 , 'CheckSwigVersion' : CheckSwigVersion
890 , 'CheckCUnit' : CheckCUnit
891 , 'CheckTcl' : CheckTcl
892 , 'CheckTclVersion' : CheckTclVersion
893 , 'CheckTk' : CheckTk
894 , 'CheckTkVersion' : CheckTkVersion
895 , 'CheckGcc' : CheckGcc
896 , 'CheckGccVisibility' : CheckGccVisibility
897 , 'CheckYacc' : CheckYacc
898 , 'CheckTkTable' : CheckTkTable
899 , 'CheckX11' : CheckX11
900 , 'CheckIDA' : CheckIDA
901 # , 'CheckIsNan' : CheckIsNan
902 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
903 }
904 # , config_h = "config.h"
905 )
906
907
908 # Math library
909
910 if need_libm:
911 if not conf.CheckMath():
912 print 'Did not find math library, exiting!'
913 Exit(1)
914 #pass
915
916 # Where is 'isnan'?
917
918 if not conf.CheckFunc('isnan'):
919 print "Didn't find isnan"
920 # Exit(1)
921
922 # GCC visibility
923
924 if conf.CheckGcc():
925 conf.env['HAVE_GCC']=True;
926 if env['WITH_GCCVISIBILITY'] and conf.CheckGccVisibility():
927 conf.env['HAVE_GCCVISIBILITY']=True;
928 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
929 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
930
931 # YACC
932
933 if not conf.CheckYacc():
934 print "YACC NOT FOUND OR NOT WORKING"
935 else:
936 conf.env['HAVE_YACC']=True
937
938 conf.env['HAVE_LEX']=True
939
940 # Tcl/Tk
941
942 if with_tcltk:
943 if conf.CheckTcl():
944 if conf.CheckTclVersion():
945 if conf.CheckTk():
946 if with_tcltk and conf.CheckTkVersion():
947 if env['STATIC_TCLTK']:
948 if conf.CheckTkTable():
949 pass
950 else:
951 without_tcltk_reason = "TkTable not found"
952 with_tcltk = False
953 else:
954 without_tcltk_reason = "Require Tk version <= 8.4. See 'scons -h'"
955 with_tcltk = False
956 else:
957 without_tcltk_reason = "Tk not found."
958 with_tcltk = False
959 else:
960 without_tcltk_reason = "Require Tcl <= 8.4 Tcl."
961 with_tcltk = False
962
963 else:
964 without_tcltk_reason = "Tcl not found."
965 with_tcltk = False
966
967 if env['STATIC_TCLTK']:
968 conf.CheckX11()
969
970 # Python... obviously we're already running python, so we just need to
971 # check that we can link to the python library OK:
972
973 if platform.system()=="Windows":
974 python_lib='python24'
975 else:
976 python_lib='python2.4'
977
978 # SWIG version
979
980 if not conf.CheckSwigVersion():
981 without_python_reason = 'SWIG >= 1.3.24 is required'
982 with_python = False
983
984 # CUnit
985
986 if with_cunit:
987 if not conf.CheckCUnit():
988 without_cunit_reason = 'CUnit not found'
989 with_cunit = False
990 #print "CUNIT NOT FOUND, LIBS=",conf.env.get('LIBS')
991
992 # IDA
993
994 if not with_ida:
995 without_ida_reason = "Not selected (see config option WITH_SOLVERS)"
996 elif not conf.CheckIDA():
997 with_ida = False
998 without_ida_reason = "IDA not found"
999
1000 # BLAS
1001
1002 need_blas=False
1003
1004 if with_lsode:
1005 need_fortran = True
1006 need_blas=True
1007
1008 if need_blas:
1009 if conf.CheckLib('blas'):
1010 with_local_blas = False
1011 without_local_blas_reason = "Found BLAS installed on system"
1012 else:
1013 with_local_blas = True
1014 need_fortran = True
1015 else:
1016 with_local_blas= False;
1017 without_local_blas_reason = "BLAS not required"
1018
1019 # FORTRAN
1020
1021 if need_fortran:
1022 conf.env.Tool('fortran')
1023 detect_fortran = conf.env.Detect(['g77','f77','gfortran'])
1024 if detect_fortran:
1025 # For some reason, g77 doesn't get detected properly on MinGW
1026 if not env.has_key('F77') and not env.has_key('FORTRAN'):
1027 conf.env.Replace(F77=detect_fortran)
1028 conf.env.Replace(F77COM='$F77 $F77FLAGS -c -o $TARGET $SOURCE')
1029 conf.env.Replace(F77FLAGS='')
1030 #print "F77:",conf.env['F77']
1031 #print "F77COM:",conf.env['F77COM']
1032 #print "F77FLAGS:",conf.env['F77FLAGS']
1033 fortran_builder = Builder(
1034 action='$F77COM'
1035 , suffix='.o'
1036 , src_suffix='.f'
1037 )
1038 conf.env.Append(BUILDERS={'Fortran':fortran_builder})
1039 else:
1040 with_lsode=False;
1041 without_lsode_reason="FORTRAN-77 required but not found"
1042
1043 #else:
1044 # print "FORTRAN not required"
1045
1046 # F2C
1047
1048 if need_fortran:
1049 if platform.system()=="Windows":
1050 conf.env.Append(LIBPATH='c:\mingw\lib')
1051
1052
1053 # TODO: -D_HPUX_SOURCE is needed
1054
1055 # TODO: check size of void*
1056
1057 # TODO: detect if dynamic libraries are possible or not
1058
1059 if platform.system()=="Windows" and env.has_key('MSVS'):
1060 if not conf.CheckHeader('windows.h') and env['PACKAGE_LINKING']=='DYNAMIC_PACKAGES':
1061 print "Reverting to STATIC_PACKAGES since windows.h is not available. Probably you "\
1062 +"need to install the Microsoft Windows Server 2003 Platform SDK, or similar."
1063 env['PACKAGE_LINKING']='STATIC_PACKAGES'
1064
1065 if with_python and not conf.CheckHeader(['basetsd.h','BaseTsd.h']):
1066 with_python = 0;
1067 without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
1068
1069 conf.env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
1070
1071 conf.Finish()
1072
1073 env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
1074 env.Append(PYTHON_LIB=[python_lib])
1075 env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
1076
1077 #---------------------------------------
1078 # SUBSTITUTION DICTIONARY for .in files
1079
1080 release = env.get('RELEASE')
1081 if release=="0.":
1082 release="0"
1083
1084 subst_dict = {
1085 '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
1086 , '@GLADE_FILE@':'ascend.glade'
1087 , '@HELP_ROOT@':''
1088 , '@ICON_EXTENSION@':icon_extension
1089 , '@INSTALL_ASCDATA@':env['INSTALL_ASCDATA']
1090 , '@INSTALL_BIN@':env['INSTALL_BIN']
1091 , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
1092 , '@INSTALL_LIB@':env['INSTALL_LIB']
1093 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
1094 , '@VERSION@':version
1095 , '@RELEASE@':release
1096 , '@DISTTAR_NAME@':env['DISTTAR_NAME']
1097 , '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
1098 , '@ASC_SHLIBSUFFIX@':env['SHLIBSUFFIX']
1099 , '@ASC_SHLIBPREFIX@':env['SHLIBPREFIX']
1100 , '@ASC_ENV_TK_DEFAULT@' : '$$ASCENDDIST/tcltk'
1101 , '@ASC_DISTDIR_REL_BIN@' : default_rel_distdir
1102 , '@PYTHON@' : python_exe
1103 }
1104
1105 if env.get('WITH_LOCAL_HELP'):
1106 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
1107 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
1108
1109 # bool options...
1110 for k,v in {
1111 'ABSOLUTE_PATHS' : 'ASC_ABSOLUTE_PATHS'
1112 ,'WITH_XTERM_COLORS' : 'ASC_XTERM_COLORS'
1113 ,'MALLOC_DEBUG' : 'MALLOC_DEBUG'
1114 }.iteritems():
1115 if env.get(k):
1116 # subst_dict['@'+v+'@']='1'
1117 subst_dict["/\\* #define "+v+' @'+v+"@ \\*/"]='# define '+v+' 1 '
1118
1119 if with_ida:
1120 subst_dict["/\\* #define ASC_WITH_IDA @ASC_WITH_IDA@ \\*/"]='#define ASC_WITH_IDA '
1121
1122 if with_lsode:
1123 subst_dict["/\\* #define ASC_WITH_LSODE @ASC_WITH_LSODE@ \\*/"]='#define ASC_WITH_LSODE '
1124
1125 if with_python:
1126 subst_dict['@ASCXX_USE_PYTHON@']="1"
1127 env['WITH_PYTHON']=1;
1128
1129 if env.has_key('HAVE_GCCVISIBILITY'):
1130 subst_dict['@HAVE_GCCVISIBILITY@'] = "1"
1131
1132 env.Append(SUBST_DICT=subst_dict)
1133
1134 #------------------------------------------------------
1135 # RECIPE: SWIG scanner
1136
1137 import SCons.Script
1138
1139 SWIGScanner = SCons.Scanner.ClassicCPP(
1140 "SWIGScan"
1141 , ".i"
1142 , "CPPPATH"
1143 , '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
1144 )
1145
1146 env.Append(SCANNERS=[SWIGScanner])
1147
1148 #------------------------------------------------------
1149 # RECIPE: 'SubstInFile', used in pygtk SConscript
1150
1151 import re
1152 from SCons.Script import * # the usual scons stuff you get in a SConscript
1153
1154 def TOOL_SUBST(env):
1155 """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
1156 from the source to the target.
1157 The values of SUBST_DICT first have any construction variables expanded
1158 (its keys are not expanded).
1159 If a value of SUBST_DICT is a python callable function, it is called and
1160 the result is expanded as the value.
1161 If there's more than one source and more than one target, each target gets
1162 substituted from the corresponding source.
1163 """
1164 env.Append(TOOLS = 'SUBST')
1165 def do_subst_in_file(targetfile, sourcefile, dict):
1166 """Replace all instances of the keys of dict with their values.
1167 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
1168 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
1169 """
1170 try:
1171 f = open(sourcefile, 'rb')
1172 contents = f.read()
1173 f.close()
1174 except:
1175 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
1176 for (k,v) in dict.items():
1177 contents = re.sub(k, v, contents)
1178 try:
1179 f = open(targetfile, 'wb')
1180 f.write(contents)
1181 f.close()
1182 except:
1183 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
1184 return 0 # success
1185
1186 def subst_in_file(target, source, env):
1187 if not env.has_key('SUBST_DICT'):
1188 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
1189 d = dict(env['SUBST_DICT']) # copy it
1190 for (k,v) in d.items():
1191 if callable(v):
1192 d[k] = env.subst(v())
1193 elif SCons.Util.is_String(v):
1194 d[k]=env.subst(v)
1195 else:
1196 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
1197 for (t,s) in zip(target, source):
1198 return do_subst_in_file(str(t), str(s), d)
1199
1200 def subst_in_file_string(target, source, env):
1201 """This is what gets printed on the console."""
1202 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
1203 for (t,s) in zip(target, source)])
1204
1205 def subst_emitter(target, source, env):
1206 """Add dependency from substituted SUBST_DICT to target.
1207 Returns original target, source tuple unchanged.
1208 """
1209 d = env['SUBST_DICT'].copy() # copy it
1210 for (k,v) in d.items():
1211 if callable(v):
1212 d[k] = env.subst(v())
1213 elif SCons.Util.is_String(v):
1214 d[k]=env.subst(v)
1215 Depends(target, SCons.Node.Python.Value(d))
1216 return target, source
1217
1218 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
1219 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
1220
1221 TOOL_SUBST(env)
1222
1223 #------------------------------------------------------
1224 # Recipe for 'CHMOD' ACTION
1225
1226 import SCons
1227 from SCons.Script.SConscript import SConsEnvironment
1228 SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
1229 lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
1230
1231 def InstallPerm(env, dest, files, perm):
1232 obj = env.Install(dest, files)
1233 for i in obj:
1234 env.AddPostAction(i, env.Chmod(str(i), perm))
1235
1236 SConsEnvironment.InstallPerm = InstallPerm
1237
1238 # define wrappers
1239 SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
1240 SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
1241 SConsEnvironment.InstallShared = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
1242
1243 #------------------------------------------------------
1244 # BUILD...
1245
1246 # so that #include <modulename/headername.h> works across all modules...
1247 env.Append(CPPPATH=['#base/generic'])
1248
1249 if gcc_version4:
1250 env.Append(CCFLAGS=['-fvisibility=hidden'])
1251
1252 if env['DEBUG']:
1253 env.Append(CCFLAGS=['-g'])
1254
1255 if env['GCOV']:
1256 env.Append(
1257 CPPFLAGS=['-g','-fprofile-arcs','-ftest-coverage']
1258 , LIBS=['gcov']
1259 , LINKFLAGS=['-fprofile-arcs','-ftest-coverage']
1260 )
1261
1262 if with_ida:
1263 env.Append(WITH_IDA=1)
1264
1265 #-------------
1266 # TCL/TK GUI
1267
1268 if with_tcltk:
1269 env.SConscript(['tcltk/generic/interface/SConscript'],'env')
1270 else:
1271 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
1272
1273 #-------------
1274 # PYTHON INTERFACE
1275
1276 if with_python:
1277 env.SConscript(['pygtk/SConscript'],'env')
1278 else:
1279 print "Skipping... Python GUI isn't being built:",without_python_reason
1280
1281 #------------
1282 # BASE/GENERIC SUBDIRECTORIES
1283
1284 libascend_env = env.Copy()
1285
1286 dirs = ['general','utilities','compiler','solver','packages']
1287
1288 srcs = []
1289 for d in dirs:
1290 heresrcs = libascend_env.SConscript('base/generic/'+d+'/SConscript','libascend_env')
1291 srcs += heresrcs
1292
1293 #-------------
1294 # IMPORTED CODE: LSODE, BLAS, etc
1295
1296 if with_lsode:
1297 srcs += env.SConscript(['lsod/SConscript'],'env')
1298 srcs += env.SConscript(['linpack/SConscript'],'env')
1299 else:
1300 print "Skipping... LSODE won't be built:", without_lsode_reason
1301
1302 if with_local_blas:
1303 srcs += env.SConscript(['blas/SConscript'],'env')
1304 else:
1305 print "Skipping... BLAS won't be built:", without_local_blas_reason
1306
1307 if not with_ida:
1308 print "Skipping... IDA won't be built:", without_ida_reason
1309
1310 #-------------
1311 # LIBASCEND -- all base/generic functionality
1312
1313 libascend = libascend_env.SharedLibrary('ascend',srcs)
1314
1315 env.Alias('libascend',libascend)
1316
1317 #-------------
1318 # UNIT TESTS
1319
1320 if with_cunit:
1321 testdirs = ['general','solver','utilities']
1322 testsrcs = []
1323 for testdir in testdirs:
1324 path = 'base/generic/'+testdir+'/test/'
1325 env.SConscript([path+'SConscript'],'env')
1326 testsrcs += [i.path for i in env['TESTSRCS_'+testdir.upper()]]
1327
1328 #print "TESTSRCS =",testsrcs
1329
1330 env.SConscript(['test/SConscript'],'env')
1331 env.SConscript(['base/generic/test/SConscript'],'env')
1332
1333 env.Alias('test',[env.Dir('test'),env.Dir('base/generic/test')])
1334
1335 else:
1336 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1337
1338 #------------------------------------------------------
1339 # CREATE ASCEND-CONFIG scriptlet
1340
1341 ascendconfig = env.SubstInFile('ascend-config.in')
1342
1343 #------------------------------------------------------
1344 # INSTALLATION
1345
1346 if env.get('CAN_INSTALL'):
1347 # the models directory only needs to be processed for installation, no other processing required.
1348 env.SConscript(['models/SConscript'],'env')
1349
1350 dirs = ['INSTALL_BIN','INSTALL_ASCDATA','INSTALL_LIB']
1351 install_dirs = [env['INSTALL_ROOT']+env[d] for d in dirs]
1352
1353 # TODO: add install options
1354 env.Alias('install',install_dirs)
1355
1356 env.InstallShared(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1357
1358 env.InstallProgram(env['INSTALL_ROOT']+env['INSTALL_BIN'],ascendconfig)
1359
1360 #------------------------------------------------------
1361 # WINDOWS INSTALLER
1362 # For the windows installer, please see pygtk/SConscript
1363
1364 if with_installer:
1365 pass
1366 else:
1367 print "Skipping... Windows installer isn't being built:",without_installer_reason
1368
1369 #------------------------------------------------------
1370 # PROJECT FILE for MSVC
1371
1372 env.SConscript(['base/msvc/SConscript'],['env','libascend']);
1373
1374 #------------------------------------------------------
1375 # CREATE the SPEC file for generation of RPM packages
1376
1377 if platform.system()=="Linux":
1378 env.SubstInFile('ascend.spec.in')
1379
1380 #------------------------------------------------------
1381 # DISTRIBUTION TAR FILE
1382
1383 env['DISTTAR_FORMAT']='bz2'
1384 env.Append(
1385 DISTTAR_EXCLUDEEXTS=['.o','.os','.so','.a','.dll','.cc','.cache','.pyc','.cvsignore','.dblite','.log','.pl']
1386 , DISTTAR_EXCLUDEDIRS=['CVS','.svn','.sconf_temp', 'dist']
1387 )
1388
1389 tar = env.DistTar("dist/"+env['DISTTAR_NAME']
1390 , [env.Dir('#')]
1391 )
1392
1393 env.Depends(tar,'ascend.spec')
1394
1395 #------------------------------------------------------
1396 # RPM BUILD
1397
1398 #if platform.system()=="Linux":
1399 # pass
1400
1401 #------------------------------------------------------
1402 # DEFAULT TARGETS
1403
1404 default_targets =['libascend']
1405 if with_tcltk:
1406 default_targets.append('tcltk')
1407 if with_python:
1408 default_targets.append('pygtk')
1409 if with_installer:
1410 default_targets.append('installer')
1411
1412 env.Default(default_targets)
1413
1414 print "Building targets:"," ".join([str(i) for i in BUILD_TARGETS])
1415
1416 # vim: set syntax=python:
1417

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