/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 993 - (show annotations) (download)
Fri Dec 22 11:03:51 2006 UTC (12 years, 11 months ago) by johnpye
File size: 49470 byte(s)
Added Matrix Market export routines (from math.nist.gov).
Added necessary build commands for above.
Work on Jacobi preconditioner for IDA (ongoing)
Set integrator_analye to make a call to slv_block_partition. Not sure if that's a good idea or not.
Tidied up comments in linsol.h
Moved unnecessary #defines from model_reorder.h into model_reorder.c.
Cleaned up codedocs in mtx*.h
Added WITH_MMIO config.h flag.

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

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