/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 968 - (show annotations) (download)
Mon Dec 18 05:49:00 2006 UTC (12 years, 11 months ago) by johnpye
File size: 48893 byte(s)
Added SCons tests to check SIGINT and to replace ascresetneeded (need replacement for this in Autoconf as well).
Removed debugging from createinst.c
Typo (text) in evaluate.c
Commented out redundant code in importhandler.c
Added signal handling in ExecuteCASGN.
Added missing ospath_free in ModuleSearchPath.
Exported InitSymbolTable, DestroySymbolTable in symtab (dubious)
Moved FPRESET macro out of ascConfig.h and into ascSignal.h
Added Asc_SignalHandler{Push,Pop}Default.
Added ASC_RESETNEEDED and HAVE_C99FPE macros in config.h.in.
Found the bug causing the SIGFPE in idakryx.a4c (raises a question about int/float division in modelling, I think)
Added system_destroy call in Simulation::~Simulation (dubious).
1 import sys, os, commands, platform, distutils.sysconfig, os.path, re
2
3 version = "0.9.5.103"
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 default_conopt_prefix = "c:\\Program Files\\CONOPT"
33 default_conopt_libpath="$CONOPT_PREFIX"
34 default_conopt_cpppath="$CONOPT_PREFIX"
35 default_conopt_lib="conopt3"
36 default_conopt_envvar="CONOPT_PATH"
37
38 default_prefix="c:\\MinGW"
39 default_libpath="$DEFAULT_PREFIX\\lib"
40 default_cpppath="$DEFAULT_PREFIX\\include"
41
42 if not os.path.exists(default_conopt_prefix):
43 default_conopt_prefix = None
44
45 need_libm = False
46 python_exe = "c:\\Python24\\python.exe"
47 default_with_scrollkeeper=False
48 else:
49 default_tcl_lib = "tcl8.4"
50 default_tk_lib = "tk8.4"
51 default_tktable_lib = "Tktable2.8"
52 default_install_assets = "$INSTALL_ASCDATA/glade/"
53 icon_extension = '.svg'
54 default_tcl = '/usr'
55 default_tcl_libpath = "$TCL/lib"
56 default_rel_distdir = '../share/ascend'
57 default_absolute_paths = True
58 default_ida_prefix="/usr/local"
59 default_conopt_prefix="/usr"
60 default_conopt_libpath="$CONOPT_PREFIX/lib"
61 default_conopt_cpppath="$CONOPT_PREFIX/include"
62 default_conopt_lib="consub3"
63 default_conopt_envvar="CONOPT_PATH"
64
65 default_prefix="/usr"
66 default_libpath="$DEFAULT_PREFIX/lib"
67 default_cpppath="$DEFAULT_PREFIX/include"
68
69 need_libm = True
70 if not os.path.isdir(default_tcl):
71 default_tcl = '/usr'
72 python_exe = distutils.sysconfig.EXEC_PREFIX+"/bin/python"
73 default_with_scrollkeeper=False
74
75 opts.Add(
76 'CC'
77 ,'C Compiler command'
78 ,None
79 )
80
81 opts.Add(
82 'CXX'
83 ,'C++ Compiler command'
84 ,None
85 )
86
87 opts.Add(BoolOption(
88 'GCOV'
89 , 'Whether to enable coverage testing in object code'
90 , False
91 ))
92
93 # Package linking option
94 opts.Add(EnumOption(
95 'PACKAGE_LINKING'
96 , 'Style of linking for external libraries'
97 , 'DYNAMIC_PACKAGES'
98 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
99 ))
100
101 opts.Add(BoolOption(
102 'WITH_GCCVISIBILITY'
103 ,"Whether to use GCC Visibility features (only applicable if available)"
104 ,True
105 ))
106
107 # You can turn off building of Tcl/Tk interface
108 opts.Add(BoolOption(
109 'WITH_TCLTK'
110 ,"Set to False if you don't want to build the original Tcl/Tk GUI."
111 , True
112 ))
113
114 # You can turn off the building of the Python interface
115 opts.Add(BoolOption(
116 'WITH_PYTHON'
117 ,"Set to False if you don't want to build Python wrappers."
118 , True
119 ))
120
121 # Which solvers will we allow?
122 opts.Add(ListOption(
123 'WITH_SOLVERS'
124 ,"List of the solvers you want to build. The default is the minimum that"
125 +" works."
126 ,["QRSLV","CMSLV","LSOD","IDA","CONOPT","LRSLV"]
127 ,['QRSLV','MPS','SLV','OPTSQP'
128 ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
129 ,'LSOD','OPTSQP',"IDA"
130 ]
131 ))
132
133 # Where will the local copy of the help files be kept?
134 opts.Add(PackageOption(
135 'WITH_LOCAL_HELP'
136 , "Directory containing the local copy of the help files (optional)"
137 , "no"
138 ))
139
140 # Will bintoken support be enabled?
141 opts.Add(BoolOption(
142 'WITH_BINTOKEN'
143 ,"Enable bintoken support? This means compiling models as C-code before"
144 +" running them, to increase solving speed for large models."
145 ,False
146 ))
147
148 # What should the default ASCENDLIBRARY path be?
149 # Note: users can change it by editing their ~/.ascend.ini
150 opts.Add(
151 'DEFAULT_ASCENDLIBRARY'
152 ,"Set the default value of the ASCENDLIBRARY -- the location where"
153 +" ASCEND will look for models when running ASCEND"
154 ,"$INSTALL_ASCDATA/models"
155 )
156
157 # Where is SWIG?
158 opts.Add(
159 'SWIG'
160 ,"SWIG location, probably only required for MinGW and MSVC users."
161 +" Enter the location as a Windows-style path, for example"
162 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
163 )
164
165 # Build the test suite?
166 opts.Add(BoolOption(
167 'WITH_CUNIT'
168 ,"You can disable CUnit tests with this option. This will basically stop"
169 +" SCons from parsing the SConscript files relating to the 'test'"
170 +" target, which just might make things marginally faster. Probably"
171 +" you can just ignore this option though. SCons will sniff for Cunit"
172 +" but build the tests only if you specify the 'test' target."
173 ,True
174 ))
175
176 #----- default paths -----
177 opts.Add(PackageOption(
178 'DEFAULT_PREFIX'
179 ,"Where are most of the shared libraries located on your system?"
180 ,default_prefix
181 ))
182
183 #------ install location for python extensions ------
184
185 # (removed for the moment)
186
187 #------ cunit --------
188 # Where was CUNIT installed?
189 opts.Add(PackageOption(
190 'CUNIT_PREFIX'
191 ,"Where are your CUnit files?"
192 ,"$DEFAULT_PREFIX"
193 ))
194
195 # Where are the CUnit includes?
196 opts.Add(PackageOption(
197 'CUNIT_CPPPATH'
198 ,"Where are your CUnit include files?"
199 ,"$CUNIT_PREFIX/include"
200 ))
201
202 # Where are the CUnit libraries?
203 opts.Add(PackageOption(
204 'CUNIT_LIBPATH'
205 ,"Where are your CUnit libraries?"
206 ,"$CUNIT_PREFIX/lib"
207 ))
208
209 #-------- ida -------
210
211 opts.Add(PackageOption(
212 "IDA_PREFIX"
213 ,"Prefix for your IDA install (IDA ./configure --prefix)"
214 ,default_ida_prefix
215 ))
216
217 opts.Add(
218 "IDA_LIB"
219 ,"Libraries linked to for IDA"
220 ,['sundials_nvecserial','sundials_ida','m']
221 )
222
223 opts.Add(
224 'IDA_CPPPATH'
225 ,"Where is your ida.h?"
226 ,"$IDA_PREFIX/include"
227 )
228
229 opts.Add(
230 'IDA_LIBPATH'
231 ,"Where are your SUNDIALS libraries installed?"
232 ,"$IDA_PREFIX/lib"
233 )
234
235 # ----- conopt-----
236
237 opts.Add(PackageOption(
238 "CONOPT_PREFIX"
239 ,"Prefix for your CONOPT install (CONOPT ./configure --prefix)"
240 ,default_conopt_prefix
241 ))
242
243 opts.Add(
244 "CONOPT_LIB"
245 ,"Library linked to for CONOPT"
246 ,default_conopt_lib
247 )
248
249 opts.Add(
250 'CONOPT_CPPPATH'
251 ,"Where is your conopt.h?"
252 ,default_conopt_cpppath
253 )
254
255 opts.Add(
256 'CONOPT_LIBPATH'
257 ,"Where is your CONOPT libraries installed?"
258 ,default_conopt_libpath
259 )
260
261 opts.Add(
262 'CONOPT_ENVVAR'
263 ,"What environment variable should be used at runtime to override the default search location for CONOPT DLL/SO?"
264 ,default_conopt_envvar
265 )
266
267 #-------- f2c ------
268
269 opts.Add(
270 "F2C_LIB"
271 ,"F2C library (eg. g2c, gfortran, f2c)"
272 ,"g2c"
273 )
274
275 opts.Add(PackageOption(
276 "F2C_LIBPATH"
277 ,"Directory containing F2C library (i.e. g2c, gfortran, f2c, etc.), if not already accessible"
278 ,"off"
279 ))
280
281 #------- tcl/tk --------
282
283 opts.Add(
284 'TCL'
285 ,'Base of Tcl distribution'
286 ,default_tcl
287 )
288
289 # Where are the Tcl includes?
290 opts.Add(
291 'TCL_CPPPATH'
292 ,"Where are your Tcl include files?"
293 ,"$TCL/include"
294 )
295
296 # Where are the Tcl libs?
297 opts.Add(
298 'TCL_LIBPATH'
299 ,"Where are your Tcl libraries?"
300 ,default_tcl_libpath
301 )
302
303 # What is the name of the Tcl lib?
304 opts.Add(
305 'TCL_LIB'
306 ,"Name of Tcl lib (eg 'tcl' or 'tcl83'), for full path to static library (if STATIC_TCLTK is set)"
307 ,default_tcl_lib
308 )
309
310 # Where are the Tk includes?
311 opts.Add(
312 'TK_CPPPATH'
313 ,"Where are your Tk include files?"
314 ,'$TCL_CPPPATH'
315 )
316
317 # Where are the Tk libs?
318 opts.Add(
319 'TK_LIBPATH'
320 ,"Where are your Tk libraries?"
321 ,'$TCL_LIBPATH'
322 )
323
324 # What is the name of the Tk lib?
325 opts.Add(
326 'TK_LIB'
327 ,"Name of Tk lib (eg 'tk' or 'tk83'), or full path to static library"
328 ,default_tk_lib
329 )
330
331 # Static linking to TkTable
332
333 opts.Add(BoolOption(
334 'STATIC_TCLTK'
335 ,'Set true for static linking for Tcl/Tk and TkTable. EXPERIMENTAL'
336 ,False
337 ))
338
339 opts.Add(
340 'TKTABLE_LIBPATH'
341 ,'Location of TkTable static library'
342 ,'$TCL_LIBPATH/Tktable2.8'
343 )
344
345 opts.Add(
346 'TKTABLE_LIB'
347 ,'Stem name of TkTable (eg tktable2.8, no ".so" or "lib") shared library, or full path of static tktable (/usr/lib/...)'
348 ,default_tktable_lib
349 )
350
351 opts.Add(
352 'TKTABLE_CPPPATH'
353 ,'Location of TkTable header file'
354 ,'$TCL_CPPPATH'
355 )
356
357 opts.Add(
358 'X11'
359 ,'Base X11 directory. Only used when STATIC_TCLTK is turned on. EXPERIMENTAL'
360 ,'/usr/X11R6'
361 )
362
363 opts.Add(
364 'X11_LIBPATH'
365 ,'Location of X11 lib. EXPERIMENTAL'
366 ,'$X11/lib'
367 )
368
369 opts.Add(
370 'X11_CPPPATH'
371 ,'Location of X11 includes. EXPERIMENTAL'
372 ,'$X11/include'
373 )
374
375 opts.Add(
376 'X11_LIB'
377 ,'Name of X11 lib. EXPERIMENTAL'
378 ,'X11'
379 )
380
381 #----- installed file locations (for 'scons install') -----
382
383 opts.Add(
384 'INSTALL_PREFIX'
385 ,'Root location for installed files'
386 ,'/usr/local'
387 )
388
389 opts.Add(
390 'INSTALL_BIN'
391 ,'Location to put binaries during installation'
392 ,"$INSTALL_PREFIX/bin"
393 )
394
395 opts.Add(
396 'INSTALL_LIB'
397 ,'Location to put libraries during installation'
398 ,"$INSTALL_PREFIX/lib"
399 )
400
401 opts.Add(
402 'INSTALL_SHARE'
403 ,'Common shared-file location on this system'
404 ,"$INSTALL_PREFIX/share"
405 )
406
407 opts.Add(
408 'INSTALL_DOC'
409 ,'Location to install documentation files'
410 ,"$INSTALL_SHARE/doc"
411 )
412
413 opts.Add(
414 'INSTALL_ASCDATA'
415 ,"Location of ASCEND shared data (TK, python, models etc)"
416 ,"$INSTALL_SHARE/ascend"
417 )
418
419 opts.Add(
420 'INSTALL_INCLUDE'
421 ,'Location to put header files during installation'
422 ,"$INSTALL_PREFIX/include"
423 )
424
425
426 opts.Add(
427 'INSTALL_ROOT'
428 ,'For use by RPM only: location of %{buildroot} during rpmbuild'
429 ,""
430 )
431
432 #----------------------
433
434 opts.Add(
435 'PYGTK_ASSETS'
436 ,'Default location for Glade assets (placed in pygtk/config.py)'
437 ,default_install_assets
438 )
439
440 opts.Add(BoolOption(
441 'DEBUG'
442 ,"Compile source with debugger symbols, eg for use with 'gdb'"
443 ,False
444 ))
445
446 opts.Add(BoolOption(
447 'MALLOC_DEBUG'
448 ,"Compile with debugging version of MALLOC. Required for full CUnit testing"
449 ,False
450 ))
451
452 #------ dmalloc --------
453 opts.Add(PackageOption(
454 'DMALLOC_PREFIX'
455 ,"Where are your dmalloc files?"
456 ,default_prefix
457 ))
458
459 opts.Add(PackageOption(
460 'DMALLOC_CPPPATH'
461 ,"Where are your dmalloc include files?"
462 ,default_cpppath
463 ))
464
465 opts.Add(PackageOption(
466 'DMALLOC_LIBPATH'
467 ,"Where are your dmalloc libraries?"
468 ,default_libpath
469 ))
470
471 opts.Add(BoolOption(
472 'WITH_DMALLOC'
473 ,"Link to the DMALLOC library (if available) for debugging of memory usage."
474 ,False
475 ))
476
477 #-----------------------
478
479 opts.Add(
480 'DISTTAR_NAME'
481 ,"Stem name of the tarball created by 'scons dist'. So for 'ascend-aaa.tar.bz2', set this to 'ascend-aaa'."
482 ,"ascend-"+version
483 )
484
485 opts.Add(
486 'RELEASE'
487 ,"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."
488 ,"0"
489 )
490
491 opts.Add(BoolOption(
492 'ABSOLUTE_PATHS'
493 ,"Whether to use absolute or relative paths in the installed Tcl/Tk interface. If you want to build an RPM, set this to false."
494 ,default_absolute_paths
495 ))
496
497 opts.Add(
498 'WIN_INSTALLER_NAME'
499 ,"Name of the installer .exe to create under Windows (minus the '.exe')"
500 ,"ascend-"+version
501 )
502
503 opts.Add(BoolOption(
504 'WITH_XTERM_COLORS'
505 ,"Set to 0 if you don't want xterm colour codes in the console output"
506 ,True
507 ))
508
509 opts.Add(BoolOption(
510 'WITH_EXTFNS'
511 ,"Set to 0 if you don't want to attempt to build external modules bundled"
512 + " with ASCEND."
513 ,True
514 ))
515
516 opts.Add(BoolOption(
517 'WITH_SCROLLKEEPER'
518 ,"Set to to 1 if you want to install an OMF file that can be read by scrollkeeper (eg Yelp on GNOME)"
519 ,default_with_scrollkeeper
520 ))
521
522 if platform.system()!="Windows":
523 opts.Add(BoolOption(
524 'WITH_GCCVISIBILITY'
525 , 'Whether to use GCC Visibility extensions when building with GCC 4.0'
526 , True
527 ))
528
529
530
531 # TODO: OTHER OPTIONS?
532 # TODO: flags for optimisation
533 # TODO: turning on/off bintoken functionality
534 # TODO: Where will the 'Makefile.bt' file be installed?
535
536 # Import the outside environment
537
538 def c_escape(str):
539 return re.sub("\\\\","/",str)
540
541 envadditional={}
542
543 if platform.system()=="Windows":
544 if os.environ.get('OSTYPE')=='msys':
545 envenv = os.environ;
546 tools = ['mingw','lex','yacc','fortran','swig','disttar','nsis']
547 #TODO removed 'doxygen' for SCons 0.96.93
548 envadditional['IS_MINGW']=True
549 else:
550 envenv = {
551 'PATH':os.environ['PATH']
552 ,'INCLUDE':os.environ['INCLUDE']
553 ,'LIB':os.environ['LIB']
554 ,'MSVS_IGNORE_IDE_PATHS':1
555 }
556 tools=['default','lex','yacc','fortran','swig','disttar','nsis']
557 #TODO removed 'doxygen' for SCons 0.96.93
558 envadditional['CPPDEFINES']=['_CRT_SECURE_NO_DEPRECATE']
559 else:
560 if os.environ.get('TARGET')=='mingw':
561 envenv = os.environ
562 tools=['crossmingw','lex','yacc','disttar','nsis','doxygen']
563 envadditional['CPPPATH']=['/usr/local/lib/gcc/i386-mingw32/3.4.5/include','/usr/include']
564 else:
565 envenv = os.environ
566 tools=['default','lex','yacc','fortran','swig','disttar','nsis']
567 #TODO removed 'doxygen' for SCons 0.96.93
568
569
570 env = Environment(
571 ENV=envenv
572 , toolpath=['scons']
573 , tools=tools
574 , **envadditional
575 )
576
577 opts.Update(env)
578 opts.Save('options.cache',env)
579
580 Help(opts.GenerateHelpText(env))
581
582 with_tcltk = env.get('WITH_TCLTK')
583 without_tcltk_reason = "disabled by options/config.py"
584
585 with_python = env.get('WITH_PYTHON')
586 without_python_reason = "disabled by options/config.py"
587
588 with_cunit = env.get('WITH_CUNIT')
589 without_cunit_reason = "not requested"
590
591 with_extfns = env.get('WITH_EXTFNS')
592 without_extfn_reason = "disabled by options/config.py"
593
594 with_scrollkeeper = env.get('WITH_SCROLLKEEPER')
595 without_scrollkeeper_reason = "disabled by options/config.py"
596
597 with_dmalloc = env.get('WITH_DMALLOC')
598 without_dmalloc_reason = "disabled by options/config.py"
599
600 if platform.system()=="Windows":
601 with_installer=1
602 else:
603 with_installer=0
604 without_installer_reason = "only possible under Windows"
605
606 if 'LSOD' in env['WITH_SOLVERS']:
607 with_lsode=True
608 else:
609 with_lsode=False
610 without_lsode_reason = "not requested (WITH_SOLVERS)"
611
612 if 'IDA' in env['WITH_SOLVERS']:
613 with_ida=True
614 else:
615 with_ida=False
616 without_ida_reason = "not requested (WITH_SOLVERS)"
617
618
619 if 'CONOPT' in env['WITH_SOLVERS']:
620 with_conopt=True
621 else:
622 with_conopt=False
623 without_conopt_reason = "not requested (WITH_SOLVERS)"
624
625
626 #print "SOLVERS:",env['WITH_SOLVERS']
627 #print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
628 #print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
629
630 can_install = True
631 if platform.system()=='Windows':
632 can_install = False
633
634 env['CAN_INSTALL']=can_install
635
636 env['INSTALL_MODELS']=env['INSTALL_ASCDATA']+"/models/"
637
638 print "TCL_CPPPATH =",env['TCL_CPPPATH']
639 print "TCL_LIBPATH =",env['TCL_LIBPATH']
640 print "TCL_LIB =",env['TCL_LIB']
641 print "CC =",env['CC']
642 print "CXX =",env['CXX']
643 print "FORTRAN=",env.get('FORTRAN')
644
645 print "ABSOLUTE PATHS =",env['ABSOLUTE_PATHS']
646 #------------------------------------------------------
647 # SPECIAL CONFIGURATION TESTS
648
649 need_fortran = False
650
651 #----------------
652 # SWIG
653
654 import os,re
655
656 def get_swig_version(env):
657 cmd = env['SWIG']+' -version'
658 (cin,coutcerr) = os.popen4(cmd)
659 output = coutcerr.read()
660
661 restr = "SWIG\\s+Version\\s+(?P<maj>[0-9]+)\\.(?P<min>[0-9]+)\\.(?P<pat>[0-9]+)\\s*$"
662 expr = re.compile(restr,re.M);
663 m = expr.search(output);
664 if not m:
665 return None
666 maj = int(m.group('maj'))
667 min = int(m.group('min'))
668 pat = int(m.group('pat'))
669
670 return (maj,min,pat)
671
672
673 def CheckSwigVersion(context):
674
675 try:
676 context.Message("Checking version of SWIG... ")
677 maj,min,pat = get_swig_version(context.env)
678 except:
679 context.Result("Failed to detect version, or failed to run SWIG")
680 return 0;
681
682 context.env['SWIGVERSION']=tuple([maj,min,pat])
683
684 if maj == 1 and (
685 min > 3
686 or (min == 3 and pat >= 24)
687 ):
688 context.Result("ok, %d.%d.%d" % (maj,min,pat))
689 return 1;
690 else:
691 context.Result("too old, %d.%d.%d" % (maj,min,pat))
692 return 0;
693
694 #----------------
695 # Scrollkeeper (Linux documentation system)
696
697 def get_scrollkeeper_omfdir(env):
698 cmd = 'scrollkeeper-config --omfdir'
699 (cin,coutcerr) = os.popen4(cmd)
700 output = coutcerr.read()
701 return output.strip()
702
703 def CheckScrollkeeperConfig(context):
704 try:
705 context.Message("Checking for scrollkeeper...")
706 dir=get_scrollkeeper_omfdir(context.env)
707 except:
708 context.Result("Failed to run 'scrollkeeper-config'")
709 return 0
710 context.env['OMFDIR']=dir
711 context.Result("OK, %s" % dir)
712 return 1
713
714 #----------------
715 # General purpose library-and-header test
716
717 class KeepContext:
718 def __init__(self,context,varprefix,static=False):
719 self.keep = {}
720 for k in ['LIBS','LIBPATH','CPPPATH','LINKFLAGS']:
721 #print "Keeping env %s = %s" % (k,context.env.get(k))
722 self.keep[k]=context.env.get(k)
723
724 if context.env.has_key(varprefix+'_CPPPATH'):
725 context.env.AppendUnique(CPPPATH=[env[varprefix+'_CPPPATH']])
726 #print "Adding '"+str(env[varprefix+'_CPPPATH'])+"' to cpp path"
727
728 if static:
729 staticlib=env[varprefix+'_LIB']
730 #print "STATIC LIB = ",staticlib
731 context.env.Append(
732 LINKFLAGS=[staticlib]
733 )
734 else:
735 if context.env.has_key(varprefix+'_LIBPATH'):
736 context.env.Append(LIBPATH=[env[varprefix+'_LIBPATH']])
737 #print "Adding '"+str(env[varprefix+'_LIBPATH'])+"' to lib path"
738
739 if context.env.has_key(varprefix+'_LIB'):
740 context.env.Append(LIBS=[env[varprefix+'_LIB']])
741 #print "Adding '"+str(env[varprefix+'_LIB'])+"' to libs"
742
743 def restore(self,context):
744 #print "RESTORING CONTEXT"
745 #print self.keep
746 #print "..."
747 for k in self.keep:
748 if self.keep[k]==None:
749 if context.env.has_key(k):
750 #print "Clearing "+str(k)
751 del context.env[k];
752 else:
753 #print "Restoring %s to '%s'" %(k,self.keep.get(k))
754 context.env[k]=self.keep[k];
755
756 def CheckExtLib(context,libname,text,ext='.c',varprefix=None,static=False):
757 """This method will check for variables LIBNAME_LIBPATH
758 and LIBNAME_CPPPATH and try to compile and link the
759 file with the provided text, linking with the
760 library libname."""
761
762 if static:
763 context.Message( 'Checking for static '+libname+'... ' )
764 else:
765 context.Message( 'Checking for '+libname+'... ' )
766
767 if varprefix==None:
768 varprefix = libname.upper()
769
770 #print "LIBS is currently:",context.env.get('LIBS')
771 keep = KeepContext(context,varprefix,static)
772
773 if not context.env.has_key(varprefix+'_LIB'):
774 # if varprefix_LIB were in env, KeepContext would
775 # have appended it already
776 context.env.Append(LIBS=[libname])
777
778 is_ok = context.TryLink(text,ext)
779
780 #print "Link success? ",(is_ok != 0)
781
782 keep.restore(context)
783
784 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
785 # print "Restored LIBS="+str(context.env['LIBS'])
786 # print "Restored LIBPATH="+str(context.env['LIBPATH'])
787
788 context.Result(is_ok)
789 return is_ok
790
791 #----------------
792 # GCC
793
794 gcc_test_text = """
795 #ifndef __GNUC__
796 # error "Not using GCC"
797 #endif
798
799 int main(void){
800 return __GNUC__;
801 }
802 """
803
804 def CheckGcc(context):
805 context.Message("Checking for GCC... ")
806 is_ok = context.TryCompile(gcc_test_text,".c")
807 context.Result(is_ok)
808 return is_ok
809
810 #----------------
811 # GCC VISIBILITY feature
812
813 gccvisibility_test_text = """
814 #if __GNUC__ < 4
815 # error "Require GCC version 4 or newer"
816 #endif
817
818 __attribute__ ((visibility("default"))) int x;
819
820 int main(void){
821 extern int x;
822 x = 4;
823 }
824 """
825
826 def CheckGccVisibility(context):
827 context.Message("Checking for GCC 'visibility' capability... ")
828 if not context.env.has_key('WITH_GCCVISIBILITY') or not env['WITH_GCCVISIBILITY']:
829 context.Result("disabled")
830 return 0
831 is_ok = context.TryCompile(gccvisibility_test_text,".c")
832 context.Result(is_ok)
833 return is_ok
834
835 #----------------
836 # YACC
837
838 yacc_test_text = """
839 %{
840 #include <stdio.h>
841
842 /* MSVC++ needs this before it can swallow Bison output */
843 #ifdef _MSC_VER
844 # define __STDC__
845 #endif
846 %}
847 %token MSG
848 %start ROOT
849 %%
850 ROOT:
851 MSG { printf("HELLO"); }
852 ;
853 %%
854 """
855
856 def CheckYacc(context):
857 context.Message("Checking for Yacc ('%s')... " % context.env.get('YACC'))
858 is_ok = context.TryCompile(yacc_test_text,".y")
859 context.Result(is_ok)
860 return is_ok
861
862 #----------------
863 # CUnit test
864
865 cunit_test_text = """
866 #include <CUnit/CUnit.h>
867 int maxi(int i1, int i2){
868 return (i1 > i2) ? i1 : i2;
869 }
870
871 void test_maxi(void){
872 CU_ASSERT(maxi(0,2) == 2);
873 CU_ASSERT(maxi(0,-2) == 0);
874 CU_ASSERT(maxi(2,2) == 2);
875
876 }
877 int main(void){
878 /* CU_initialize_registry() */
879 return 0;
880 }
881 """
882
883 def CheckCUnit(context):
884 return CheckExtLib(context,'cunit',cunit_test_text)
885
886 #----------------
887 # dmalloc test
888
889 dmalloc_test_text = """
890 #include <stdlib.h>
891 #include <dmalloc.h>
892
893 int main(void){
894 char *c;
895 c = malloc(100*sizeof(char));
896 free(c);
897 return 0;
898 }
899 """
900
901 def CheckDMalloc(context):
902 return CheckExtLib(context,'dmalloc',dmalloc_test_text)
903
904 #----------------
905 # MATH test
906
907 math_test_text = """
908 #ifndef _ALL_SOURCE
909 # define _ALL_SOURCE
910 #endif
911 #ifndef _XOPEN_SOURCE
912 # define _XOPEN_SOURCE
913 #endif
914 #ifndef _XOPEN_SOURCE_EXTENDED
915 # define _XOPEN_SOURCE_EXTENDED 1
916 #endif
917 #include <math.h>
918 int main(void){
919 double x = 1.0; double y = 1.0; int i = 1;
920 acosh(x); asinh(x); atanh(x); cbrt(x); expm1(x); erf(x); erfc(x); isnan(x);
921 j0(x); j1(x); jn(i,x); ilogb(x); logb(x); log1p(x); rint(x);
922 y0(x); y1(x); yn(i,x);
923 #ifdef _THREAD_SAFE
924 gamma_r(x,&i);
925 lgamma_r(x,&i);
926 #else
927 gamma(x);
928 lgamma(x);
929 #endif
930 hypot(x,y); nextafter(x,y); remainder(x,y); scalb(x,y);
931 return 0;
932 }
933 """
934
935 def CheckMath(context):
936 context.Message('Checking for IEEE math library... ')
937 libsave=context.env.get('LIBS');
938 context.env.AppendUnique(LIBS=['m'])
939 is_ok=context.TryLink(math_test_text,".c")
940 context.Result(is_ok)
941 if not is_ok:
942 context.env['LIBS']=libsave
943 return is_ok
944
945 #----------------
946 # libpython test
947
948 libpython_test_text = """
949 #include <Python.h>
950 int main(void){
951 PyObject *p;
952 p = Py_None;
953 return 0;
954 }
955 """
956
957 def CheckPythonLib(context):
958 context.Message('Checking for libpython... ')
959
960 if platform.system()=="Windows":
961 python_lib='python%d%d'
962 else:
963 python_lib='python%d.%d'
964 python_libs = [python_lib % (sys.version_info[0],sys.version_info[1])]
965
966 python_cpppath = [distutils.sysconfig.get_python_inc()]
967 cfig = distutils.sysconfig.get_config_vars()
968
969 lastLIBS = context.env.get('LIBS')
970 lastLIBPATH = context.env.get('LIBPATH')
971 lastCPPPATH = context.env.get('CPPPATH')
972 lastLINKFLAGS = context.env.get('LINKFLAGS')
973
974 python_libpath = []
975 python_linkflags = []
976 if platform.system()=="Windows":
977 pass
978 else:
979 # checked on Linux and SunOS
980 if cfig['LDLIBRARY']==cfig['LIBRARY']:
981 sys.stdout.write("(static)")
982 python_libpath += [cfig['LIBPL']]
983 python_linkflags += cfig['LIBS'].split(' ')
984
985 context.env.AppendUnique(LIBS=python_libs)
986 context.env.AppendUnique(LIBPATH=python_libpath)
987 context.env.AppendUnique(CPPPATH=python_cpppath)
988 context.env.AppendUnique(LINKFLAGS=python_linkflags)
989 result = context.TryLink(libpython_test_text,".c");
990
991 context.Result(result)
992
993 if(result):
994 context.env['PYTHON_LIBPATH']=python_libpath
995 context.env['PYTHON_LIB']=python_libs
996 context.env['PYTHON_CPPPATH']=python_cpppath
997 context.env['PYTHON_LINKFLAGS']=python_linkflags
998
999 context.env['LIBS'] = lastLIBS
1000 context.env['LIBPATH'] = lastLIBPATH
1001 context.env['CPPPATH'] = lastCPPPATH
1002 context.env['LINKFLAGS'] = lastLINKFLAGS
1003
1004 return result
1005
1006 #----------------
1007 # IDA test
1008
1009 sundials_version_major_required = 2
1010 sundials_version_minor_min = 2
1011 sundials_version_minor_max = 3
1012
1013 sundials_version_text = """
1014 #include <sundials/sundials_config.h>
1015 #include <stdio.h>
1016 int main(){
1017 printf("%s",SUNDIALS_PACKAGE_VERSION);
1018 return 0;
1019 }
1020 """
1021
1022 ida_test_text = """
1023 # include <ida/ida.h>
1024 # include <nvector/nvector_serial.h>
1025 # include <ida/ida_spgmr.h>
1026 int main(){
1027 void *ida_mem;
1028 ida_mem = IDACreate();
1029 return 0;
1030 }
1031 """
1032
1033 def CheckIDA(context):
1034 context.Message( 'Checking for IDA (SUNDIALS)... ' )
1035
1036 keep = KeepContext(context,"IDA")
1037
1038 is_ok = context.TryLink(ida_test_text,".c")
1039 context.Result(is_ok)
1040
1041 keep.restore(context)
1042
1043 return is_ok
1044
1045 # slightly changed calling convention (IDACalcID) in newer versions of SUNDIALS,
1046 # so detect the version and act accordingly.
1047 def CheckIDAVersion(context):
1048 keep = KeepContext(context,'IDA')
1049 context.Message("Checking SUNDIALS version... ")
1050 (is_ok,output) = context.TryRun(sundials_version_text,'.c')
1051 keep.restore(context)
1052 if not is_ok:
1053 context.Result("failed to run check")
1054 return 0
1055
1056 major,minor,patch = tuple([int(i) for i in output.split(".")])
1057 context.env['SUNDIALS_VERSION_MAJOR'] = major
1058 context.env['SUNDIALS_VERSION_MINOR'] = minor
1059 if major != sundials_version_major_required \
1060 or minor < sundials_version_minor_min \
1061 or minor > sundials_version_minor_max:
1062 context.Result(output+" (bad version)")
1063 # bad version
1064 return 0
1065
1066 # good version
1067 context.Result(output+", good")
1068 return 1
1069
1070 #----------------
1071 # CONOPT test
1072
1073 conopt_test_text = """
1074 #if !defined(_WIN32)
1075 # define FNAME_LCASE_DECOR
1076 #endif
1077
1078 #include <conopt.h>
1079 #include <stdlib.h>
1080 int main(){
1081 int s, *v, e;
1082 s = COIDEF_Size();
1083 v = (int *)malloc(s*sizeof(int));
1084 e = COIDEF_Ini(v);
1085 return e;
1086 }
1087 """
1088
1089 def CheckCONOPT(context):
1090 context.Message( 'Checking for CONOPT... ' )
1091
1092 keep = KeepContext(context,"CONOPT")
1093
1094 is_ok = context.TryLink(conopt_test_text,".c")
1095 context.Result(is_ok)
1096
1097 keep.restore(context)
1098
1099 return is_ok
1100
1101 #----------------
1102 # Tcl test
1103
1104 # TCL and TK required version 8.1, 8.2, 8.3, or 8.4:
1105 tcltk_minor_newest_acceptable = 4
1106 tcltk_major_required = 8
1107
1108 tcl_check_text = r"""
1109 #include <tcl.h>
1110 #include <stdio.h>
1111 int main(void){
1112 printf("%s",TCL_PATCH_LEVEL);
1113 return 0;
1114 }
1115 """
1116
1117 def CheckTcl(context):
1118 return CheckExtLib(context,'tcl',tcl_check_text,static=env['STATIC_TCLTK'])
1119
1120 def CheckTclVersion(context):
1121 keep = KeepContext(context,'TCL',static=env['STATIC_TCLTK'])
1122 context.Message("Checking Tcl version... ")
1123 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
1124 keep.restore(context)
1125 if not is_ok:
1126 context.Result("failed to run check")
1127 return 0
1128
1129 major,minor,patch = tuple([int(i) for i in output.split(".")])
1130 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
1131 context.Result(output+" (bad version)")
1132 # bad version
1133 return 0
1134
1135 # good version
1136 context.Result(output+", good")
1137 return 1
1138
1139 #----------------
1140 # Tk test
1141
1142 tk_check_text = r"""
1143 #include <tk.h>
1144 #include <stdio.h>
1145 int main(void){
1146 printf("%s",TK_PATCH_LEVEL);
1147 return 0;
1148 }
1149 """
1150 def CheckTk(context):
1151 return CheckExtLib(context,'tk',tk_check_text,static=env['STATIC_TCLTK'])
1152
1153
1154 def CheckTkVersion(context):
1155 keep = KeepContext(context,'TK',static=context.env['STATIC_TCLTK'])
1156 context.Message("Checking Tk version... ")
1157 #print "LINKFLAGS =",context.env['LINKFLAGS']
1158 (is_ok,output) = context.TryRun(tk_check_text,'.c')
1159 keep.restore(context)
1160 if not is_ok:
1161 context.Result("failed to run check")
1162 return 0
1163
1164 major,minor,patch = tuple([int(i) for i in output.split(".")])
1165 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
1166 # bad version
1167 context.Result(output+" (bad version)")
1168 return 0
1169
1170 # good version
1171 context.Result(output+" (good)")
1172 return 1
1173
1174 #----------------
1175 # Tktable test
1176
1177 tktable_check_text = r"""
1178 #include <tkTable.h>
1179 #include <stdio.h>
1180 int main(void){
1181 Table mytable;
1182 return 0;
1183 }
1184 """
1185
1186 def CheckTkTable(context):
1187 return CheckExtLib(context,'tktable',tktable_check_text,static=env['STATIC_TCLTK'])
1188
1189 #---------------
1190 # X11 test
1191
1192 x11_check_text = r"""
1193 #include <X11/Xlib.h>
1194 #include <X11/IntrinsicP.h>
1195 #include <X11/Intrinsic.h>
1196 #include <X11/ObjectP.h>
1197 #include <X11/Object.h>
1198 int main(void){
1199 Object mything;
1200 return 0;
1201 }
1202 """
1203
1204 def CheckX11(context):
1205 return CheckExtLib(context,'X11',x11_check_text)
1206
1207 #----------------
1208 # Check that we can raise and catch sigint
1209
1210 sigint_test_text = r"""
1211 #include <signal.h>
1212 #include <setjmp.h>
1213 #include <stdlib.h>
1214 static jmp_buf g_jmpenv;
1215 void sighandler(int sig){
1216 longjmp(g_jmpenv,sig);
1217 }
1218 void testsigint(){
1219 raise(SIGINT);
1220 }
1221 int main(void){
1222 signal(SIGINT,&sighandler);
1223 switch(setjmp(g_jmpenv)){
1224 case 0:
1225 testsigint();
1226 exit(1);
1227 case SIGINT:
1228 exit(0);
1229 default:
1230 exit(2);
1231 }
1232 }
1233 """
1234
1235 def CheckSIGINT(context):
1236 context.Message("Checking SIGINT is catchable... ")
1237 (is_ok,output)=context.TryRun(sigint_test_text,".c")
1238 context.Result(is_ok)
1239 return is_ok
1240
1241 #----------------
1242 # Check that we're able to catch floating point errors
1243
1244 sigfpe_test_text = r"""
1245 #include <signal.h>
1246 #include <setjmp.h>
1247 #include <stdlib.h>
1248 #include <fenv.h>
1249 static jmp_buf g_jmpenv;
1250 void fpehandler(int sig){
1251 longjmp(g_jmpenv,sig);
1252 }
1253 int main(void){
1254 fenv_t myfenv;
1255 fegetenv(&myfenv);
1256 fesetenv(&myfenv);
1257 feenableexcept(FE_ALL_EXCEPT);
1258 signal(SIGFPE,&fpehandler);
1259 double x;
1260 switch(setjmp(g_jmpenv)){
1261 case 0:
1262 x = 1.0 / 0.0;
1263 /* failed to catch */
1264 exit(1);
1265 case SIGFPE:
1266 exit(0);
1267 }
1268 }
1269 """
1270
1271 def CheckFPE(context):
1272 context.Message("Checking C99 FPE behaviour... ")
1273 (is_ok,output) = context.TryRun(sigfpe_test_text,'.c')
1274 context.Result(is_ok)
1275 return is_ok
1276
1277 #----------------
1278 # signal reset needed?
1279
1280 sigreset_test_text = r"""
1281 #include <signal.h>
1282 #include <setjmp.h>
1283 #include <stdlib.h>
1284 #include <stdio.h>
1285 typedef void SigHandlerFn(int);
1286 static jmp_buf g_jmpenv;
1287 void sighandler(int sig){
1288 longjmp(g_jmpenv,sig);
1289 }
1290 void testsigint(){
1291 fprintf(stderr,"Raising SIGINT\n");
1292 raise(SIGINT);
1293 }
1294 int main(void){
1295 SigHandlerFn *last,*saved;
1296 saved = signal(SIGINT,&sighandler);
1297 if(saved!=SIG_DFL){
1298 fprintf(stderr,"Default handler was not correctly set\n");
1299 exit(3);
1300 }
1301 switch(setjmp(g_jmpenv)){
1302 case 0:
1303 testsigint();
1304 fprintf(stderr,"Back from SIGINT\n");
1305 exit(1);
1306 case SIGINT:
1307 break;
1308 default:
1309 exit(2);
1310 };
1311 last = signal(SIGINT,(saved!=NULL)?saved:SIG_DFL);
1312 if(last!=&sighandler){
1313 printf("1");
1314 exit(0);
1315 }
1316 printf("0");
1317 exit(0);
1318 }
1319 """
1320
1321 def CheckSigReset(context):
1322 context.Message("Checking signal handler reset... ")
1323 (is_ok,output) = context.TryRun(sigreset_test_text,'.c')
1324 if not is_ok:
1325 context.Result("ERROR")
1326 return 0
1327 if(int(output)):
1328 context.Result("required");
1329 context.env['ASC_RESETNEEDED'] = True
1330 else:
1331 context.Result("not required");
1332 context.env['ASC_RESETNEEDED'] = False
1333 return is_ok
1334
1335 #----------------
1336 # GCC Version sniffing
1337
1338 # TODO FIXME
1339
1340 gcc_version4 = False
1341
1342 #------------------------------------------------------
1343 # CONFIGURATION
1344
1345 conf = Configure(env
1346 , custom_tests = {
1347 'CheckMath' : CheckMath
1348 , 'CheckSwigVersion' : CheckSwigVersion
1349 , 'CheckPythonLib' : CheckPythonLib
1350 , 'CheckCUnit' : CheckCUnit
1351 , 'CheckDMalloc' : CheckDMalloc
1352 , 'CheckTcl' : CheckTcl
1353 , 'CheckTclVersion' : CheckTclVersion
1354 , 'CheckTk' : CheckTk
1355 , 'CheckTkVersion' : CheckTkVersion
1356 , 'CheckGcc' : CheckGcc
1357 , 'CheckGccVisibility' : CheckGccVisibility
1358 , 'CheckYacc' : CheckYacc
1359 , 'CheckTkTable' : CheckTkTable
1360 , 'CheckX11' : CheckX11
1361 , 'CheckIDA' : CheckIDA
1362 , 'CheckIDAVersion' : CheckIDAVersion
1363 , 'CheckCONOPT' : CheckCONOPT
1364 , 'CheckScrollkeeperConfig' : CheckScrollkeeperConfig
1365 , 'CheckFPE' : CheckFPE
1366 , 'CheckSIGINT' : CheckSIGINT
1367 , 'CheckSigReset' : CheckSigReset
1368 # , 'CheckIsNan' : CheckIsNan
1369 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
1370 }
1371 # , config_h = "config.h"
1372 )
1373
1374 # stdio -- just to check that compiler is behaving
1375
1376 if not conf.CheckHeader('stdio.h'):
1377 print "CPPPATH =",env.get('CPPPATH')
1378 print "Did not find 'stdio.h'! Check your compiler configuration."
1379 Exit(1)
1380
1381 # Math library
1382
1383 if need_libm:
1384 if not conf.CheckMath():
1385 print 'Did not find math library, exiting!'
1386 Exit(1)
1387 #pass
1388
1389 # Where is 'isnan'?
1390
1391 if not conf.CheckFunc('isnan') and not conf.CheckFunc('_isnan'):
1392 print "Didn't find isnan"
1393 # Exit(1)
1394
1395 # GCC visibility
1396
1397 if conf.CheckGcc():
1398 conf.env['HAVE_GCC']=True;
1399 if env['WITH_GCCVISIBILITY'] and conf.CheckGccVisibility():
1400 conf.env['HAVE_GCCVISIBILITY']=True;
1401 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
1402 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
1403 conf.env.Append(CCFLAGS=['-Wall'])
1404
1405 # Catching SIGINT
1406
1407 if not conf.CheckSIGINT():
1408 print "SIGINT unable to be caught. Aborting."
1409 exit(1)
1410
1411 # Catching SIGFPE
1412
1413 if conf.CheckFPE():
1414 conf.env['HAVE_C99FPE']=True
1415 else:
1416 conf.env['HAVE_C99FPE']=False
1417
1418 # Checking for signal reset requirement
1419
1420 if not conf.CheckSigReset():
1421 print "Unable to determine if signal reset is required"
1422 exit(1)
1423
1424 # YACC
1425
1426 if not conf.CheckYacc():
1427 print "YACC NOT FOUND OR NOT WORKING"
1428 else:
1429 conf.env['HAVE_YACC']=True
1430
1431 conf.env['HAVE_LEX']=True
1432
1433 # Tcl/Tk
1434
1435 if with_tcltk:
1436 if conf.CheckTcl():
1437 if conf.CheckTclVersion():
1438 if conf.CheckTk():
1439 if with_tcltk and conf.CheckTkVersion():
1440 if env['STATIC_TCLTK']:
1441 if conf.CheckTkTable():
1442 pass
1443 else:
1444 without_tcltk_reason = "TkTable not found"
1445 with_tcltk = False
1446 else:
1447 without_tcltk_reason = "Require Tk version <= 8.4. See 'scons -h'"
1448 with_tcltk = False
1449 else:
1450 without_tcltk_reason = "Tk not found."
1451 with_tcltk = False
1452 else:
1453 without_tcltk_reason = "Require Tcl <= 8.4 Tcl."
1454 with_tcltk = False
1455
1456 else:
1457 without_tcltk_reason = "Tcl not found."
1458 with_tcltk = False
1459
1460 if env['STATIC_TCLTK']:
1461 conf.CheckX11()
1462
1463 # Python... obviously we're already running python, so we just need to
1464 # check that we can link to the python library OK:
1465
1466 if not conf.CheckPythonLib():
1467 without_python_reason = 'libpython2.x not found or not linkable'
1468 with_python = False
1469
1470 # SWIG version
1471
1472 if with_python and not conf.CheckSwigVersion():
1473 without_python_reason = 'SWIG >= 1.3.24 is required'
1474 with_python = False
1475
1476 # CUnit
1477
1478 if with_cunit:
1479 if not conf.CheckCUnit():
1480 without_cunit_reason = 'CUnit not found'
1481 with_cunit = False
1482 #print "CUNIT NOT FOUND, LIBS=",conf.env.get('LIBS')
1483
1484 # DMALLOC
1485
1486 if with_dmalloc:
1487 if not conf.CheckDMalloc():
1488 without_dmalloc_reason = 'dmalloc not found'
1489 with_dmalloc = False
1490
1491 # IDA
1492
1493 if not with_ida:
1494 without_ida_reason = "Not selected (see config option WITH_SOLVERS)"
1495 elif not conf.CheckIDA():
1496 with_ida = False
1497 without_ida_reason = "IDA not found"
1498 elif not conf.CheckIDAVersion():
1499 with_ida = False
1500 without_ida_reason = "Unsupported (or undetected) SUNDIALS version"
1501
1502 # CONOPT
1503
1504 if not with_conopt:
1505 without_conopt_reason = "Not selected (see config option WITH_SOLVERS)"
1506 elif not conf.CheckCONOPT():
1507 with_conopt = False
1508 without_conpt_reason = "CONOPT not found"
1509
1510 # BLAS
1511
1512 need_blas=False
1513
1514 if with_lsode:
1515 need_fortran = True
1516 need_blas=True
1517
1518 if need_blas:
1519 if conf.CheckLib('blas'):
1520 with_local_blas = False
1521 without_local_blas_reason = "Found BLAS installed on system"
1522 else:
1523 with_local_blas = True
1524 need_fortran = True
1525 else:
1526 with_local_blas= False;
1527 without_local_blas_reason = "BLAS not required"
1528
1529 # FORTRAN
1530
1531 if need_fortran:
1532 conf.env.Tool('fortran')
1533 detect_fortran = conf.env.Detect(['g77','f77','gfortran'])
1534 if detect_fortran:
1535 # For some reason, g77 doesn't get detected properly on MinGW
1536 if not env.has_key('F77') and not env.has_key('FORTRAN'):
1537 conf.env.Replace(F77=detect_fortran)
1538 conf.env.Replace(F77COM='$F77 $F77FLAGS -c -o $TARGET $SOURCE')
1539 conf.env.Replace(F77FLAGS='')
1540 #print "F77:",conf.env['F77']
1541 #print "F77COM:",conf.env['F77COM']
1542 #print "F77FLAGS:",conf.env['F77FLAGS']
1543 fortran_builder = Builder(
1544 action='$F77COM'
1545 , suffix='.o'
1546 , src_suffix='.f'
1547 )
1548 conf.env.Append(BUILDERS={'Fortran':fortran_builder})
1549 else:
1550 with_lsode=False;
1551 without_lsode_reason="FORTRAN-77 required but not found"
1552
1553 #else:
1554 # print "FORTRAN not required"
1555
1556 # F2C
1557
1558 if need_fortran:
1559 if platform.system()=="Windows":
1560 conf.env.Append(LIBPATH='c:\mingw\lib')
1561
1562 # scrollkeeper
1563
1564 if with_scrollkeeper:
1565 if not conf.CheckScrollkeeperConfig():
1566 with_scrollkeeper=False
1567 without_scrollkeeper_reason="unable to detect scrollkeeper-config"
1568
1569 # TODO: -D_HPUX_SOURCE is needed
1570
1571 # TODO: check size of void*
1572
1573 # TODO: detect if dynamic libraries are possible or not
1574
1575 if platform.system()=="Windows" and env.has_key('MSVS'):
1576 _found_windows_h = conf.CheckHeader('Windows.h')
1577
1578 if not _found_windows_h:
1579 print "Could not locate 'Windows.h' in CPPPATH. Check your configuration."
1580 Exit(1)
1581
1582 if with_python and not conf.CheckHeader(['basetsd.h','BaseTsd.h']):
1583 with_python = 0;
1584 without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
1585
1586 conf.env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
1587
1588 conf.Finish()
1589
1590 #---------------------------------------
1591 # SUBSTITUTION DICTIONARY for .in files
1592
1593 release = env.get('RELEASE')
1594 if release=="0.":
1595 release="0"
1596
1597 #print "SUBSTITUTED CONOPT_LIBPATH:",c_escape(env.subst("$CONOPT_LIBPATH"))
1598
1599 subst_dict = {
1600 '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
1601 , '@GLADE_FILE@':'ascend.glade'
1602 , '@HELP_ROOT@':''
1603 , '@ICON_EXTENSION@':icon_extension
1604 , '@INSTALL_ASCDATA@':env['INSTALL_ASCDATA']
1605 , '@INSTALL_BIN@':env['INSTALL_BIN']
1606 , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
1607 , '@INSTALL_LIB@':env['INSTALL_LIB']
1608 , '@INSTALL_MODELS@':env['INSTALL_MODELS']
1609 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
1610 , '@VERSION@':version
1611 , '@RELEASE@':release
1612 , '@DISTTAR_NAME@':env['DISTTAR_NAME']
1613 , '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
1614 , '@ASC_SHLIBSUFFIX@':env['SHLIBSUFFIX']
1615 , '@ASC_SHLIBPREFIX@':env['SHLIBPREFIX']
1616 , '@ASC_ENV_TK_DEFAULT@' : '$$ASCENDDIST/tcltk'
1617 , '@ASC_DISTDIR_REL_BIN@' : default_rel_distdir
1618 , '@PYTHON@' : python_exe
1619 , '@ASC_CONOPT_LIB@':env.get('CONOPT_LIB')
1620 , '@ASC_CONOPT_ENVVAR@':env.get('CONOPT_ENVVAR')
1621 , '@ASC_CONOPT_DLPATH@':c_escape(env.subst("$CONOPT_LIBPATH"))
1622 , '@SOURCE_ROOT@':os.path.abspath(str(env.Dir("#")))
1623 }
1624
1625 if env.get('WITH_LOCAL_HELP'):
1626 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
1627 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
1628
1629 # bool options...
1630 for k,v in {
1631 'ABSOLUTE_PATHS' : 'ASC_ABSOLUTE_PATHS'
1632 ,'WITH_XTERM_COLORS' : 'ASC_XTERM_COLORS'
1633 ,'MALLOC_DEBUG' : 'MALLOC_DEBUG'
1634 }.iteritems():
1635 if env.get(k):
1636 # subst_dict['@'+v+'@']='1'
1637 subst_dict["/\\* #define "+v+' @'+v+"@ \\*/"]='# define '+v+' 1 '
1638
1639 if with_ida:
1640 subst_dict["/\\* #define ASC_WITH_IDA @ASC_WITH_IDA@ \\*/"]='#define ASC_WITH_IDA '
1641
1642 if with_dmalloc:
1643 subst_dict["/\\* #define ASC_WITH_DMALLOC @ASC_WITH_DMALLOC@ \\*/"]='#define ASC_WITH_DMALLOC '
1644
1645 if with_conopt:
1646 subst_dict["/\\* #define ASC_WITH_CONOPT @ASC_WITH_CONOPT@ \\*/"]='#define ASC_WITH_CONOPT '
1647
1648 if with_lsode:
1649 subst_dict["/\\* #define ASC_WITH_LSODE @ASC_WITH_LSODE@ \\*/"]='#define ASC_WITH_LSODE '
1650
1651 if with_python:
1652 subst_dict['@ASCXX_USE_PYTHON@']="1"
1653 env['WITH_PYTHON']=1;
1654
1655 if env.has_key('HAVE_GCCVISIBILITY'):
1656 subst_dict['@HAVE_GCCVISIBILITY@'] = "1"
1657
1658 if env.get('ASC_RESETNEEDED'):
1659 subst_dict["/\\* #define ASC_RESETNEEDED @ASC_RESETNEEDED@ \\*/"]='#define ASC_RESETNEEDED '
1660
1661 if env.get('HAVE_C99FPE'):
1662 subst_dict["/\\* #define HAVE_C99FPE @HAVE_C99FPE@ \\*/"]='#define HAVE_C99FPE '
1663
1664 env.Append(SUBST_DICT=subst_dict)
1665
1666 #------------------------------------------------------
1667 # RECIPE: Fix up long command-line bug on Win2k
1668
1669 # Currently this is broken, awaiting help from the SCons users list
1670
1671 if 0 and env['PLATFORM'] == 'win32':
1672 import win32file
1673 import win32event
1674 import win32process
1675 import win32security
1676 import string
1677
1678 def my_spawn(sh, escape, cmd, args, spawnenv):
1679 for var in spawnenv:
1680 spawnenv[var] = spawnenv[var].encode('ascii', 'replace')
1681
1682 sAttrs = win32security.SECURITY_ATTRIBUTES()
1683 StartupInfo = win32process.STARTUPINFO()
1684 newargs = string.join(map(escape, args[1:]), ' ')
1685 cmdline = cmd + " " + newargs
1686
1687 # check for any special operating system commands
1688 if cmd == 'del':
1689 for arg in args[1:]:
1690 win32file.DeleteFile(arg)
1691 exit_code = 0
1692 else:
1693 # otherwise execute the command.
1694 hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo)
1695 win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
1696 exit_code = win32process.GetExitCodeProcess(hProcess)
1697 win32file.CloseHandle(hProcess);
1698 win32file.CloseHandle(hThread);
1699 return exit_code
1700
1701 env['SPAWN'] = my_spawn
1702
1703 #------------------------------------------------------
1704 # RECIPE: SWIG scanner
1705
1706 import SCons.Script
1707
1708 SWIGScanner = SCons.Scanner.ClassicCPP(
1709 "SWIGScan"
1710 , ".i"
1711 , "CPPPATH"
1712 , '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
1713 )
1714
1715 env.Append(SCANNERS=[SWIGScanner])
1716
1717 #------------------------------------------------------
1718 # RECIPE: 'SubstInFile', used in pygtk SConscript
1719
1720 import re
1721 from SCons.Script import * # the usual scons stuff you get in a SConscript
1722
1723 def TOOL_SUBST(env):
1724 """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
1725 from the source to the target.
1726 The values of SUBST_DICT first have any construction variables expanded
1727 (its keys are not expanded).
1728 If a value of SUBST_DICT is a python callable function, it is called and
1729 the result is expanded as the value.
1730 If there's more than one source and more than one target, each target gets
1731 substituted from the corresponding source.
1732 """
1733 env.Append(TOOLS = 'SUBST')
1734 def do_subst_in_file(targetfile, sourcefile, dict):
1735 """Replace all instances of the keys of dict with their values.
1736 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
1737 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
1738 """
1739 try:
1740 f = open(sourcefile, 'rb')
1741 contents = f.read()
1742 f.close()
1743 except:
1744 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
1745 for (k,v) in dict.items():
1746 contents = re.sub(k, v, contents)
1747 try:
1748 f = open(targetfile, 'wb')
1749 f.write(contents)
1750 f.close()
1751 except:
1752 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
1753 return 0 # success
1754
1755 def subst_in_file(target, source, env):
1756 if not env.has_key('SUBST_DICT'):
1757 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
1758 d = dict(env['SUBST_DICT']) # copy it
1759 for (k,v) in d.items():
1760 if callable(v):
1761 d[k] = env.subst(v())
1762 elif SCons.Util.is_String(v):
1763 d[k]=env.subst(v)
1764 else:
1765 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
1766 for (t,s) in zip(target, source):
1767 return do_subst_in_file(str(t), str(s), d)
1768
1769 def subst_in_file_string(target, source, env):
1770 """This is what gets printed on the console."""
1771 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
1772 for (t,s) in zip(target, source)])
1773
1774 def subst_emitter(target, source, env):
1775 """Add dependency from substituted SUBST_DICT to target.
1776 Returns original target, source tuple unchanged.
1777 """
1778 d = env['SUBST_DICT'].copy() # copy it
1779 for (k,v) in d.items():
1780 if callable(v):
1781 d[k] = env.subst(v())
1782 elif SCons.Util.is_String(v):
1783 d[k]=env.subst(v)
1784 Depends(target, SCons.Node.Python.Value(d))
1785 return target, source
1786
1787 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
1788 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
1789
1790 TOOL_SUBST(env)
1791
1792 #------------------------------------------------------
1793 # Recipe for 'CHMOD' ACTION
1794
1795 import SCons
1796 from SCons.Script.SConscript import SConsEnvironment
1797 SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
1798 lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
1799
1800 def InstallPerm(env, dest, files, perm):
1801 obj = env.Install(dest, files)
1802 for i in obj:
1803 env.AddPostAction(i, env.Chmod(str(i), perm))
1804
1805 SConsEnvironment.InstallPerm = InstallPerm
1806
1807 # define wrappers
1808 SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
1809 SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
1810 SConsEnvironment.InstallShared = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
1811
1812 #------------------------------------------------------
1813 # BUILD...
1814
1815 # so that #include <modulename/headername.h> works across all modules...
1816 env.AppendUnique(CPPPATH=['#base/generic'])
1817
1818 if env['DEBUG']:
1819 env.Append(CCFLAGS=['-g'])
1820
1821 if env['GCOV']:
1822 env.Append(
1823 CPPFLAGS=['-g','-fprofile-arcs','-ftest-coverage']
1824 , LIBS=['gcov']
1825 , LINKFLAGS=['-fprofile-arcs','-ftest-coverage']
1826 )
1827
1828 if with_ida:
1829 env.Append(WITH_IDA=1)
1830
1831 if with_conopt:
1832 env.Append(WITH_CONOPT=1)
1833
1834 #-------------
1835 # TCL/TK GUI
1836
1837 if with_tcltk:
1838 env.SConscript(['tcltk/generic/interface/SConscript'],'env')
1839 else:
1840 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
1841
1842 #-------------
1843 # PYTHON INTERFACE
1844
1845 if with_python:
1846 env.SConscript(['pygtk/SConscript'],'env')
1847 else:
1848 print "Skipping... Python GUI isn't being built:",without_python_reason
1849
1850 #------------
1851 # BASE/GENERIC SUBDIRECTORIES
1852
1853 libascend_env = env.Copy()
1854
1855 dirs = ['general','utilities','compiler','solver','packages']
1856
1857 srcs = []
1858 for d in dirs:
1859 heresrcs = libascend_env.SConscript('base/generic/'+d+'/SConscript','libascend_env')
1860 srcs += heresrcs
1861
1862 #-------------
1863 # IMPORTED CODE: LSODE, BLAS, etc
1864
1865 if with_lsode:
1866 srcs += env.SConscript(['lsod/SConscript'],'env')
1867 srcs += env.SConscript(['linpack/SConscript'],'env')
1868 else:
1869 print "Skipping... LSODE won't be built:", without_lsode_reason
1870
1871 if with_local_blas:
1872 srcs += env.SConscript(['blas/SConscript'],'env')
1873 else:
1874 print "Skipping... BLAS won't be built:", without_local_blas_reason
1875
1876 if not with_ida:
1877 print "Skipping... IDA won't be built:", without_ida_reason
1878
1879 #-------------
1880 # LIBASCEND -- all base/generic functionality
1881
1882 if with_dmalloc:
1883 libascend_env.Append(LIBS=['dmalloc'])
1884
1885 libascend = libascend_env.SharedLibrary('ascend',srcs)
1886
1887 env.Alias('libascend',libascend)
1888
1889 #-------------
1890 # UNIT TESTS (C CODE)
1891
1892 if with_cunit:
1893 testdirs = ['general','solver','utilities']
1894 testsrcs = []
1895 for testdir in testdirs:
1896 path = 'base/generic/'+testdir+'/test/'
1897 env.SConscript([path+'SConscript'],'env')
1898 testsrcs += [i.path for i in env['TESTSRCS_'+testdir.upper()]]
1899
1900 #print "TESTSRCS =",testsrcs
1901
1902 env.SConscript(['test/SConscript'],'env')
1903 env.SConscript(['base/generic/test/SConscript'],'env')
1904
1905 env.Alias('test',[env.Dir('test'),env.Dir('base/generic/test')])
1906
1907 else:
1908 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1909
1910 #-------------
1911 # EXTERNAL FUNCTIONS
1912
1913 env['extfns']=[]
1914 modeldirs = env.SConscript(['models/SConscript'],'env')
1915
1916 if not with_extfns:
1917 print "Skipping... External modules aren't being built:",without_extfns_reason
1918
1919 env.Alias('extfns',env['extfns'])
1920
1921 #------------------------------------------------------
1922 # CREATE ASCEND-CONFIG scriptlet
1923
1924 ascendconfig = env.SubstInFile('ascend-config.in')
1925
1926 #------------------------------------------------------
1927 # INSTALLATION
1928
1929 if env.get('CAN_INSTALL'):
1930
1931 dirs = ['INSTALL_BIN','INSTALL_ASCDATA','INSTALL_LIB', 'INSTALL_INCLUDE', 'INSTALL_DOC']
1932 install_dirs = [env.Entry(env['INSTALL_ROOT']+env[d]) for d in dirs]
1933 install_dirs += modeldirs
1934
1935 # TODO: add install options
1936 env.Alias('install',install_dirs)
1937
1938 env.InstallShared(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1939
1940 env.InstallProgram(env['INSTALL_ROOT']+env['INSTALL_BIN'],ascendconfig)
1941
1942 #------------------------------------------------------
1943 # WINDOWS INSTALLER
1944 # For the windows installer, please see pygtk/SConscript
1945
1946 if with_installer:
1947 pass
1948 else:
1949 print "Skipping... Windows installer isn't being built:",without_installer_reason
1950
1951 #------------------------------------------------------
1952 # PROJECT FILE for MSVC
1953
1954 env.SConscript(['base/msvc/SConscript'],['env','libascend']);
1955
1956 #------------------------------------------------------
1957 # CREATE the SPEC file for generation of RPM packages
1958
1959 if platform.system()=="Linux":
1960 env.SubstInFile('ascend.spec.in')
1961
1962 #------------------------------------------------------
1963 # CREATE OMF FILE FOR USE WITH SCROLLKEEPER
1964
1965 if with_scrollkeeper:
1966 env.SubstInFile('#/pygtk/gnome/ascend.omf.in')
1967 env.InstallShared(env['INSTALL_ROOT']+env['OMFDIR'],"#/pygtk/gnome/ascend.omf")
1968
1969 #------------------------------------------------------
1970 # DISTRIBUTION TAR FILE
1971
1972 env['DISTTAR_FORMAT']='bz2'
1973 env.Append(
1974 DISTTAR_EXCLUDEEXTS=['.o','.os','.so','.a','.dll','.cc','.cache','.pyc','.cvsignore','.dblite','.log','.pl','.out']
1975 , DISTTAR_EXCLUDEDIRS=['CVS','.svn','.sconf_temp', 'dist']
1976 )
1977
1978 tar = env.DistTar("dist/"+env['DISTTAR_NAME']
1979 , [env.Dir('#')]
1980 )
1981
1982 env.Depends(tar,'ascend.spec')
1983
1984 Alias('dist',tar)
1985
1986 #------------------------------------------------------
1987 # USER'S MANUAL
1988
1989 env.SConscript('doc/SConscript',['env'])
1990
1991 #------------------------------------------------------
1992 # LIBASCEND DOXYGEN DOCUMENTATION
1993
1994 env.SConscript('base/doc/SConscript',['env'])
1995
1996 #------------------------------------------------------
1997 # RPM BUILD
1998
1999 # for RPM builds, 'scons dist' then 'rpmbuild -ta dist/ascend-*.tar.bz2'
2000 # (check * for the version number used to create the tarball)
2001
2002 #------------------------------------------------------
2003 # DEFAULT TARGETS
2004
2005 default_targets =['libascend']
2006 if with_tcltk:
2007 default_targets.append('tcltk')
2008 if with_python:
2009 default_targets.append('pygtk')
2010 if with_installer:
2011 default_targets.append('installer')
2012 if with_extfns:
2013 default_targets.append('extfns')
2014
2015 env.Default(default_targets)
2016
2017 print "Building targets:"," ".join([str(i) for i in BUILD_TARGETS])
2018
2019 # vim: set syntax=python:
2020

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