/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1078 - (show annotations) (download)
Tue Jan 9 08:04:51 2007 UTC (12 years, 11 months ago) by johnpye
File size: 50156 byte(s)
Fixing MINGW detection
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 Exit(1)
1429
1430 # Math library
1431
1432 if need_libm:
1433 if not conf.CheckMath():
1434 print 'Did not find math library, exiting!'
1435 Exit(1)
1436 #pass
1437
1438 # Where is 'isnan'?
1439
1440 if not conf.CheckFunc('isnan') and not conf.CheckFunc('_isnan'):
1441 print "Didn't find isnan"
1442 # Exit(1)
1443
1444 # GCC visibility
1445
1446 if conf.CheckGcc():
1447 conf.env['HAVE_GCC']=True;
1448 if env['WITH_GCCVISIBILITY'] and conf.CheckGccVisibility():
1449 conf.env['HAVE_GCCVISIBILITY']=True;
1450 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
1451 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
1452 conf.env.Append(CCFLAGS=['-Wall'])
1453
1454 # Catching SIGINT
1455
1456 if not conf.CheckSIGINT():
1457 print "SIGINT unable to be caught. Aborting."
1458 exit(1)
1459
1460 # Catching SIGFPE
1461
1462 if conf.CheckFPE():
1463 conf.env['HAVE_C99FPE']=True
1464 else:
1465 conf.env['HAVE_C99FPE']=False
1466
1467 # Checking for signal reset requirement
1468
1469 if not conf.CheckSigReset():
1470 print "Unable to determine if signal reset is required"
1471 exit(1)
1472
1473 # YACC
1474
1475 if not conf.CheckYacc():
1476 print "YACC NOT FOUND OR NOT WORKING"
1477 else:
1478 conf.env['HAVE_YACC']=True
1479
1480 if not conf.CheckLex():
1481 print "YACC NOT FOUND OR NOT WORKING"
1482 else:
1483 conf.env['HAVE_LEX']=True
1484
1485 # Tcl/Tk
1486
1487 if with_tcltk:
1488 if conf.CheckTcl():
1489 if conf.CheckTclVersion():
1490 if conf.CheckTk():
1491 if with_tcltk and conf.CheckTkVersion():
1492 if env['STATIC_TCLTK']:
1493 if conf.CheckTkTable():
1494 pass
1495 else:
1496 without_tcltk_reason = "TkTable not found"
1497 with_tcltk = False
1498 else:
1499 without_tcltk_reason = "Require Tk version <= 8.4. See 'scons -h'"
1500 with_tcltk = False
1501 else:
1502 without_tcltk_reason = "Tk not found."
1503 with_tcltk = False
1504 else:
1505 without_tcltk_reason = "Require Tcl <= 8.4 Tcl."
1506 with_tcltk = False
1507
1508 else:
1509 without_tcltk_reason = "Tcl not found."
1510 with_tcltk = False
1511
1512 if env['STATIC_TCLTK']:
1513 conf.CheckX11()
1514
1515 # Python... obviously we're already running python, so we just need to
1516 # check that we can link to the python library OK:
1517
1518 if not conf.CheckPythonLib():
1519 without_python_reason = 'libpython2.x not found or not linkable'
1520 with_python = False
1521 env['WITH_PYTHON']=False
1522
1523 # SWIG version
1524
1525 if with_python and not conf.CheckSwigVersion():
1526 without_python_reason = 'SWIG >= 1.3.24 is required'
1527 with_python = False
1528 env['WITH_PYTHON']=False
1529
1530 # CUnit
1531
1532 if with_cunit:
1533 if not conf.CheckCUnit():
1534 without_cunit_reason = 'CUnit not found'
1535 with_cunit = False
1536 #print "CUNIT NOT FOUND, LIBS=",conf.env.get('LIBS')
1537
1538 # DMALLOC
1539
1540 if with_dmalloc:
1541 if not conf.CheckDMalloc():
1542 without_dmalloc_reason = 'dmalloc not found'
1543 with_dmalloc = False
1544
1545 # IDA
1546
1547 if not with_ida:
1548 without_ida_reason = "Not selected (see config option WITH_SOLVERS)"
1549 elif not conf.CheckIDA():
1550 with_ida = False
1551 without_ida_reason = "IDA not found"
1552 elif not conf.CheckIDAVersion():
1553 with_ida = False
1554 without_ida_reason = "Unsupported (or undetected) SUNDIALS version"
1555
1556 # CONOPT
1557
1558 if not with_conopt:
1559 without_conopt_reason = "Not selected (see config option WITH_SOLVERS)"
1560 elif not conf.CheckCONOPT():
1561 with_conopt = False
1562 without_conpt_reason = "CONOPT not found"
1563
1564 # BLAS
1565
1566 need_blas=False
1567
1568 if with_lsode:
1569 need_fortran = True
1570 need_blas=True
1571
1572 if need_blas:
1573 if conf.CheckLib('blas'):
1574 with_local_blas = False
1575 without_local_blas_reason = "Found BLAS installed on system"
1576 else:
1577 with_local_blas = True
1578 need_fortran = True
1579 else:
1580 with_local_blas= False;
1581 without_local_blas_reason = "BLAS not required"
1582
1583 # FORTRAN
1584
1585 if need_fortran:
1586 conf.env.Tool('fortran')
1587 detect_fortran = conf.env.Detect(['g77','f77','gfortran'])
1588 if detect_fortran:
1589 # For some reason, g77 doesn't get detected properly on MinGW
1590 if not env.has_key('F77') and not env.has_key('FORTRAN'):
1591 conf.env.Replace(F77=detect_fortran)
1592 conf.env.Replace(F77COM='$F77 $F77FLAGS -c -o $TARGET $SOURCE')
1593 conf.env.Replace(F77FLAGS='')
1594 #print "F77:",conf.env['F77']
1595 #print "F77COM:",conf.env['F77COM']
1596 #print "F77FLAGS:",conf.env['F77FLAGS']
1597 fortran_builder = Builder(
1598 action='$F77COM'
1599 , suffix='.o'
1600 , src_suffix='.f'
1601 )
1602 conf.env.Append(BUILDERS={'Fortran':fortran_builder})
1603 else:
1604 with_lsode=False;
1605 without_lsode_reason="FORTRAN-77 required but not found"
1606
1607 #else:
1608 # print "FORTRAN not required"
1609
1610 # F2C
1611
1612 if need_fortran:
1613 if platform.system()=="Windows":
1614 conf.env.Append(LIBPATH='c:\mingw\lib')
1615
1616 # scrollkeeper
1617
1618 if with_scrollkeeper:
1619 if not conf.CheckScrollkeeperConfig():
1620 with_scrollkeeper=False
1621 without_scrollkeeper_reason="unable to detect scrollkeeper-config"
1622
1623 # TODO: -D_HPUX_SOURCE is needed
1624
1625 # TODO: check size of void*
1626
1627 # TODO: detect if dynamic libraries are possible or not
1628
1629 if platform.system()=="Windows" and env.has_key('MSVS'):
1630 _found_windows_h = conf.CheckHeader('Windows.h')
1631
1632 if not _found_windows_h:
1633 print "Could not locate 'Windows.h' in CPPPATH. Check your configuration."
1634 Exit(1)
1635
1636 if with_python and not conf.CheckHeader(['basetsd.h','BaseTsd.h']):
1637 with_python = 0;
1638 without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
1639
1640 conf.env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
1641
1642 conf.Finish()
1643
1644 #---------------------------------------
1645 # SUBSTITUTION DICTIONARY for .in files
1646
1647 release = env.get('RELEASE')
1648 if release=="0.":
1649 release="0"
1650
1651 #print "SUBSTITUTED CONOPT_LIBPATH:",c_escape(env.subst("$CONOPT_LIBPATH"))
1652
1653 subst_dict = {
1654 '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
1655 , '@GLADE_FILE@':'ascend.glade'
1656 , '@HELP_ROOT@':''
1657 , '@ICON_EXTENSION@':icon_extension
1658 , '@INSTALL_ASCDATA@':env['INSTALL_ASCDATA']
1659 , '@INSTALL_BIN@':env['INSTALL_BIN']
1660 , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
1661 , '@INSTALL_LIB@':env['INSTALL_LIB']
1662 , '@INSTALL_MODELS@':env['INSTALL_MODELS']
1663 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
1664 , '@VERSION@':version
1665 , '@RELEASE@':release
1666 , '@DISTTAR_NAME@':env['DISTTAR_NAME']
1667 , '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
1668 , '@ASC_SHLIBSUFFIX@':env['SHLIBSUFFIX']
1669 , '@ASC_SHLIBPREFIX@':env['SHLIBPREFIX']
1670 , '@ASC_ENV_TK_DEFAULT@' : '$$ASCENDDIST/tcltk'
1671 , '@ASC_DISTDIR_REL_BIN@' : default_rel_distdir
1672 , '@PYTHON@' : python_exe
1673 , '@ASC_CONOPT_LIB@':env.get('CONOPT_LIB')
1674 , '@ASC_CONOPT_ENVVAR@':env.get('CONOPT_ENVVAR')
1675 , '@ASC_CONOPT_DLPATH@':c_escape(env.subst("$CONOPT_LIBPATH"))
1676 , '@SOURCE_ROOT@':os.path.abspath(str(env.Dir("#")))
1677 }
1678
1679 if env.get('WITH_LOCAL_HELP'):
1680 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
1681 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
1682
1683 # bool options...
1684 for k,v in {
1685 'ABSOLUTE_PATHS' : 'ASC_ABSOLUTE_PATHS'
1686 ,'WITH_XTERM_COLORS' : 'ASC_XTERM_COLORS'
1687 ,'MALLOC_DEBUG' : 'MALLOC_DEBUG'
1688 }.iteritems():
1689 if env.get(k):
1690 # subst_dict['@'+v+'@']='1'
1691 subst_dict["/\\* #define "+v+' @'+v+"@ \\*/"]='# define '+v+' 1 '
1692
1693 if with_ida:
1694 subst_dict["/\\* #define ASC_WITH_IDA @ASC_WITH_IDA@ \\*/"]='#define ASC_WITH_IDA '
1695
1696 if with_dmalloc:
1697 subst_dict["/\\* #define ASC_WITH_DMALLOC @ASC_WITH_DMALLOC@ \\*/"]='#define ASC_WITH_DMALLOC '
1698
1699 if with_conopt:
1700 subst_dict["/\\* #define ASC_WITH_CONOPT @ASC_WITH_CONOPT@ \\*/"]='#define ASC_WITH_CONOPT '
1701
1702 if with_lsode:
1703 subst_dict["/\\* #define ASC_WITH_LSODE @ASC_WITH_LSODE@ \\*/"]='#define ASC_WITH_LSODE '
1704
1705 if with_mmio:
1706 subst_dict["/\\* #define ASC_WITH_MMIO @ASC_WITH_MMIO@ \\*/"]='#define ASC_WITH_MMIO '
1707
1708 if with_python:
1709 subst_dict['@ASCXX_USE_PYTHON@']="1"
1710 env['WITH_PYTHON']=1;
1711
1712 if env.has_key('HAVE_GCCVISIBILITY'):
1713 subst_dict['@HAVE_GCCVISIBILITY@'] = "1"
1714
1715 if env.get('ASC_RESETNEEDED'):
1716 subst_dict["/\\* #define ASC_RESETNEEDED @ASC_RESETNEEDED@ \\*/"]='#define ASC_RESETNEEDED '
1717
1718 if env.get('HAVE_C99FPE'):
1719 subst_dict["/\\* #define HAVE_C99FPE @HAVE_C99FPE@ \\*/"]='#define HAVE_C99FPE '
1720
1721 env.Append(SUBST_DICT=subst_dict)
1722
1723 #------------------------------------------------------
1724 # RECIPE: Fix up long command-line bug on Win2k
1725
1726 # Currently this is broken, awaiting help from the SCons users list
1727
1728 if 0 and env['PLATFORM'] == 'win32':
1729 import win32file
1730 import win32event
1731 import win32process
1732 import win32security
1733 import string
1734
1735 def my_spawn(sh, escape, cmd, args, spawnenv):
1736 for var in spawnenv:
1737 spawnenv[var] = spawnenv[var].encode('ascii', 'replace')
1738
1739 sAttrs = win32security.SECURITY_ATTRIBUTES()
1740 StartupInfo = win32process.STARTUPINFO()
1741 newargs = string.join(map(escape, args[1:]), ' ')
1742 cmdline = cmd + " " + newargs
1743
1744 # check for any special operating system commands
1745 if cmd == 'del':
1746 for arg in args[1:]:
1747 win32file.DeleteFile(arg)
1748 exit_code = 0
1749 else:
1750 # otherwise execute the command.
1751 hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo)
1752 win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
1753 exit_code = win32process.GetExitCodeProcess(hProcess)
1754 win32file.CloseHandle(hProcess);
1755 win32file.CloseHandle(hThread);
1756 return exit_code
1757
1758 env['SPAWN'] = my_spawn
1759
1760 #------------------------------------------------------
1761 # RECIPE: SWIG scanner
1762
1763 import SCons.Script
1764
1765 SWIGScanner = SCons.Scanner.ClassicCPP(
1766 "SWIGScan"
1767 , ".i"
1768 , "CPPPATH"
1769 , '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
1770 )
1771
1772 env.Append(SCANNERS=[SWIGScanner])
1773
1774 #------------------------------------------------------
1775 # RECIPE: 'SubstInFile', used in pygtk SConscript
1776
1777 import re
1778 from SCons.Script import * # the usual scons stuff you get in a SConscript
1779
1780 def TOOL_SUBST(env):
1781 """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
1782 from the source to the target.
1783 The values of SUBST_DICT first have any construction variables expanded
1784 (its keys are not expanded).
1785 If a value of SUBST_DICT is a python callable function, it is called and
1786 the result is expanded as the value.
1787 If there's more than one source and more than one target, each target gets
1788 substituted from the corresponding source.
1789 """
1790 env.Append(TOOLS = 'SUBST')
1791 def do_subst_in_file(targetfile, sourcefile, dict):
1792 """Replace all instances of the keys of dict with their values.
1793 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
1794 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
1795 """
1796 try:
1797 f = open(sourcefile, 'rb')
1798 contents = f.read()
1799 f.close()
1800 except:
1801 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
1802 for (k,v) in dict.items():
1803 contents = re.sub(k, v, contents)
1804 try:
1805 f = open(targetfile, 'wb')
1806 f.write(contents)
1807 f.close()
1808 except:
1809 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
1810 return 0 # success
1811
1812 def subst_in_file(target, source, env):
1813 if not env.has_key('SUBST_DICT'):
1814 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
1815 d = dict(env['SUBST_DICT']) # copy it
1816 for (k,v) in d.items():
1817 if callable(v):
1818 d[k] = env.subst(v())
1819 elif SCons.Util.is_String(v):
1820 d[k]=env.subst(v)
1821 else:
1822 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
1823 for (t,s) in zip(target, source):
1824 return do_subst_in_file(str(t), str(s), d)
1825
1826 def subst_in_file_string(target, source, env):
1827 """This is what gets printed on the console."""
1828 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
1829 for (t,s) in zip(target, source)])
1830
1831 def subst_emitter(target, source, env):
1832 """Add dependency from substituted SUBST_DICT to target.
1833 Returns original target, source tuple unchanged.
1834 """
1835 d = env['SUBST_DICT'].copy() # copy it
1836 for (k,v) in d.items():
1837 if callable(v):
1838 d[k] = env.subst(v())
1839 elif SCons.Util.is_String(v):
1840 d[k]=env.subst(v)
1841 Depends(target, SCons.Node.Python.Value(d))
1842 return target, source
1843
1844 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
1845 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
1846
1847 TOOL_SUBST(env)
1848
1849 #------------------------------------------------------
1850 # Recipe for 'CHMOD' ACTION
1851
1852 import SCons
1853 from SCons.Script.SConscript import SConsEnvironment
1854 SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
1855 lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
1856
1857 def InstallPerm(env, dest, files, perm):
1858 obj = env.Install(dest, files)
1859 for i in obj:
1860 env.AddPostAction(i, env.Chmod(str(i), perm))
1861
1862 SConsEnvironment.InstallPerm = InstallPerm
1863
1864 # define wrappers
1865 SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
1866 SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
1867 SConsEnvironment.InstallShared = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
1868
1869 #------------------------------------------------------
1870 # BUILD...
1871
1872 # so that #include <modulename/headername.h> works across all modules...
1873 env.AppendUnique(CPPPATH=['#base/generic'])
1874
1875 if env['DEBUG']:
1876 env.Append(CCFLAGS=['-g'])
1877
1878 if env['GCOV']:
1879 env.Append(
1880 CPPFLAGS=['-g','-fprofile-arcs','-ftest-coverage']
1881 , LIBS=['gcov']
1882 , LINKFLAGS=['-fprofile-arcs','-ftest-coverage']
1883 )
1884
1885 if with_ida:
1886 env.Append(WITH_IDA=1)
1887
1888 if with_conopt:
1889 env.Append(WITH_CONOPT=1)
1890
1891 #-------------
1892 # TCL/TK GUI
1893
1894 if with_tcltk:
1895 env.SConscript(['tcltk/generic/interface/SConscript'],'env')
1896 else:
1897 print "Skipping... Tcl/Tk bindings aren't being built:",without_tcltk_reason
1898
1899 #-------------
1900 # PYTHON INTERFACE
1901
1902 if with_python:
1903 env.SConscript(['pygtk/SConscript'],'env')
1904 else:
1905 print "Skipping... Python bindings aren't being built:",without_python_reason
1906
1907 #------------
1908 # BASE/GENERIC SUBDIRECTORIES
1909
1910 libascend_env = env.Copy()
1911
1912 dirs = ['general','utilities','compiler','solver','packages']
1913
1914 srcs = []
1915 for d in dirs:
1916 heresrcs = libascend_env.SConscript('base/generic/'+d+'/SConscript','libascend_env')
1917 srcs += heresrcs
1918
1919 #-------------
1920 # IMPORTED CODE: LSODE, BLAS, etc
1921
1922 if with_lsode:
1923 srcs += env.SConscript(['lsod/SConscript'],'env')
1924 srcs += env.SConscript(['linpack/SConscript'],'env')
1925 else:
1926 print "Skipping... LSODE won't be built:", without_lsode_reason
1927
1928 if with_local_blas:
1929 srcs += env.SConscript(['blas/SConscript'],'env')
1930 else:
1931 print "Skipping... BLAS won't be built:", without_local_blas_reason
1932
1933 if not with_ida:
1934 print "Skipping... IDA won't be built:", without_ida_reason
1935
1936 if with_mmio:
1937 srcs += env.SConscript(['mmio/SConscript'],'env')
1938 else:
1939 print "Skipping... MMIO export won't be built:", without_mmio_reason
1940 #-------------
1941 # LIBASCEND -- all base/generic functionality
1942
1943 if with_dmalloc:
1944 libascend_env.Append(LIBS=['dmalloc'])
1945
1946 libascend = libascend_env.SharedLibrary('ascend',srcs)
1947
1948 env.Alias('libascend',libascend)
1949
1950 #-------------
1951 # UNIT TESTS (C CODE)
1952
1953 if with_cunit:
1954 testdirs = ['general','solver','utilities']
1955 testsrcs = []
1956 for testdir in testdirs:
1957 path = 'base/generic/'+testdir+'/test/'
1958 env.SConscript([path+'SConscript'],'env')
1959 testsrcs += [i.path for i in env['TESTSRCS_'+testdir.upper()]]
1960
1961 #print "TESTSRCS =",testsrcs
1962
1963 env.SConscript(['test/SConscript'],'env')
1964 env.SConscript(['base/generic/test/SConscript'],'env')
1965
1966 env.Alias('test',[env.Dir('test'),env.Dir('base/generic/test')])
1967
1968 else:
1969 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1970
1971 #-------------
1972 # EXTERNAL FUNCTIONS
1973
1974 env['extfns']=[]
1975 modeldirs = env.SConscript(['models/SConscript'],'env')
1976
1977 if not with_extfns:
1978 print "Skipping... External modules aren't being built:",without_extfns_reason
1979
1980 env.Alias('extfns',env['extfns'])
1981
1982 #------------------------------------------------------
1983 # CREATE ASCEND-CONFIG scriptlet
1984
1985 ascendconfig = env.SubstInFile('ascend-config.in')
1986
1987 #------------------------------------------------------
1988 # INSTALLATION
1989
1990 if env.get('CAN_INSTALL'):
1991
1992 dirs = ['INSTALL_BIN','INSTALL_ASCDATA','INSTALL_LIB', 'INSTALL_INCLUDE', 'INSTALL_DOC']
1993 install_dirs = [env.Entry(env['INSTALL_ROOT']+env[d]) for d in dirs]
1994 install_dirs += modeldirs
1995
1996 # TODO: add install options
1997 env.Alias('install',install_dirs)
1998
1999 env.InstallShared(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
2000
2001 env.InstallProgram(env['INSTALL_ROOT']+env['INSTALL_BIN'],ascendconfig)
2002
2003 #------------------------------------------------------
2004 # WINDOWS INSTALLER
2005 # For the windows installer, please see pygtk/SConscript
2006
2007 if with_installer:
2008 pass
2009 else:
2010 print "Skipping... Windows installer isn't being built:",without_installer_reason
2011
2012 #------------------------------------------------------
2013 # PROJECT FILE for MSVC
2014
2015 env.SConscript(['base/msvc/SConscript'],['env','libascend']);
2016
2017 #------------------------------------------------------
2018 # CREATE the SPEC file for generation of RPM packages
2019
2020 if platform.system()=="Linux":
2021 env.SubstInFile('ascend.spec.in')
2022
2023 #------------------------------------------------------
2024 # CREATE OMF FILE FOR USE WITH SCROLLKEEPER
2025
2026 if with_scrollkeeper:
2027 env.SubstInFile('#/pygtk/gnome/ascend.omf.in')
2028 env.InstallShared(env['INSTALL_ROOT']+env['OMFDIR'],"#/pygtk/gnome/ascend.omf")
2029
2030 #------------------------------------------------------
2031 # DISTRIBUTION TAR FILE
2032
2033 env['DISTTAR_FORMAT']='bz2'
2034 env.Append(
2035 DISTTAR_EXCLUDEEXTS=['.o','.os','.so','.a','.dll','.cc','.cache','.pyc','.cvsignore','.dblite','.log','.pl','.out']
2036 , DISTTAR_EXCLUDEDIRS=['CVS','.svn','.sconf_temp', 'dist']
2037 )
2038
2039 tar = env.DistTar("dist/"+env['DISTTAR_NAME']
2040 , [env.Dir('#')]
2041 )
2042
2043 env.Depends(tar,'ascend.spec')
2044
2045 Alias('dist',tar)
2046
2047 #------------------------------------------------------
2048 # USER'S MANUAL
2049
2050 env.SConscript('doc/SConscript',['env'])
2051
2052 #------------------------------------------------------
2053 # LIBASCEND DOXYGEN DOCUMENTATION
2054
2055 env.SConscript('base/doc/SConscript',['env'])
2056
2057 #------------------------------------------------------
2058 # RPM BUILD
2059
2060 # for RPM builds, 'scons dist' then 'rpmbuild -ta dist/ascend-*.tar.bz2'
2061 # (check * for the version number used to create the tarball)
2062
2063 #------------------------------------------------------
2064 # DEFAULT TARGETS
2065
2066 default_targets =['libascend']
2067 if with_tcltk:
2068 default_targets.append('tcltk')
2069 if with_python:
2070 default_targets.append('pygtk')
2071 if with_installer:
2072 default_targets.append('installer')
2073 if with_extfns:
2074 default_targets.append('extfns')
2075
2076 env.Default(default_targets)
2077
2078 print "Building targets:"," ".join([str(i) for i in BUILD_TARGETS])
2079
2080 # vim: set syntax=python:
2081

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