/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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