/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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