/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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