/[ascend]/branches/georgy/SConstruct
ViewVC logotype

Contents of /branches/georgy/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3129 - (show annotations) (download)
Sun Jun 26 21:19:06 2016 UTC (23 months, 3 weeks ago) by georgy
File size: 81151 byte(s)
Added initial code to specify and detect the Python executable.
1 #!/usr/bin/python invoke_using_scons
2 # This is a build script for use with SCons. Use it to compile ASCEND on
3 # Linux, Windows. It should also give some success on Mac, although this is
4 # much less tested.
5
6 # version number for this ASCEND build:
7 version = "0.9.10"
8
9 # shared library API numbering, for Linux (FIXME windows too?)
10 soname_major_int = "1"
11 soname_minor = ".0"
12
13 import sys, os, commands, platform, distutils.sysconfig, os.path, re, types
14 import subprocess
15
16 # version number for python, useful on Windows
17 pyversion = "%d.%d" % (sys.version_info[0],sys.version_info[1])
18
19 # architecture label
20 winarchtag = "-win32"
21 mingw64suff = ""
22 mingw64excpt ="_dw2"
23 if platform.architecture()[0] == "64bit":
24 winarchtag="-amd64"
25 mingw64suff = "_64"
26 mingw64excpt ="_seh"
27
28 import SCons.Warnings
29 SCons.Warnings.suppressWarningClass(SCons.Warnings.VisualCMissingWarning)
30
31 #------------------------------------------------------
32 # PLATFORM DEFAULTS
33
34 #print "PLATFORM = ",platform.system()
35
36 soname_major = "." + soname_major_int
37 default_install_prefix = '/usr/local'
38 default_install_bin = "$INSTALL_PREFIX/bin"
39 default_install_lib = "$INSTALL_PREFIX/lib"
40 default_install_models = "$INSTALL_LIB/ascend/models"
41 default_install_solvers = "$INSTALL_LIB/ascend/solvers"
42 default_install_assets = "$INSTALL_ASCDATA/glade/"
43 default_install_ascdata = "$INSTALL_SHARE/ascend"
44 default_install_include = "$INSTALL_PREFIX/include"
45 default_python=sys.executable
46 default_install_python = distutils.sysconfig.get_python_lib(plat_specific=1)
47 default_install_python_ascend = "$INSTALL_PYTHON/ascend"
48 default_tcl = '/usr'
49 default_tcl_libpath = "$TCL/lib"
50 default_tcl_cpppath = "$TCL/include"
51 default_conopt_envvar="CONOPT_PATH"
52 default_with_graphviz = True
53 default_tcl_lib = "tcl8.5"
54 default_tk_lib = "tk8.5"
55 default_tktable_lib = "Tktable2.9"
56 default_ida_prefix="$DEFAULT_PREFIX"
57 default_ipopt_libpath = "$IPOPT_PREFIX/lib"
58 default_ipopt_dll = ["$DEFAULT_PREFIX/bin/%s.dll"%i for i in ["libgfortran$MINGW64SUFF-3", "libstdc++$MINGW64SUFF-6","libquadmath$MINGW64SUFF-0","libgcc_s$MINGW64EXCPT$MINGW64SUFF-1"]]+[None] # should be five here
59 default_ipopt_libs = ["$F2C_LIB","blas","lapack","pthread","ipopt"]
60 default_conopt_prefix="$DEFAULT_PREFIX"
61 default_conopt_libpath="$CONOPT_PREFIX"
62 default_conopt_cpppath="$CONOPT_PREFIX"
63 default_conopt_dlpath="$CONOPT_PREFIX"
64 default_prefix="/usr"
65 default_libpath="$DEFAULT_PREFIX/lib"
66 default_cpppath="$DEFAULT_PREFIX/include"
67 default_f2c_lib="gfortran"
68 default_swig="swig"
69
70 icon_extension = '.png'
71
72 if platform.system()=="Windows":
73 try:
74 d = os.path.split(os.path.dirname(WhereIs("gcc.exe")))[0]
75 default_prefix=d
76 except:
77 default_prefix="c:\\mingw"
78
79 default_libpath="$DEFAULT_PREFIX\\lib"
80 default_cpppath="$DEFAULT_PREFIX\\include"
81
82 # these correspond the the version of Tcl/Tk linked to in the NSIS scripts
83 default_tcl_lib = "tcl85"
84 default_tk_lib = "tk85"
85 default_tktable_lib = "Tktable28"
86
87 # on windows, we locate explicitly in gtkbrowser.py:
88 default_install_assets = ""
89
90 default_tcl = "c:\\Tcl"
91 if os.environ.get('MSYSTEM'):
92 default_tcl_libpath="$TCL\\bin"
93 else:
94 default_tcl_libpath="$TCL\\lib"
95
96 # on Windows, we build ASCEND such that it finds it support files
97 # using paths relative to the location of the executable
98 default_absolute_paths = False
99 default_dist_rel_bin = '.'
100 default_tk_rel_dist = 'tcltk'
101 default_library_rel_dist = 'models'
102 default_solvers_rel_dist = 'solvers'
103
104 # where to look for IDA solver libraries, headers, etc.
105 default_ida_prefix = "$DEFAULT_PREFIX"
106
107 # IPOPT. we now prefer to build our own version.
108 default_ipopt_libs = ["ipopt",'stdc++','coinmumps','coinmetis','coinlapack','coinblas','gfortran','pthread']
109
110 # where to look for CONOPT when compiling
111 default_conopt_prefix = "c:\\Program Files\\CONOPT"
112 default_conopt_lib="conopt3"
113
114 need_libm = False
115 python_exe = sys.executable
116 default_with_scrollkeeper=False
117 pathsep = ";"
118
119 default_f2c_lib="gfortran"
120
121 default_swig=WhereIs("swig.exe")
122
123 soname_minor = ""
124 soname_major = ""
125 # still problems with Graphviz on Windows, leave it off now by default.
126
127 if not os.path.exists(default_conopt_prefix):
128 default_conopt_prefix = None
129
130 elif platform.system()=="Darwin":
131
132 default_install_prefix = ''
133 default_install_bin = "$INSTALL_PREFIX/ASCEND.app/Contents"
134 default_install_lib = "$INSTALL_BIN"
135 default_install_models = "$INSTALL_BIN/Models"
136 default_install_solvers = "$INSTALL_BIN/Solvers"
137 default_install_ascdata = "$INSTALL_BIN/Resources"
138 default_install_include = "$INSTALL_BIN/Headers"
139 default_install_python = "$INSTALL_BIN/Python"
140 default_install_python_ascend = default_install_python
141 default_install_assets = "$INSTALL_ASCDATA/glade/"
142 # FIXME still need to work out the Tcl/Tk side of things...
143
144 # within the bundle, we'll use relative paths
145 default_absolute_paths = False
146 default_dist_rel_bin = '.'
147 default_tk_rel_dist = 'tcltk'
148
149 # we should move these to /Library/ASCEND/Models and /Library/ASCEND/Solvers, for visibility
150 default_library_rel_dist = 'Models'
151 default_solvers_rel_dist = 'Solvers'
152
153 # where to look for CONOPT when compiling
154 default_conopt_prefix = "/Library/CONOPT"
155
156 default_conopt_lib="conopt3"
157
158 need_libm = False
159 python_exe = sys.executable
160 default_with_scrollkeeper=False
161 pathsep = ";"
162
163 if not os.path.exists(default_conopt_prefix):
164 default_conopt_prefix = None
165
166 else: # LINUX, unix we hope
167
168 # the scons 'philosophy' if there is one is that the scons input arguments
169 # completely determine what external tools get picked any time there might
170 # be choices.
171 # We don't follow that philosophy with regard to tcl/tk.
172 # tcl/tk are often in multiple versions and locations on any given system.
173 # This leaves us trying to guess whether we should take:
174 # - only explicit arguments, otherwise disable tcl, tk
175 # - the first tcl/tk in the users path
176 # - the tcl/tk under a given user-specified prefix
177 # - the folklore-based canonical location of distributor's tcl/tk on a given linux dist
178 # We know one thing for sure. Any tcl installation includes tclsh, and thus
179 # it's the canonical way to find anything about tcl once tclsh is picked.
180 # So all the above reduces to 'how do we find tclsh?'
181 icon_extension = '.svg'
182
183 # here's the folklore we know.
184 if os.path.exists("/etc/debian_version"):
185 default_tcl_cpppath = "/usr/include/tcl8.4"
186 default_tcl_lib = "tcl8.4"
187 default_tk_lib = "tk8.4"
188 default_tktable_lib = "Tktable2.8"
189
190 if os.path.exists("/etc/SuSE-release"):
191 default_tcl_cpppath = "/usr/include"
192 default_tcl_lib = "tcl8.4"
193 default_tk_lib = "tk8.4"
194 default_tktable_lib = "Tktable2.9"
195
196 if os.path.exists("/etc/lsb-release"):
197 _f = file("/etc/lsb-release")
198 _r = re.compile("([A-Z][^=]*)=(.*)")
199 LSB = {}
200 for l in _f:
201 _m = _r.match(l.strip())
202 LSB[_m.group(1)] = _m.group(2)
203 print LSB
204 if LSB.has_key('DISTRIB_ID') and LSB['DISTRIB_ID'] == "Ubuntu":
205 if float(LSB['DISTRIB_RELEASE']) >= 9.04:
206 default_tcl_lib = "tcl8.5"
207 default_tk_lib = "tk8.5"
208 default_tktable_lib = "Tktable2.9"
209 default_tcl_cpppath = "/usr/include/tcl8.5"
210 if not os.path.exists(default_tcl_cpppath):
211 default_tcl_lib = "tcl8.4"
212 default_tk_lib = "tk8.4"
213 default_tktable_lib = "Tktable2.9"
214 default_tcl_cpppath = "/usr/include/tcl8.4"
215
216 # centos 5
217 if os.path.exists("/etc/redhat-release"):
218 default_tcl_cpppath = "/usr/include"
219 default_tcl_lib = "tcl"
220 if sys.maxint > 2**32:
221 default_tcl_libpath = "/usr/lib64"
222 else:
223 default_tcl_libpath = "/usr/lib"
224 default_tk_lib = "tk"
225 default_tktable_lib = "Tktable2.9"
226
227
228 default_absolute_paths = True
229 default_dist_rel_bin = '..'
230 default_tk_rel_dist = 'share/ascend/tcltk'
231 default_library_rel_dist = 'lib/ascend/models'
232 default_solvers_rel_dist = 'lib/ascend/solvers'
233
234 default_conopt_libpath="$CONOPT_PREFIX/lib"
235 default_conopt_cpppath="$CONOPT_PREFIX/include"
236 default_conopt_dlpath= default_conopt_libpath + ":/usr/local/lib"
237 default_conopt_lib="consub3"
238
239 need_libm = True
240 if not os.path.isdir(default_tcl):
241 default_tcl = '/usr'
242 python_exe = distutils.sysconfig.EXEC_PREFIX+"/bin/python"
243 default_with_scrollkeeper=False
244 pathsep = ":"
245
246 if not os.path.exists(default_ida_prefix):
247 default_ida_prefix = None
248
249 soname_clean = "${SHLIBPREFIX}ascend${SHLIBSUFFIX}"
250 soname_full = "%s%s" % (soname_clean,soname_major)
251
252 #------------------------------------------------------
253 # OPTIONS
254 #
255 # The following give the set of command-line parameters that can be passed to
256 # SCons from the commandline. Options will be 'remembered' by being cached
257 # in the file 'options.cache'; if you want to start with a clean slate, you
258 # should remove that file.
259
260 vars = Variables(['options.cache', 'config.py'])
261
262 vars.Add('HOST_PREFIX'
263 ,"Host architecture prefix"
264 ,""
265 )
266
267 vars.Add('CC'
268 ,'C Compiler command'
269 ,"${HOST_PREFIX}gcc"
270 )
271
272 vars.Add('CXX'
273 ,'C++ Compiler command'
274 ,"${HOST_PREFIX}g++"
275 )
276
277 vars.Add(BoolVariable('GCOV'
278 , 'Whether to enable coverage testing in object code'
279 , False
280 ))
281
282 if platform.system()!="Windows":
283 vars.Add(BoolVariable('WITH_GCCVISIBILITY'
284 ,"Whether to use GCC Visibility features (only applicable if available)"
285 ,True
286 ))
287
288 vars.Add(BoolVariable('WITH_SIGNALS'
289 ,"Whether to permit use of signals for flow control in the C-level code"
290 ,True
291 ))
292
293 # You can turn off building of Tcl/Tk interface
294 vars.Add(BoolVariable('WITH_TCLTK'
295 ,"Set to False if you don't want to build the original Tcl/Tk GUI."
296 , True
297 ))
298
299 # You can turn off the building of the Python interface
300 vars.Add(BoolVariable('WITH_PYTHON'
301 ,"Set to False if you don't want to build Python wrappers."
302 , True
303 ))
304
305 # Which solvers will we allow?
306 vars.Add(ListVariable('WITH_SOLVERS'
307 ,"List of the solvers you want to build. The default is the minimum that"
308 +" works. The option 'LSOD' is provided for backwards compatibility"
309 +"; the value 'LSODE' is preferred."
310 ,["QRSLV","CMSLV","LSODE","IDA","CONOPT","LRSLV","IPOPT","DOPRI5"]
311 ,['QRSLV','MPS','SLV','OPTSQP'
312 ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
313 ,'LSODE','LSOD','OPTSQP',"IDA","TRON","IPOPT","DOPRI5","MAKEMPS","RADAU5"
314 ]
315 ))
316
317 # Where will the local copy of the help files be kept?
318 vars.Add(BoolVariable('WITH_DOC'
319 , "Should we try to build and install help files? If not, ASCEND will access online help files"
320 , True
321 ))
322
323 vars.Add(BoolVariable('WITH_DOC_BUILD'
324 , "If true, we'll attempt to build docs. Set false, we'll assume we already have then (eg from the tarball)"
325 , "$WITH_DOC"
326 ))
327
328 vars.Add(BoolVariable('WITH_DOC_INSTALL'
329 , "If true, SCons will install the documentation file(s). If false, assume rpm or dpkg is going to do it."
330 , "$WITH_DOC"
331 ))
332
333 vars.Add('HELP_ROOT'
334 , "Location of the main help file"
335 , "$INSTALL_DOC/book.pdf"
336 )
337
338 # Will bintoken support be enabled?
339 vars.Add(BoolVariable('WITH_BINTOKEN'
340 ,"Enable bintoken support? This means compiling models as C-code before"
341 +" running them, to increase solving speed for large models."
342 ,False
343 ))
344
345 # What should the default ASCENDLIBRARY path be?
346 # Note: users can change it by editing their ~/.ascend.ini
347 vars.Add('DEFAULT_ASCENDLIBRARY'
348 ,"Set the default value of the ASCENDLIBRARY -- the location where"
349 +" ASCEND will look for models when running ASCEND"
350 ,"$INSTALL_MODELS"
351 )
352
353 # What should the default ASCENDLIBRARY path be?
354 # Note: users can change it by editing their ~/.ascend.ini
355 vars.Add('DEFAULT_ASCENDSOLVERS'
356 ,"Set the default value of ASCENDSOLVERS -- the location where"
357 +" ASCEND will look for solver shared-library files"
358 ,"$INSTALL_SOLVERS"
359 )
360
361 # Where is SWIG?
362 vars.Add('SWIG'
363 ,"SWIG location, probably only required for MinGW and MSVC users."
364 +" Enter the location as a Windows-style path, for example"
365 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
366 ,default_swig
367 )
368
369 # Build the test suite?
370 vars.Add(BoolVariable('WITH_CUNIT'
371 ,"You can disable CUnit tests with this option. This will basically stop"
372 +" SCons from parsing the SConscript files relating to the 'test'"
373 +" target, which just might make things marginally faster. Probably"
374 +" you can just ignore this option though. SCons will sniff for Cunit"
375 +" but build the tests only if you specify the 'test' target."
376 ,True
377 ))
378
379 # Build with MMIO matrix export support?
380 vars.Add(BoolVariable('WITH_MMIO'
381 ,"Include support for exporting matrices in Matrix Market format"
382 ,True
383 ))
384
385 #----- default paths -----
386 vars.Add(PackageVariable('DEFAULT_PREFIX'
387 ,"Where are most of the shared libraries located on your system?"
388 ,default_prefix
389 ))
390
391 #------ cunit --------
392 # CUnit is a unit testing library that we use to test libascend.
393
394 # Where was CUNIT installed?
395 vars.Add(PackageVariable('CUNIT_PREFIX'
396 ,"Where are your CUnit files?"
397 ,"$DEFAULT_PREFIX"
398 ))
399
400 # Where are the CUnit includes?
401 vars.Add(PackageVariable('CUNIT_CPPPATH'
402 ,"Where are your CUnit include files?"
403 ,"$CUNIT_PREFIX/include"
404 ))
405
406 # Where are the CUnit libraries?
407 vars.Add(PackageVariable('CUNIT_LIBPATH'
408 ,"Where are your CUnit libraries?"
409 ,"$CUNIT_PREFIX/lib"
410 ))
411
412 # ----- conopt-----
413
414 vars.Add(PackageVariable("CONOPT_PREFIX"
415 ,"Prefix for your CONOPT install (CONOPT ./configure --prefix)"
416 ,default_conopt_prefix
417 ))
418
419 vars.Add("CONOPT_LIB"
420 ,"Library linked to for CONOPT. This is the name of the CONOPT .so or DLL. On Windows it seems to be called 'copopt3' but on linux it seems to be called 'consub3'."
421 ,default_conopt_lib
422 )
423
424 vars.Add(BoolVariable("CONOPT_LINKED"
425 ,"Do you want to dynamically link to CONOPT (only possible if CONOPT is available at buildtime)"
426 ,False
427 ))
428
429 vars.Add('CONOPT_CPPPATH'
430 ,"Where is your conopt.h?"
431 ,default_conopt_cpppath
432 )
433
434 vars.Add('CONOPT_LIBPATH'
435 ,"Where is your CONOPT library installed?"
436 ,default_conopt_libpath
437 )
438
439 vars.Add('CONOPT_DLPATH'
440 ,"Default (fallback) search path that ASCEND should use when dlopening the CONOPT library at runtime? This is only used if the conopt environment variable doesn't exist and doesn't point to a location where the DLL/SO is found. This is in platform-specific form (paths with ';' separator in Windows, ':' separator on Linux)."
441 ,default_conopt_dlpath
442 )
443
444 vars.Add('CONOPT_ENVVAR'
445 ,"Name of the optional environment variable which will be used for the value of the searchpath for the CONOPT DLL/SO."
446 ,default_conopt_envvar
447 )
448
449 #------- IPOPT -------
450
451 if platform.system()=="Windows":
452 vars.Add(PackageVariable("IPOPT_PREFIX"
453 ,"Prefix for your IPOPT install (IPOPT ./configure --prefix)"
454 ,default_conopt_prefix
455 ))
456
457 vars.Add("IPOPT_LIBS"
458 ,"Library linked to for IPOPT"
459 ,default_ipopt_libs
460 )
461
462 vars.Add("IPOPT_LIBPATH"
463 ,"Where is your IPOPT library installed"
464 ,default_ipopt_libpath
465 )
466
467 vars.Add('IPOPT_CPPPATH'
468 ,"Where is your IPOPT coin/IpStdCInterface.h (do not include the 'coin' in the path)"
469 ,"$IPOPT_PREFIX/include"
470 )
471
472 vars.Add('MINGW64SUFF'
473 ,"Suffix for 64-bit GCC-related DLLs for bundling with the installer"
474 ,mingw64suff
475 )
476
477 vars.Add('MINGW64EXCPT'
478 ,"Suffix to specify exception style for GCC-related DLLs to be bundled with the installer"
479 ,mingw64excpt
480 )
481
482 for i in range(5):
483 vars.Add('IPOPT_DLL%d'%(i+1)
484 ,"Exact path of IPOPT DLL (%d) to be included in the installer (Windows only)"%(i+1)
485 ,default_ipopt_dll[i]
486 )
487
488 #-------- f2c ------
489
490 vars.Add("F2C_LIB"
491 ,"F2C library (eg. g2c, gfortran, f2c)"
492 ,default_f2c_lib # the default is gfortran now
493 )
494
495 vars.Add(PackageVariable("F2C_LIBPATH"
496 ,"Directory containing F2C library (i.e. g2c, gfortran, f2c, etc.), if not already accessible"
497 ,"off"
498 ))
499
500 vars.Add("FORTRAN"
501 ,"Fortran compiler (eg g77, gfortran)"
502 ,"${HOST_PREFIX}gfortran"
503 )
504
505 vars.Add("SHFORTRAN"
506 ,"Fortran compiler for shared library object (should normally be same as FORTRAN)"
507 ,"$FORTRAN"
508 )
509
510 #------- Python --------
511
512 vars.Add('PYTHON'
513 ,"Location of the Python executable to which ASCEND should be linked"
514 ,default_python
515 )
516
517 #------- tcl/tk --------
518
519 vars.Add('TCL'
520 ,'Base of Tcl distribution'
521 ,default_tcl
522 )
523
524 # Where are the Tcl includes?
525 vars.Add('TCL_CPPPATH'
526 ,"Where are your Tcl include files?"
527 ,default_tcl_cpppath
528 )
529
530 # Where are the Tcl libs?
531 vars.Add('TCL_LIBPATH'
532 ,"Where are your Tcl libraries?"
533 ,default_tcl_libpath
534 )
535
536 # What is the name of the Tcl lib?
537 vars.Add('TCL_LIB'
538 ,"Name of Tcl lib (eg 'tcl' or 'tcl83'), for full path to static library (if STATIC_TCLTK is set)"
539 ,default_tcl_lib
540 )
541
542 # Where are the Tk includes?
543 vars.Add('TK_CPPPATH'
544 ,"Where are your Tk include files?"
545 ,'$TCL_CPPPATH'
546 )
547
548 # Where are the Tk libs?
549 vars.Add('TK_LIBPATH'
550 ,"Where are your Tk libraries?"
551 ,'$TCL_LIBPATH'
552 )
553
554 # What is the name of the Tk lib?
555 vars.Add('TK_LIB'
556 ,"Name of Tk lib (eg 'tk' or 'tk83'), or full path to static library"
557 ,default_tk_lib
558 )
559
560 # Static linking to TkTable
561
562 vars.Add(BoolVariable('STATIC_TCLTK'
563 ,'Set true for static linking for Tcl/Tk and TkTable. EXPERIMENTAL'
564 ,False
565 ))
566
567 vars.Add('TKTABLE_LIBPATH'
568 ,'Location of TkTable static library'
569 ,'$TCL_LIBPATH/Tktable2.8'
570 )
571
572 vars.Add('TKTABLE_LIB'
573 ,'Stem name of TkTable (eg tktable2.8, no ".so" or "lib") shared library, or full path of static tktable (/usr/lib/...)'
574 ,default_tktable_lib
575 )
576
577 vars.Add('TKTABLE_CPPPATH'
578 ,'Location of TkTable header file'
579 ,'$TCL_CPPPATH'
580 )
581
582 vars.Add('X11'
583 ,'Base X11 directory. Only used when STATIC_TCLTK is turned on. EXPERIMENTAL'
584 ,'/usr/X11R6'
585 )
586
587 vars.Add('X11_LIBPATH'
588 ,'Location of X11 lib. EXPERIMENTAL'
589 ,'$X11/lib'
590 )
591
592 vars.Add('X11_CPPPATH'
593 ,'Location of X11 includes. EXPERIMENTAL'
594 ,'$X11/include'
595 )
596
597 vars.Add('X11_LIB'
598 ,'Name of X11 lib. EXPERIMENTAL'
599 ,'X11'
600 )
601
602 #----- installed file locations (for 'scons install') -----
603
604 vars.Add('INSTALL_PREFIX'
605 ,'Root location for installed files'
606 ,default_install_prefix
607 )
608
609 vars.Add('INSTALL_BIN'
610 ,'Location to put binaries during installation'
611 ,default_install_bin
612 )
613
614 vars.Add('INSTALL_LIB'
615 ,'Location to put libraries during installation'
616 ,default_install_lib
617 )
618
619 vars.Add('INSTALL_SHARE'
620 ,'Common shared-file location on this system'
621 ,"$INSTALL_PREFIX/share"
622 )
623
624 vars.Add('INSTALL_ASCDATA'
625 ,"Location of ASCEND shared data (TK, python, models etc)"
626 ,default_install_ascdata
627 )
628
629 vars.Add('INSTALL_PYTHON'
630 ,'General location for Python extensions on this system'
631 ,default_install_python
632 )
633
634 vars.Add('INSTALL_PYTHON_ASCEND'
635 ,'Location for installation of Python modules specific to ASCEND'
636 ,default_install_python_ascend
637 )
638
639 vars.Add('INSTALL_TK'
640 ,'Location for Tcl/Tk files used by ASCEND Tk GUI'
641 ,"$INSTALL_ASCDATA/tcltk"
642 )
643
644 vars.Add('INSTALL_MODELS'
645 ,"Location of ASCEND model files (.a4c,.a4l,.a4s)"
646 ,default_install_models
647 )
648
649 vars.Add('INSTALL_SOLVERS'
650 ,"Location of ASCEND solvers"
651 ,default_install_solvers
652 )
653
654 vars.Add('INSTALL_DOC'
655 ,"Location of ASCEND documentation files"
656 ,"$INSTALL_SHARE/doc/ascend-"+version
657 )
658
659 vars.Add('INSTALL_INCLUDE'
660 ,'Location to put header files during installation'
661 ,default_install_include
662 )
663
664 vars.Add('INSTALL_ROOT'
665 ,'For use by RPM only: location of %{buildroot} during rpmbuild'
666 ,""
667 )
668
669 vars.Add('EXTLIB_SUFFIX'
670 ,"Filename suffix for ASCEND 'external libraries' (for use with IMPORT"
671 ,"_ascend$SHLIBSUFFIX"
672 )
673
674 vars.Add('EXTLIB_PREFIX'
675 ,"Filename suffix for ASCEND 'external libraries' (for use with IMPORT"
676 ,"$SHLIBPREFIX"
677 )
678
679 #----------------------
680
681 vars.Add('PYGTK_ASSETS'
682 ,'Default location for Glade assets (will be recorded in pygtk/config.py)'
683 ,default_install_assets
684 )
685
686 vars.Add(BoolVariable('DEBUG'
687 ,"Compile source with debugger symbols, eg for use with 'gdb'"
688 ,False
689 ))
690
691 vars.Add(BoolVariable('MALLOC_DEBUG'
692 ,"Compile with debugging version of MALLOC. Required for full CUnit testing"
693 ,False
694 ))
695
696 #------ dmalloc --------
697 vars.Add(PackageVariable('DMALLOC_PREFIX'
698 ,"Where are your dmalloc files?"
699 ,"$DEFAULT_PREFIX"
700 ))
701
702 vars.Add(PackageVariable('DMALLOC_CPPPATH'
703 ,"Where are your dmalloc include files?"
704 ,default_cpppath
705 ))
706
707 vars.Add(PackageVariable('DMALLOC_LIBPATH'
708 ,"Where are your dmalloc libraries?"
709 ,default_libpath
710 ))
711
712 vars.Add(BoolVariable('WITH_DMALLOC'
713 ,"Link to the DMALLOC library (if available) for debugging of memory usage."
714 ,False
715 ))
716
717 vars.Add(BoolVariable('WITH_GRAPHVIZ'
718 ,"Link to the GRAPHVIZ library (if available, for generating incidence graphs)"
719 ,default_with_graphviz
720 ))
721
722
723 #------ ufsparse --------
724 vars.Add(PackageVariable('UFSPARSE_PREFIX'
725 ,"Where are your UFSPARSE files?"
726 ,"$DEFAULT_PREFIX"
727 ))
728
729 vars.Add(PackageVariable('UFSPARSE_CPPPATH'
730 ,"Where are your UFSPARSE include files?"
731 ,default_cpppath
732 ))
733
734 vars.Add(PackageVariable('UFSPARSE_LIBPATH'
735 ,"Where are your UFSPARSE libraries?"
736 ,default_libpath
737 ))
738
739 vars.Add(BoolVariable('WITH_UFSPARSE'
740 ,"Link to the UFSPARSE library (if available, for additional sparse matrix routines)"
741 ,True
742 ))
743
744 #-----------------------
745
746 vars.Add(BoolVariable('UPDATE_NO_YACC_LEX'
747 ,"Update the *_no_yacc* and *_no_lex* files in the source tree? (these files are created so that ASCEND can be compiled in the absence of those tools)"
748 ,False
749 ))
750
751 vars.Add('DISTTAR_NAME'
752 ,"Stem name of the tarball created by 'scons dist'. So for 'ascend-aaa.tar.bz2', set this to 'ascend-aaa'."
753 ,"ascend-"+version
754 )
755
756 vars.Add('RELEASE'
757 ,"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."
758 ,"0"
759 )
760
761 vars.Add(BoolVariable('ABSOLUTE_PATHS'
762 ,"Whether to use absolute or relative paths in the installed Tcl/Tk interface. If you want to build an RPM, set this to false."
763 ,default_absolute_paths
764 ))
765
766 vars.Add('WIN_INSTALLER_NAME'
767 ,"Name of the installer .exe to create under Windows (minus the '.exe')"
768 ,"ascend-"+version+winarchtag+"-py"+pyversion+".exe"
769 )
770
771 vars.Add(BoolVariable('WITH_XTERM_COLORS'
772 ,"Set to 0 if you don't want xterm colour codes in the console output"
773 ,True
774 ))
775
776 vars.Add(BoolVariable('WITH_EXTFNS'
777 ,"Set to 0 if you don't want to attempt to build the external modules bundled with ASCEND"
778 ,True
779 ))
780
781 vars.Add(BoolVariable('WITH_SCROLLKEEPER'
782 ,"Set to to 1 if you want to install an OMF file that can be read by scrollkeeper (eg Yelp on GNOME)"
783 ,default_with_scrollkeeper
784 ))
785
786 vars.Add(BoolVariable('WITH_MSVCR71'
787 ,"Attempt to link against MSVCR71.DLL, to enable passing of FILE* objects to/from python"
788 ,False
789 ))
790
791
792 # TODO: OTHER OPTIONS?
793 # TODO: flags for optimisation
794 # TODO: turning on/off bintoken functionality
795 # TODO: Where will the 'Makefile.bt' file be installed?
796
797 # Import the outside environment
798
799 def c_escape(str):
800 return re.sub("\\\\","/",str)
801
802 envadditional={}
803
804 tools = [
805 'lex', 'yacc', 'fortran', 'swig', 'substinfile'
806 ,'disttar', 'tar', 'graphviz','sundials', 'dvi', 'pdflatex'
807 ]
808 if platform.system()=="Windows":
809 tools += ['nsis']
810
811 if os.environ.get('OSTYPE')=='msys' or os.environ.get('MSYSTEM'):
812 envenv = os.environ
813 tools += ['mingw']
814 envadditional['IS_MINGW']=True
815 else:
816 print "Assuming VC++ build environment (Note: MinGW is preferred)"
817 envenv = {
818 'PATH':os.environ['PATH']
819 ,'INCLUDE':os.environ['INCLUDE']
820 ,'LIB':os.environ['LIB']
821 ,'MSVS_IGNORE_IDE_PATHS':1
822 }
823 tools += ['default']
824 envadditional['CPPDEFINES']=['_CRT_SECURE_NO_DEPRECATE']
825 else:
826 envenv = os.environ
827 tools += ['default','doxygen','ipopt']
828
829 env = Environment(
830 ENV=envenv
831 , toolpath=['scons']
832 , tools=tools
833 , **envadditional
834 )
835
836 # Create .def files by default on Windows (or else SCons 2.0.1 never seems to be happy)
837 if platform.system()=="Windows":
838 env.Append(WINDOWS_INSERT_DEF=1)
839
840 #print "PATH =",os.environ['PATH']
841 #print "PROGSUFFIX =",env['PROGSUFFIX']
842 #print "CPPPATH =",env['CPPPATH']
843
844 vars.Update(env)
845
846 for l in ['SUNDIALS','IPOPT']:
847 var = "%s_LIBS" % l
848 if env.get(var) and not isinstance(env[var],types.ListType):
849 env[var] = env[var].split(",")
850
851 if 'LSOD' in env['WITH_SOLVERS']:
852 if 'LSODE' not in env['WITH_SOLVERS']:
853 env['WITH_SOLVERS'].append('LSODE')
854 env['WITH_SOLVERS'].remove('LSOD')
855
856 vars.Save('options.cache',env)
857
858 Help(vars.GenerateHelpText(env))
859
860 if env['ENV'].get('HOST_PREFIX'):
861 triplet = re.compile("^[a-z0-9_]+-[a-z0-9_]+-[a-z0-9]+$")
862 if not triplet.match(env['ENV']['HOST_PREFIX']):
863 print "NOTE: invalid host triplet from environment variable HOST_PREFIX has been ignored"
864 else:
865 print "NOTE: using HOST_PREFIX=%s from environment to override HOST_PREFIX SCons variable" % env['ENV']['HOST_PREFIX']
866 env['HOST_PREFIX'] = env['ENV']['HOST_PREFIX']+"-"
867
868 with_tcltk = env.get('WITH_TCLTK')
869 without_tcltk_reason = "disabled by options/config.py"
870
871 with_python = env.get('WITH_PYTHON')
872 without_python_reason = "disabled by options/config.py"
873
874 with_cunit = env.get('WITH_CUNIT')
875 without_cunit_reason = "not requested"
876
877 with_extfns = env.get('WITH_EXTFNS')
878 without_extfn_reason = "disabled by options/config.py"
879
880 with_scrollkeeper = env.get('WITH_SCROLLKEEPER')
881 without_scrollkeeper_reason = "disabled by options/config.py"
882
883 with_dmalloc = env.get('WITH_DMALLOC')
884 without_dmalloc_reason = "disabled by options/config.py"
885
886 with_graphviz = env.get('WITH_GRAPHVIZ')
887 without_graphiviz_reason = "disabled by options/config.py"
888
889 with_ufsparse = env.get('WITH_UFSPARSE')
890 without_ufsparse_reason = "disabled by options/config.py"
891
892 with_mmio = env.get('WITH_MMIO')
893 without_mmio_reason = "disabled by options/config.py"
894
895 with_signals = env.get('WITH_SIGNALS')
896 without_signals_reason = "disabled by options/config.py"
897
898 with_doc = env.get('WITH_DOC')
899
900 with_doc_build = env.get('WITH_DOC_BUILD');
901 without_doc_build_reason = "disabled by options/config.py"
902 if not with_doc:
903 with_doc_build = False
904 without_doc_build_reason = "disabled by with_doc"
905
906 with_latex2html = False
907
908 if platform.system()=="Windows":
909 with_installer=1
910 else:
911 with_installer=0
912 without_installer_reason = "only possible under Windows"
913
914 notselected = "Not selected (see config option WITH_SOLVERS)"
915
916 with_lsode = 'LSODE' in env['WITH_SOLVERS']
917 without_lsode_reason = notselected
918
919 with_ida = 'IDA' in env['WITH_SOLVERS']
920 without_ida_reason = notselected
921
922 with_dopri5 = 'DOPRI5' in env['WITH_SOLVERS']
923 without_dopri5_reason = notselected
924
925 with_radau5 = 'RADAU5' in env['WITH_SOLVERS']
926 without_radau5_reason = notselected
927
928 with_conopt = 'CONOPT' in env['WITH_SOLVERS']
929 without_conopt_reason = notselected
930
931 with_ipopt = 'IPOPT' in env['WITH_SOLVERS']
932 without_ipopt_reason = notselected
933
934 with_makemps = 'MAKEMPS' in env['WITH_SOLVERS']
935 without_makemps_reason = notselected
936
937
938 #print "SOLVERS:",env['WITH_SOLVERS']
939 #print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
940 #print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
941
942 can_install = True
943 if platform.system()=='Windows':
944 can_install = False
945
946 env['CAN_INSTALL']=can_install
947
948 #print "TCL=",env['TCL']
949 #print "TCL_CPPPATH =",env['TCL_CPPPATH']
950 #print "TCL_LIBPATH =",env['TCL_LIBPATH']
951 #print "TCL_LIB =",env['TCL_LIB']
952
953 #print "ABSOLUTE PATHS =",env['ABSOLUTE_PATHS']
954 #print "INSTALL_ASCDATA =",env['INSTALL_ASCDATA']
955 #print "INSTALL_PREFIX =",env['INSTALL_PREFIX']
956 #print "INSTALL_MODELS =",env['INSTALL_MODELS']
957 #print "INSTALL_SOLVERS =",env['INSTALL_SOLVERS']
958 #print "INSTALL_PYTHON =",env['INSTALL_PYTHON']
959 #print "INSTALL_PYTHON_ASCEND =",env['INSTALL_PYTHON_ASCEND']
960 #print "DEFAULT_ASCENDLIBRARY =",env['DEFAULT_ASCENDLIBRARY']
961 #print "DEFAULT_ASCENDSOLVERS =",env['DEFAULT_ASCENDSOLVERS']
962
963
964 #------------------------------------------------------
965 # SPECIAL CONFIGURATION TESTS
966
967 need_fortran = False
968 need_fortran_reasons = []
969
970 #----------------
971 # CC
972
973 cc_test_text = """
974 int main(void){
975 return 0;
976 }
977 """;
978
979 def CheckCC(context):
980 context.Message("Checking C compiler ('%s')... " % context.env.subst('$CC'))
981 is_ok = context.TryCompile(cc_test_text,".c")
982 context.Result(is_ok)
983 return is_ok
984
985 #----------------
986 # CXX
987
988 cxx_test_text = """
989 template<class X>
990 class pair{
991 public:
992 X a;
993 X b;
994 };
995
996 int main(void){
997 pair<double> P;
998 P.a = 0;
999 return 0;
1000 }
1001 """;
1002
1003 def CheckCXX(context):
1004 context.Message("Checking C++ compiler ('%s')... " % context.env.subst('$CXX'))
1005 if not context.env.get('CXX'):
1006 context.Result("not found")
1007 return False
1008 is_ok = context.TryCompile(cxx_test_text,".cpp")
1009 context.Result(is_ok)
1010 return is_ok
1011
1012 #----------------
1013
1014 f77_test_text = """
1015 C Hello World in Fortran 77
1016
1017 PROGRAM HELLO
1018 PRINT*, 'Hello World!'
1019 END
1020 """;
1021
1022 def CheckFortran(context):
1023 context.Message("Checking Fortran compiler ('%s')..." % context.env.subst('$FORTRAN'))
1024 if not context.env.get('FORTRAN'):
1025 context.Result('not found')
1026 return False
1027 is_ok = context.TryCompile(f77_test_text,".f")
1028 context.Result(is_ok)
1029 return is_ok
1030
1031 #----------------
1032 # Address Sanitizer
1033
1034 asan_test_text = """
1035 #if !defined(__has_feature)
1036 # error "__has_feature" not defined"
1037 #else
1038 # if !__has_feature(address_sanitizer)
1039 # error "address_sanitizer is not available"
1040 # endif
1041 #endif
1042 int main(void){
1043 return 0;
1044 }
1045 """
1046
1047 def CheckASan(context):
1048 context.Message("Checking for AddressSanitizer... ")
1049 ccf = context.env.get('CCFLAGS')
1050 context.env.AppendUnique(CCFLAGS=['-O1','-g','-fsanitize=address','-fno-omit-frame-pointer'])
1051 is_ok = context.TryCompile(asan_test_text,".c")
1052 context.Result(is_ok)
1053 if ccf is None:
1054 del context.env['CCFLAGS']
1055 else:
1056 context.env['CCFLAGS'] = ccf
1057 return is_ok
1058
1059 #----------------
1060 # SWIG
1061
1062 import os,re
1063
1064 def get_swig_version(env):
1065 if not WhereIs(env['SWIG']):
1066 raise RuntimeError("'%s' not found in PATH"%env.subst("$SWIG"))
1067 cmd = [env['SWIG'],'-version']
1068 p = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1069 output, err = p.communicate()
1070
1071 restr = r"\s*SWIG\s+Version\s+(?P<maj>[0-9]+)\.(?P<min>[0-9]+)\.(?P<pat>[0-9]+)\b"
1072 expr = re.compile(restr,re.MULTILINE|re.IGNORECASE);
1073 m = expr.match(output);
1074 if not m:
1075 raise RuntimeError("Failed match on output '%s'" % output)
1076 maj = int(m.group('maj'))
1077 min = int(m.group('min'))
1078 pat = int(m.group('pat'))
1079
1080 return (maj,min,pat)
1081
1082
1083 def CheckSwigVersion(context):
1084
1085 try:
1086 context.Message("Checking version of SWIG... ")
1087 maj,min,pat = get_swig_version(context.env)
1088 except Exception,e:
1089 context.Result("Failed (%s)" % str(e))
1090 return False;
1091
1092 context.env['SWIGVERSION']=tuple([maj,min,pat])
1093
1094 msg = "too old"
1095 res = False
1096 if maj == 1 and (
1097 min > 3
1098 or (min == 3 and pat >= 24)
1099 ):
1100 msg = "ok"
1101 res = True
1102 elif maj == 2 or maj==3:
1103 msg = "ok"
1104 res = True
1105
1106 context.Result("%s, %d.%d.%d" % (msg, maj,min,pat))
1107 return res;
1108
1109 #----------------
1110 # Scrollkeeper (Linux documentation system)
1111
1112 def get_scrollkeeper_omfdir(env):
1113 cmd = ['scrollkeeper-config','--omfdir']
1114 p = subprocess.Popen(cmd,stdout=subprocess.PIPE)
1115 output = p.communicate()
1116 return output.strip()
1117
1118 def CheckScrollkeeperConfig(context):
1119 try:
1120 context.Message("Checking for scrollkeeper...")
1121 dir=get_scrollkeeper_omfdir(context.env)
1122 except:
1123 context.Result("Failed to run 'scrollkeeper-config'")
1124 return 0
1125 context.env['OMFDIR']=dir
1126 context.Result("OK, %s" % dir)
1127 return 1
1128
1129 #----------------
1130 # General purpose library-and-header test
1131
1132 class KeepContext:
1133 def __init__(self,context,varprefix,static=False):
1134 self.keep = {}
1135 for k in ['LIBS','LIBPATH','CPPPATH','LINKFLAGS']:
1136 #print "Keeping env %s = %s" % (k,context.env.get(k))
1137 self.keep[k]=context.env.get(k)
1138
1139 if context.env.has_key(varprefix+'_CPPPATH'):
1140 context.env.AppendUnique(CPPPATH=[env[varprefix+'_CPPPATH']])
1141 #print "Adding '"+str(env[varprefix+'_CPPPATH'])+"' to cpp path"
1142
1143 if static:
1144 staticlib=env[varprefix+'_LIB']
1145 #print "STATIC LIB = ",staticlib
1146 context.env.Append(
1147 LINKFLAGS=[staticlib]
1148 )
1149 else:
1150 if context.env.has_key(varprefix+'_LIBPATH'):
1151 context.env.Append(LIBPATH=[env[varprefix+'_LIBPATH']])
1152 #print "Adding '"+str(env[varprefix+'_LIBPATH'])+"' to lib path"
1153
1154 if context.env.has_key(varprefix+'_LIB'):
1155 context.env.Append(LIBS=[env[varprefix+'_LIB']])
1156 #print "Adding '"+str(env[varprefix+'_LIB'])+"' to libs"
1157 elif context.env.has_key(varprefix+'_LIBS'):
1158 context.env.AppendUnique(LIBS=env[varprefix+'_LIBS'])
1159
1160 def restore(self,context):
1161 #print "RESTORING CONTEXT"
1162 #print self.keep
1163 #print "..."
1164 for k in self.keep:
1165 if self.keep[k]==None:
1166 if context.env.has_key(k):
1167 #print "Clearing "+str(k)
1168 del context.env[k];
1169 else:
1170 #print "Restoring %s to '%s'" %(k,self.keep.get(k))
1171 context.env[k]=self.keep[k];
1172
1173 def CheckExtLib(context,libname,text,ext='.c',varprefix=None,static=False,testname=None):
1174 """This method will check for variables LIBNAME_LIBPATH
1175 and LIBNAME_CPPPATH and try to compile and link the
1176 file with the provided text, linking with the
1177 library libname."""
1178
1179 if testname is None:
1180 testname = libname
1181
1182 if static:
1183 context.Message( 'Checking for static '+testname+'... ' )
1184 else:
1185 context.Message( 'Checking for '+testname+'... ' )
1186
1187 if varprefix==None:
1188 if not isinstance(libname,str):
1189 raise RuntimeError("varprefix must be provided, as libname is not a string")
1190 varprefix = libname.upper()
1191
1192 #print "LIBS is currently:",context.env.get('LIBS')
1193 keep = KeepContext(context,varprefix,static)
1194
1195 if not context.env.has_key(varprefix+'_LIB') and not context.env.has_key(varprefix+'_LIBS'):
1196 # if varprefix_LIB were in env, KeepContext would
1197 # have appended it already
1198 if isinstance(libname,str):
1199 context.env.Append(LIBS=[libname])
1200 else:
1201 context.env.Append(LIBS=libname)
1202
1203 is_ok = context.TryLink(text,ext)
1204
1205 #print "Link success? ",(is_ok != 0)
1206
1207 keep.restore(context)
1208
1209 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
1210 # print "Restored LIBS="+str(context.env['LIBS'])
1211 # print "Restored LIBPATH="+str(context.env['LIBPATH'])
1212
1213 context.Result(is_ok)
1214 return is_ok
1215
1216 #----------------
1217 # GCC
1218
1219 gcc_test_text = """
1220 #ifndef __GNUC__
1221 # error "Not using GCC"
1222 #endif
1223
1224 int main(void){
1225 return __GNUC__;
1226 }
1227 """
1228
1229 def CheckGcc(context):
1230 context.Message("Checking for GCC... ")
1231 is_ok = context.TryCompile(gcc_test_text,".c")
1232 context.Result(is_ok)
1233 return is_ok
1234
1235 #----------------
1236 # GCC VISIBILITY feature
1237
1238 gccvisibility_test_text = """
1239 #if __GNUC__ < 4
1240 # error "Require GCC version 4 or newer"
1241 #endif
1242
1243 __attribute__ ((visibility("default"))) int x;
1244
1245 int main(void){
1246 extern int x;
1247 x = 4;
1248 }
1249 """
1250
1251 def CheckGccVisibility(context):
1252 context.Message("Checking for GCC 'visibility' capability... ")
1253 if not context.env.has_key('WITH_GCCVISIBILITY') or not env['WITH_GCCVISIBILITY']:
1254 context.Result("disabled")
1255 return 0
1256 is_ok = context.TryCompile(gccvisibility_test_text,".c")
1257 context.Result(is_ok)
1258 return is_ok
1259
1260 #----------------
1261 # YACC
1262
1263 yacc_test_text = """
1264 %{
1265 #include <stdio.h>
1266
1267 /* MSVC++ needs this before it can swallow Bison output */
1268 #ifdef _MSC_VER
1269 # define __STDC__
1270 #endif
1271 %}
1272 %token MSG
1273 %start ROOT
1274 %%
1275 ROOT:
1276 MSG { printf("HELLO"); }
1277 ;
1278 %%
1279 """
1280
1281 def CheckYacc(context):
1282 context.Message("Checking for Yacc ('%s')... " % context.env.get('YACC'))
1283 is_ok = context.TryCompile(yacc_test_text,".y")
1284 context.Result(is_ok)
1285 return is_ok
1286
1287 #----------------
1288 # LEX
1289
1290 lex_test_text = """
1291 %{
1292 #include <stdio.h>
1293 %}
1294 DIGIT [0-9]
1295 ID [a-z][a-z0-9]*
1296 %%
1297 {DIGIT}+ {
1298 printf("A digit: %s\\n",yytext);
1299 }
1300
1301 [ \\t\\n]+ /* ignore */
1302
1303 . {
1304 printf("Unrecognized guff");
1305 }
1306 %%
1307 main(){
1308 yylex();
1309 }
1310 """
1311
1312 def CheckLex(context):
1313 context.Message("Checking for Lex ('%s')... " % context.env.get('LEX'))
1314 is_ok = context.TryCompile(lex_test_text,".l")
1315 context.Result(is_ok)
1316 return is_ok
1317
1318 lexdestroy_test_text = """
1319 %{
1320 #include <stdio.h>
1321 #include <unistd.h>
1322 %}
1323
1324 %%
1325 username printf("%s", getlogin());
1326 %%
1327
1328 int yywrap(void){
1329 return 1;
1330 }
1331
1332 main(){
1333 //yylex();
1334 yylex_destroy();
1335 }
1336
1337 """
1338
1339 def CheckLexDestroy(context):
1340 context.Message("Checking for yylex_destroy... ")
1341 is_ok, outstring = context.TryRun(lexdestroy_test_text,".l")
1342 context.Result(is_ok)
1343 return is_ok
1344
1345 #----------------
1346 # CUnit test
1347
1348 cunit_test_text = """
1349 #include <CUnit/CUnit.h>
1350 int maxi(int i1, int i2){
1351 return (i1 > i2) ? i1 : i2;
1352 }
1353
1354 void test_maxi(void){
1355 CU_ASSERT(maxi(0,2) == 2);
1356 CU_ASSERT(maxi(0,-2) == 0);
1357 CU_ASSERT(maxi(2,2) == 2);
1358
1359 }
1360 int main(void){
1361 /* CU_initialize_registry() */
1362 return 0;
1363 }
1364 """
1365
1366 def CheckCUnit(context):
1367 return CheckExtLib(context,'cunit',cunit_test_text)
1368
1369 #----------------
1370 # dmalloc test
1371
1372 dmalloc_test_text = """
1373 #include <stdlib.h>
1374 #include <dmalloc.h>
1375
1376 int main(void){
1377 char *c;
1378 c = (char *)malloc(100*sizeof(char));
1379 free(c);
1380 return 0;
1381 }
1382 """
1383
1384 def CheckDMalloc(context):
1385 return CheckExtLib(context,'dmalloc',dmalloc_test_text)
1386
1387 #----------------
1388 # graphviz test
1389
1390 # test graphviz agraph...
1391 graphviz_agraph_test_text = """
1392 #ifdef __WIN32__
1393 # include <gvc.h>
1394 #else
1395 # include <graphviz/gvc.h>
1396 #endif
1397 #ifdef WITH_CGRAPH
1398 # error WITH_CGRAPH is defined!
1399 #endif
1400 int main(void){
1401 Agraph_t *g;
1402 g = agopen("g", AGDIGRAPH);
1403 return 0;
1404 }
1405 """
1406 def CheckGraphVizAgraph(context):
1407 return CheckExtLib(context,'gvc',graphviz_agraph_test_text,ext=".c",varprefix="GRAPHVIZ",testname="graphviz agraph")
1408
1409 # test graphviz cgraph
1410 graphviz_cgraph_test_text = """
1411 #ifdef __WIN32__
1412 # include <gvc.h>
1413 #else
1414 # include <graphviz/cgraph.h>
1415 # include <graphviz/gvc.h>
1416 #endif
1417 int main(void){
1418 Agraph_t *g;
1419 GVC_t *gvc;
1420 gvc = gvContext();
1421 g = agopen("g", Agdirected, 0);
1422 return 0;
1423 }
1424 """
1425 def CheckGraphVizCgraph(context):
1426 return CheckExtLib(context,['gvc','cgraph'],graphviz_cgraph_test_text,ext=".c",varprefix="GRAPHVIZ",testname="graphviz cgraph")
1427
1428 # GVC_t *gvc;
1429 # gvc = gvContext();
1430
1431 # test for definition of 'boolean' in graphviz/types.h
1432 graphviz_boolean_test = """
1433 #ifdef __WIN32__
1434 # include <types.h>
1435 #else
1436 # include <graphviz/types.h>
1437 #endif
1438 #ifndef GV_TYPES_H
1439 # error WHERE IS GV_TYPES_H?
1440 #endif
1441 int main(void){
1442 boolean x;
1443 x = TRUE;
1444 return 0;
1445 }
1446 """
1447 def CheckGraphVizBoolean(context):
1448 return CheckExtLib(context,'graphviz',graphviz_boolean_test,ext=".c" \
1449 ,testname="graphviz 'boolean' definition"
1450 )
1451
1452 #----------------
1453 # ufsparse test
1454
1455 ufsparse_test_text = """
1456 #include <ufsparse/cs.h>
1457 int main(void){
1458 cs *A,*B,*C;
1459 C = cs_multiply(A,B);
1460 return 0;
1461 }
1462 """
1463
1464 def CheckUFSparse(context):
1465 return CheckExtLib(context
1466 ,libname='cxsparse'
1467 ,varprefix='ufsparse'
1468 ,text=ufsparse_test_text
1469 ,ext=".c"
1470 )
1471
1472 #----------------
1473 # MATH test
1474
1475 math_test_text = """
1476 #ifndef _ALL_SOURCE
1477 # define _ALL_SOURCE
1478 #endif
1479 #ifndef _XOPEN_SOURCE
1480 # define _XOPEN_SOURCE
1481 #endif
1482 #ifndef _XOPEN_SOURCE_EXTENDED
1483 # define _XOPEN_SOURCE_EXTENDED 1
1484 #endif
1485 #include <math.h>
1486 int main(void){
1487 double x = 1.0; double y = 1.0; int i = 1;
1488 acosh(x); asinh(x); atanh(x); cbrt(x); expm1(x); erf(x); erfc(x); isnan(x);
1489 j0(x); j1(x); jn(i,x); ilogb(x); logb(x); log1p(x); rint(x);
1490 y0(x); y1(x); yn(i,x);
1491 /* this part causes problems with crossmingw... */
1492 #ifdef _THREAD_SAFE
1493 gamma_r(x,&i);
1494 lgamma_r(x,&i);
1495 #else
1496 gamma(x);
1497 lgamma(x);
1498 #endif
1499 hypot(x,y); nextafter(x,y); remainder(x,y); scalb(x,y);
1500 return 0;
1501 }
1502 """
1503
1504 def CheckMath(context):
1505 context.Message('Checking for IEEE math library... ')
1506 libsave=context.env.get('LIBS');
1507 context.env.AppendUnique(LIBS=['m'])
1508 is_ok=context.TryLink(math_test_text,".c")
1509 context.Result(is_ok)
1510 if libsave is None:
1511 del(context.env['LIBS'])
1512 else:
1513 context.env['LIBS']=libsave
1514 return is_ok
1515
1516 #----------------
1517 # malloc.h test
1518
1519 malloc_test_text = """
1520 #include <stdlib.h>
1521 int main(){
1522 double *x;
1523 x = malloc(sizeof(double)*5);
1524 x[4] = 3.3;
1525 free(x);
1526 }
1527 """
1528
1529 def CheckMalloc(context):
1530 context.Message("Checking for malloc...")
1531 is_ok = context.TryLink(malloc_test_text,".c")
1532 context.Result(is_ok)
1533 return is_ok
1534
1535 #----------------
1536 # dlopen test
1537
1538 dlopen_test_text = """
1539 #ifdef __WIN32__
1540 # include <windows.h>
1541 #else
1542 # include <dlfcn.h>
1543 #endif
1544 int main(){
1545 #ifdef __WIN32__
1546 HINSTANCE d;
1547 LoadLibrary("imaginary_and_nonexistent.dll");
1548 #else
1549 void *d;
1550 d = dlopen("imaginary_and_nonexistent.so", 1);
1551 #endif
1552 return 0;
1553 }
1554 """
1555
1556 def CheckDLOpen(context):
1557 context.Message("Checking for ability to load shared libraries at runtime...")
1558 libsave=context.env.get('LIBS');
1559 if platform.system()!="Windows":
1560 context.env.Append(LIBS=['dl'])
1561 is_ok = context.TryLink(dlopen_test_text,".c")
1562 context.Result(is_ok)
1563 context.env['LIBS'] = libsave
1564 return is_ok
1565
1566 #----------------
1567 # libpython test
1568
1569 libpython_test_text = """
1570 #include <Python.h>
1571 PyObject *get10(void){
1572 PyObject *p = Py_BuildValue("i", 10);
1573 return p;
1574 }
1575 int main(void){
1576 return 0;
1577 }
1578 """
1579
1580 def pythoncall(env,expr1):
1581 """
1582 Evaluate a Python string, using the version of Python specified
1583 """
1584 import subprocess
1585 import os
1586 fn = "scons%d" % os.getpid()
1587 while os.path.exists(fn):
1588 fn = fn + "0"
1589 try:
1590 f = file(fn,"w")
1591 f.write("#!python\nimport sys\nprint sys.argv[1]")
1592 f.close()
1593 p1 = subprocess.Popen(
1594 ["sh.exe","-c","%s -c \"%s\""%(env['PYTHON'],expr1,)]
1595 ,stdout=subprocess.PIPE
1596 )
1597 out = p1.communicate()[0].strip()
1598 except Exception,e:
1599 print "FAILED: %s"%str(e)
1600 finally:
1601 os.unlink(fn)
1602 return out
1603
1604
1605 def CheckPythonLib(context):
1606 context.Message('Checking for libpython... ')
1607
1608 if 0 and context.env['PYTHON'] is not None:
1609 # get the parameters by running a specified python executable
1610 context.Result("PYTHON specified; not yet implemented")
1611 else:
1612 # get the parameter from this python that is powering SCons
1613 python_cpppath = [distutils.sysconfig.get_python_inc()]
1614 python_h = os.path.join(python_cpppath[0],"python.h")
1615 v = distutils.sysconfig.get_config_vars()
1616 python_lib = "python%s"%v['VERSION']
1617 if sys.platform=="win32":
1618 # 'native' win32 is a special case for library name and location
1619 python_so = "python%s%s"%(v['VERSION'],context.env.get('SHLIBSUFFIX'))
1620 python_libpath = [os.oath.join(sys.prefix,"Libs")]
1621 else:
1622 python_so = v['INSTSONAME']
1623 python_libpath = [v['LIBDIR']]
1624 python_cpppath += [v['INCLUDEDIR']]
1625
1626 # TODO restore settings for Darwin here... LIBPL and LIBS
1627
1628 # check that header and library files were found
1629 if not os.path.exists(python_h):
1630 context.Result("'python.h' not found.")
1631 if not os.path.exists(os.path.join(python_libpath[0],python_so)):
1632 context.Results("'%s' not found."%python_so)
1633
1634 context.env['PYTHON_LIBS']=[python_lib]
1635 context.env['PYTHON_LIBPATH']=python_libpath
1636 context.env['PYTHON_CPPPATH']=python_cpppath
1637 context.env['PYTHON_LIBFLAGS']=[]
1638
1639 # check that we can link against the python library
1640 return CheckExtLib(context,python_lib,libpython_test_text,varprefix="PYTHON")
1641
1642 if 0:
1643 if sys.platform=="msys":
1644 print "\nsys.executable",sys.executable
1645 print "PYTHON =",env['PYTHON']
1646 print "PYTHON sys.executable",pythoncall(env,"import sys;print sys.executable")
1647 print "PYTHON get_python_inc()",pythoncall(env,"import distutils.sysconfig as d;print d.get_python_inc()")
1648 print "PYTHON LIBDIR",pythoncall(env,"import distutils.sysconfig as d;print d.get_config_vars()['LIBDIR']")
1649 print "PYTHON LDLIBRARY",pythoncall(env,"import distutils.sysconfig as d;print d.get_config_vars()['LDLIBRARY']")
1650
1651 python_lib='python%d.%d'
1652 if sys.platform=="win32":
1653 python_lib='python%d%d'
1654 try:
1655 python_libs = [python_lib % (sys.version_info[0],sys.version_info[1])]
1656 python_cpppath = [distutils.sysconfig.get_python_inc()]
1657 cfig = distutils.sysconfig.get_config_vars()
1658 except:
1659 context.Result("not found")
1660 return 0
1661
1662 lastLIBS = context.env.get('LIBS')
1663 lastLIBPATH = context.env.get('LIBPATH')
1664 lastCPPPATH = context.env.get('CPPPATH')
1665 lastLINKFLAGS = context.env.get('LINKFLAGS')
1666
1667 python_libpath = []
1668 python_linkflags = []
1669 if sys.platform=="win32":
1670 python_libpath += [os.path.join(sys.prefix,"libs")]
1671 elif sys.platform=="msys2":
1672 python_libpath += pythoncall(env,
1673 "import distutils.sysconfig as d;print d.get_config_vars()['LIBDIR']")
1674 print
1675 elif platform.system()=="Darwin":
1676 python_libpath += [cfig['LIBPL']]
1677 python_linkflags += cfig['LIBS'].split(' ')
1678 else:
1679 # checked on Linux and SunOS
1680 if cfig['LDLIBRARY']==cfig['LIBRARY']:
1681 sys.stdout.write("(static)")
1682 python_libpath += [cfig['LIBPL']]
1683 python_linkflags += cfig['LIBS'].split(' ')
1684
1685 context.env.AppendUnique(LIBS=python_libs)
1686 context.env.AppendUnique(LIBPATH=python_libpath)
1687 context.env.AppendUnique(CPPPATH=python_cpppath)
1688 context.env.AppendUnique(LINKFLAGS=python_linkflags)
1689 result = context.TryLink(libpython_test_text,".c");
1690
1691 context.Result(result)
1692
1693 if(result):
1694 context.env['PYTHON_LIBPATH']=python_libpath
1695 context.env['PYTHON_LIB']=python_libs
1696 context.env['PYTHON_CPPPATH']=python_cpppath
1697 context.env['PYTHON_LINKFLAGS']=python_linkflags
1698
1699 context.env['LIBS'] = lastLIBS
1700 context.env['LIBPATH'] = lastLIBPATH
1701 context.env['CPPPATH'] = lastCPPPATH
1702 context.env['LINKFLAGS'] = lastLINKFLAGS
1703
1704 return result
1705
1706 #----------------
1707 # IDA test
1708
1709 sundials_version_major_required = 2
1710 sundials_version_minor_min = 4
1711 sundials_version_minor_max = 4
1712
1713 sundials_version_text = """
1714 #include <sundials/sundials_config.h>
1715 #include <stdio.h>
1716 int main(){
1717 printf("%s",SUNDIALS_PACKAGE_VERSION);
1718 return 0;
1719 }
1720 """
1721
1722 ida_test_text = """
1723 #if SUNDIALS_VERSION_MAJOR==2 && SUNDIALS_VERSION_MINOR==2
1724 # include <sundials/sundials_config.h>
1725 # include <sundials/sundials_nvector.h>
1726 # include <nvector_serial.h>
1727 # include <ida.h>
1728 # include <ida/ida_spgmr.h>
1729 #else
1730 # include <sundials/sundials_config.h>
1731 # include <nvector/nvector_serial.h>
1732 # include <ida/ida.h>
1733 #endif
1734 int main(){
1735 void *ida_mem;
1736 ida_mem = IDACreate();
1737 return 0;
1738 }
1739 """
1740
1741 # slightly changed calling convention (IDACalcID) in newer versions of SUNDIALS,
1742 # so detect the version and act accordingly.
1743 def CheckSUNDIALS(context):
1744 keep = KeepContext(context,'SUNDIALS')
1745 context.Message("Checking for SUNDIALS... ")
1746 (is_ok,output) = context.TryRun(sundials_version_text,'.c')
1747 keep.restore(context)
1748 if not is_ok:
1749 context.Result(0)
1750 return 0
1751
1752 major,minor,patch = tuple([int(i) for i in output.split(".")])
1753 context.env['SUNDIALS_VERSION_MAJOR'] = major
1754 context.env['SUNDIALS_VERSION_MINOR'] = minor
1755 if major != sundials_version_major_required \
1756 or minor < sundials_version_minor_min \
1757 or minor > sundials_version_minor_max:
1758 context.Result(output+" (bad version)")
1759 # bad version
1760 return 0
1761
1762 # good version
1763 context.Result("%d.%d.%d, good" % (major,minor,patch))
1764
1765 return 1
1766
1767
1768 def CheckIDA(context):
1769 context.Message( 'Checking for IDA... ' )
1770
1771 keep = KeepContext(context,"SUNDIALS")
1772
1773 major = context.env['SUNDIALS_VERSION_MAJOR']
1774 minor = context.env['SUNDIALS_VERSION_MINOR']
1775
1776 cppdef = context.env.get('CPPDEFINES')
1777
1778 context.env.Append(CPPDEFINES=[
1779 ('SUNDIALS_VERSION_MAJOR',"$SUNDIALS_VERSION_MAJOR")
1780 ,('SUNDIALS_VERSION_MINOR',"$SUNDIALS_VERSION_MINOR")
1781 ])
1782
1783 context.env['SUNDIALS_CPPPATH_EXTRA']=[]
1784 if major==2 and minor==2:
1785 context.env.Append(SUNDIALS_CPPPATH_EXTRA = ["$SUNDIALS_CPPPATH/sundials"])
1786
1787 context.env.Append(CPPDEFINES=[('SUNDIALS_VERSION_MAJOR',"$SUNDIALS_VERSION_MAJOR"),('SUNDIALS_VERSION_MINOR',"$SUNDIALS_VERSION_MINOR")])
1788 context.env.AppendUnique(LIBS=context.env['SUNDIALS_LIBS'])
1789 context.env.AppendUnique(CPPPATH=context.env['SUNDIALS_CPPPATH_EXTRA'])
1790
1791 is_ok = context.TryLink(ida_test_text,".c")
1792 context.Result(is_ok)
1793
1794 if cppdef:
1795 context.env['CPPDEFINES']=cppdef
1796 else:
1797 del context.env['CPPDEFINES']
1798
1799 keep.restore(context)
1800
1801 return is_ok
1802
1803
1804 #----------------
1805 # CONOPT test
1806
1807 conopt_test_text = """
1808 #if !defined(_WIN32)
1809 # define FNAME_LCASE_DECOR
1810 #endif
1811
1812 #include <conopt.h>
1813 #include <stdlib.h>
1814 int main(){
1815 int s, *v, e;
1816 s = COIDEF_Size();
1817 v = (int *)malloc(s*sizeof(int));
1818 e = COIDEF_Ini(v);
1819 return e;
1820 }
1821 """
1822
1823 def CheckCONOPT(context):
1824 context.Message( 'Checking for CONOPT... ' )
1825
1826 keep = KeepContext(context,"CONOPT")
1827
1828 is_ok = context.TryLink(conopt_test_text,".c")
1829 context.Result(is_ok)
1830
1831 keep.restore(context)
1832
1833 return is_ok
1834
1835 #----------------
1836 # IPOPT test
1837
1838 ipopt_test_text = """
1839 #if !defined(_WIN32)
1840 # define FNAME_LCASE_DECOR
1841 #endif
1842
1843 #include <coin/IpStdCInterface.h>
1844 int main(){
1845 Number n;
1846 IpoptProblem nlp = 0;
1847 n = 1;
1848 FreeIpoptProblem(nlp); // probably a crash if you run this
1849 return 0;
1850 }
1851 """
1852
1853 def CheckIPOPT(context):
1854 context.Message( 'Checking for IPOPT... ' )
1855
1856 keep = KeepContext(context,"IPOPT")
1857 is_ok = context.TryLink(ipopt_test_text,".c")
1858 context.Result(is_ok)
1859
1860 keep.restore(context)
1861
1862 return is_ok
1863
1864 #----------------
1865 # Tcl test
1866
1867 # TCL and TK required version 8.1 through 8.5:
1868 tcltk_minor_newest_acceptable = 5
1869 tcltk_major_required = 8
1870
1871 tcl_check_text = r"""
1872 #include <tcl.h>
1873 #include <stdio.h>
1874 int main(void){
1875 printf("%s",TCL_PATCH_LEVEL);
1876 return 0;
1877 }
1878 """
1879
1880 def CheckTcl(context):
1881 return CheckExtLib(context,'tcl',tcl_check_text,static=env['STATIC_TCLTK'])
1882
1883 def CheckTclVersion(context):
1884 keep = KeepContext(context,'TCL',static=env['STATIC_TCLTK'])
1885 context.Message("Checking Tcl version... ")
1886 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
1887 keep.restore(context)
1888 if not is_ok:
1889 context.Result("failed to run check")
1890 return 0
1891
1892 major,minor,patch = tuple([int(i) for i in output.split(".")])
1893 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
1894 context.Result(output+" (bad version)")
1895 # bad version
1896 return 0
1897
1898 # good version
1899 context.Result(output+", good")
1900 return 1
1901
1902 #----------------
1903 # Tk test
1904
1905 tk_check_text = r"""
1906 #include <tk.h>
1907 #include <stdio.h>
1908 int main(void){
1909 printf("%s",TK_PATCH_LEVEL);
1910 return 0;
1911 }
1912 """
1913 def CheckTk(context):
1914 return CheckExtLib(context,'tk',tk_check_text,static=env['STATIC_TCLTK'])
1915
1916
1917 def CheckTkVersion(context):
1918 keep = KeepContext(context,'TK',static=context.env['STATIC_TCLTK'])
1919 context.Message("Checking Tk version... ")
1920 #print "LINKFLAGS =",context.env['LINKFLAGS']
1921 (is_ok,output) = context.TryRun(tk_check_text,'.c')
1922 keep.restore(context)
1923 if not is_ok:
1924 context.Result("failed to run check")
1925 return 0
1926
1927 major,minor,patch = tuple([int(i) for i in output.split(".")])
1928 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
1929 # bad version
1930 context.Result(output+" (bad version)")
1931 return 0
1932
1933 # good version
1934 context.Result(output+" (good)")
1935 return 1
1936
1937 #----------------
1938 # Tktable test
1939
1940 tktable_check_text = r"""
1941 #include <tkTable.h>
1942 #include <stdio.h>
1943 int main(void){
1944 Table mytable;
1945 return 0;
1946 }
1947 """
1948
1949 def CheckTkTable(context):
1950 return CheckExtLib(context,'tktable',tktable_check_text,static=env['STATIC_TCLTK'])
1951
1952 #---------------
1953 # X11 test
1954
1955 x11_check_text = r"""
1956 #include <X11/Xlib.h>
1957 #include <X11/IntrinsicP.h>
1958 #include <X11/Intrinsic.h>
1959 #include <X11/ObjectP.h>
1960 #include <X11/Object.h>
1961 int main(void){
1962 Object mything;
1963 return 0;
1964 }
1965 """
1966
1967 def CheckX11(context):
1968 return CheckExtLib(context,'X11',x11_check_text)
1969
1970 #----------------
1971 # Check that we can raise and catch sigint
1972
1973 sigint_test_text = r"""
1974 #include <signal.h>
1975 #include <setjmp.h>
1976 #include <stdlib.h>
1977 static jmp_buf g_jmpenv;
1978 void sighandler(int sig){
1979 longjmp(g_jmpenv,sig);
1980 }
1981 void testsigint(){
1982 raise(SIGINT);
1983 }
1984 int main(void){
1985 signal(SIGINT,&sighandler);
1986 switch(setjmp(g_jmpenv)){
1987 case 0:
1988 testsigint();
1989 exit(1);
1990 case SIGINT:
1991 exit(0);
1992 default:
1993 exit(2);
1994 }
1995 }
1996 """
1997
1998 def CheckSIGINT(context):
1999 context.Message("Checking SIGINT is catchable... ")
2000 (is_ok,output)=context.TryRun(sigint_test_text,".c")
2001 context.Result(is_ok)
2002 return is_ok
2003
2004 #----------------
2005 # Check that we're able to catch floating point errors
2006
2007 sigfpe_test_text = r"""
2008 #include <signal.h>
2009 #include <setjmp.h>
2010 #include <stdlib.h>
2011 #include <fenv.h>
2012 static jmp_buf g_jmpenv;
2013 void fpehandler(int sig){
2014 longjmp(g_jmpenv,sig);
2015 }
2016 int main(void){
2017 fenv_t myfenv;
2018 fegetenv(&myfenv);
2019 fesetenv(&myfenv);
2020 feenableexcept(FE_ALL_EXCEPT);
2021 signal(SIGFPE,&fpehandler);
2022 double x;
2023 switch(setjmp(g_jmpenv)){
2024 case 0:
2025 x = 1.0 / 0.0;
2026 /* failed to catch */
2027 exit(1);
2028 case SIGFPE:
2029 exit(0);
2030 }
2031 }
2032 """
2033
2034 def CheckFPE(context):
2035 context.Message("Checking C99 FPE behaviour... ")
2036 (is_ok,output) = context.TryRun(sigfpe_test_text,'.c')
2037 context.Result(is_ok)
2038 return is_ok
2039
2040 #----------------
2041 # signal reset needed?
2042
2043 sigreset_test_text = r"""
2044 #include <signal.h>
2045 #include <setjmp.h>
2046 #include <stdlib.h>
2047 #include <stdio.h>
2048 typedef void SigHandlerFn(int);
2049 static jmp_buf g_jmpenv;
2050 void sighandler(int sig){
2051 longjmp(g_jmpenv,sig);
2052 }
2053 void testsigint(){
2054 /* fprintf(stderr,"Raising SIGINT\n"); */
2055 raise(SIGINT);
2056 }
2057 int main(void){
2058 SigHandlerFn *last,*saved;
2059 saved = signal(SIGINT,&sighandler);
2060 if(saved!=SIG_DFL){
2061 fprintf(stderr,"Default handler (%p) was not correctly set\n",SIG_DFL);
2062 exit(3);
2063 }
2064 switch(setjmp(g_jmpenv)){
2065 case 0:
2066 testsigint();
2067 fprintf(stderr,"Back from SIGINT\n");
2068 exit(1);
2069 case SIGINT:
2070 break;
2071 default:
2072 exit(2);
2073 };
2074 last = signal(SIGINT,SIG_DFL);
2075 if(last!=&sighandler){
2076 printf("1");
2077 exit(0);
2078 }
2079 printf("0");
2080 exit(0);
2081 }
2082 """
2083
2084 def CheckSigReset(context):
2085 context.Message("Checking signal handler reset... ")
2086 libsave=context.env.get('LIBS')
2087 context.env.AppendUnique(LIBS=['m'])
2088 (is_ok,output) = context.TryRun(sigreset_test_text,'.c')
2089
2090 if libsave is None:
2091 del(context.env['LIBS'])
2092 else:
2093 context.env['LIBS']=libsave
2094
2095 if not is_ok:
2096 context.Result("ERROR")
2097 return False
2098 if int(output)==1:
2099 context.Result("required");
2100 context.env['ASC_RESETNEEDED'] = True
2101 else:
2102 context.Result("not required");
2103 context.env['ASC_RESETNEEDED'] = False
2104 return True
2105
2106 #----------------
2107 # LyX on this system?
2108
2109 def CheckLyx(context):
2110 context.Message("Checking for LyX... ")
2111 r = context.env.WhereIs("lyx")
2112 if r:
2113 context.Result(r)
2114 else:
2115 context.Result(0)
2116 return r
2117
2118 #----------------
2119 # Latex2HTML on this system?
2120
2121 def CheckLatex2HTML(context):
2122 context.Message("Checking for latex2html...")
2123 if context.env.WhereIs("latex2html"):
2124 r = True
2125 else:
2126 r = False
2127 context.Result(r)
2128 return r
2129
2130 #----------------
2131 # Check usable 'erf' function
2132
2133 erf_test_text = r"""
2134 #include <math.h>
2135 int main(){
2136 double x = erf(0.5);
2137 return 0;
2138 }
2139 """
2140 def CheckErf(context):
2141 context.Message("Checking for erf... ")
2142 libsave=context.env.get('LIBS')
2143 context.env.AppendUnique(LIBS=['m'])
2144 (is_ok,output) = context.TryRun(erf_test_text,'.c')
2145 context.Result(is_ok)
2146
2147 #----------------
2148 # GCC Version sniffing
2149
2150 # TODO FIXME
2151
2152 gcc_version4 = False
2153
2154 #------------------------------------------------------
2155 # CONFIGURATION
2156
2157 conf = Configure(env
2158 , custom_tests = {
2159 'CheckCC' : CheckCC
2160 , 'CheckCXX' : CheckCXX
2161 , 'CheckFortran' : CheckFortran
2162 , 'CheckMath' : CheckMath
2163 , 'CheckMalloc' : CheckMalloc
2164 , 'CheckASan' : CheckASan
2165 , 'CheckDLOpen' : CheckDLOpen
2166 , 'CheckSwigVersion' : CheckSwigVersion
2167 , 'CheckPythonLib' : CheckPythonLib
2168 , 'CheckCUnit' : CheckCUnit
2169 , 'CheckDMalloc' : CheckDMalloc
2170 , 'CheckLyx' : CheckLyx
2171 , 'CheckLatex2HTML' : CheckLatex2HTML
2172 , 'CheckGraphVizAgraph' : CheckGraphVizAgraph
2173 , 'CheckGraphVizCgraph' : CheckGraphVizCgraph
2174 , 'CheckGraphVizBoolean' : CheckGraphVizBoolean
2175 , 'CheckUFSparse' : CheckUFSparse
2176 , 'CheckTcl' : CheckTcl
2177 , 'CheckTclVersion' : CheckTclVersion
2178 , 'CheckTk' : CheckTk
2179 , 'CheckTkVersion' : CheckTkVersion
2180 , 'CheckGcc' : CheckGcc
2181 , 'CheckGccVisibility' : CheckGccVisibility
2182 , 'CheckYacc' : CheckYacc
2183 , 'CheckLex' : CheckLex
2184 , 'CheckLexDestroy' : CheckLexDestroy
2185 , 'CheckTkTable' : CheckTkTable
2186 , 'CheckX11' : CheckX11
2187 , 'CheckIDA' : CheckIDA
2188 , 'CheckSUNDIALS' : CheckSUNDIALS
2189 , 'CheckCONOPT' : CheckCONOPT
2190 , 'CheckIPOPT' : CheckIPOPT
2191 , 'CheckScrollkeeperConfig' : CheckScrollkeeperConfig
2192 , 'CheckFPE' : CheckFPE
2193 , 'CheckSIGINT' : CheckSIGINT
2194 , 'CheckSigReset' : CheckSigReset
2195 , 'CheckErf' : CheckErf
2196 # , 'CheckIsNan' : CheckIsNan
2197 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
2198 }
2199 # , config_h = "config.h"
2200 )
2201
2202 def sconsversioncheck():
2203
2204 # uncomment the following line to skip the version check:
2205 # return 1
2206
2207 import SCons
2208 v = SCons.__version__.split(".")
2209 if v[0] != '0':
2210 if v[0] == '1' or v[0] == '2':
2211 return 1;
2212 return 0
2213 if int(v[1]) >= 97:
2214 return 1
2215 if v[1] != '96':
2216 return 0
2217 micro = int(v[2])
2218 if micro == 92 or micro == 93 or micro == 96:
2219 return 1;
2220 return 0
2221
2222 if not sconsversioncheck():
2223 print "Scons version is not OK. Please try version 0.96.92 or 0.96.93,"
2224 print "or consult the developers in the case of newer versions. Modify"
2225 print "the function 'sconsversioncheck' in the file SConstruct if you"
2226 print "want to *force* SCons to continue."
2227 Exit(1)
2228
2229 # check C compiler
2230
2231 if conf.CheckCC() is False:
2232 print "Failed to build simple test file with your C compiler."
2233 print "Check your compiler is installed and running correctly."
2234 Exit(1)
2235
2236 if conf.CheckCXX() is False:
2237 print "Failed to build simple test file with your C++ compiler."
2238 print "Check your compiler is installed and running correctly."
2239 print "You can set your C++ compiler using the CXX scons option."
2240 Exit(1)
2241
2242 if conf.CheckASan() is False:
2243 conf.env['HAVE_ASAN'] = True
2244 else:
2245 conf.env['HAVE_ASAN'] = False
2246
2247 # stdio -- just to check that compiler is behaving
2248
2249 if conf.CheckHeader('stdio.h') is False:
2250 print "CPPPATH =",env.get('CPPPATH')
2251 print "Did not find 'stdio.h'! Check your compiler configuration."
2252 print ""
2253 print "You environment is printed here:"
2254 for k,v in os.environ.iteritems():
2255 print "%-30s%s" % ("%s :" % k, v)
2256 Exit(1)
2257
2258 # sizes of vars used in libascend eg in gl_list etc.
2259
2260 _sizes = {
2261 "VOID_P" : "void *"
2262 ,"INT" : "int"
2263 ,"LONG" : "long"
2264 ,"LONG_LONG" : "long long"
2265 ,"UINT" : "unsigned int"
2266 ,"ULONG" : "unsigned long"
2267 ,"ULONGLONG" : "unsigned long long"
2268 }
2269
2270 for _var,_type in _sizes.iteritems():
2271 _size = conf.CheckTypeSize(_type)
2272 if not _size:
2273 print "Couldn't determine 'sizeof(%s)'" % _type
2274 Exit(1)
2275 conf.env["SIZEOF_%s" % _var] = str(_size)
2276
2277 # check for some string functions
2278
2279 if conf.CheckFunc('sprintf') is False:
2280 print "Didn't find sprintf";
2281 Exit(1)
2282
2283 if conf.CheckErf() is False:
2284 print "Didn't find erf";
2285 Exit(1)
2286 else:
2287 conf.env['HAVE_ERF'] = True
2288
2289 if conf.CheckFunc('strdup'):
2290 conf.env['HAVE_STRDUP'] = True
2291
2292 if conf.CheckFunc('snprintf'):
2293 conf.env['HAVE_SNPRINTF'] = True
2294 elif conf.CheckFunc('_snprintf'):
2295 conf.env['HAVE__SNPRINTF'] = True
2296
2297 if conf.CheckFunc('cpow'):
2298 conf.env['HAVE_CPOW'] = True
2299
2300 # attempt to support MSVCRT 7.1 on Windows
2301
2302 if platform.system()=="Windows" and env.get('WITH_MSVCR71'):
2303 conf.env.Append(LIBS='msvcr71')
2304
2305 # Math library
2306
2307 conf.env['HAVE_IEEE']=True
2308
2309 if need_libm and (conf.CheckMath() is False):
2310 conf.env['HAVE_IEEE']=False
2311 print 'Did not find math library, exiting!'
2312 Exit(1)
2313
2314 # Malloc
2315
2316 if conf.CheckMalloc() is False:
2317 conf.env['HAVE_MALLOC']=False
2318 print "Did not find functioning 'malloc', exiting!"
2319 Exit(1)
2320
2321 # dlopen/LoadLibrary
2322
2323 # CURRENTLY BREAKS LATER TEST (libsave?)
2324 #if conf.CheckDLOpen() is False:
2325 # print "Did not find functioning dlopen/LoadLibrary, exiting!"
2326 # Exit(1)
2327
2328 # Where is 'isnan'?
2329
2330 if conf.CheckFunc('isnan') is False and conf.CheckFunc('_isnan') is False:
2331 print "Didn't find isnan"
2332 # Exit(1)
2333
2334 # GCC visibility
2335
2336 if conf.CheckGcc():
2337 conf.env['HAVE_GCC']=True;
2338 if env.get('WITH_GCCVISIBILITY') and conf.CheckGccVisibility():
2339 conf.env['HAVE_GCCVISIBILITY']=True;
2340 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
2341 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
2342 conf.env.Append(CCFLAGS=['-Wall'])
2343
2344 # Catching SIGINT
2345
2346 if env['WITH_SIGNALS']:
2347 if not conf.CheckSIGINT():
2348 with_signals = False
2349 without_signals_reason = "SIGINT uncatchable"
2350
2351 # Catching SIGFPE
2352
2353 if conf.CheckFPE():
2354 conf.env['HAVE_C99FPE']=True
2355 else:
2356 conf.env['HAVE_C99FPE']=False
2357
2358 # Checking for signal reset requirement
2359
2360 if conf.CheckSigReset() is False:
2361 print "Unable to determine if signal reset is required"
2362 Exit(1)
2363
2364 # YACC
2365
2366 if conf.CheckYacc():
2367 conf.env['HAVE_YACC']=True
2368
2369 if conf.CheckLex():
2370 conf.env['HAVE_LEX']=True
2371
2372 if conf.CheckLexDestroy():
2373 conf.env['HAVE_LEXDESTROY']=True
2374
2375 # Tcl/Tk
2376
2377 if with_tcltk:
2378 if conf.CheckTcl():
2379 if conf.CheckTclVersion():
2380 if conf.CheckTk():
2381 if with_tcltk and conf.CheckTkVersion():
2382 if env['STATIC_TCLTK']:
2383 if conf.CheckTkTable():
2384 pass
2385 else:
2386 without_tcltk_reason = "TkTable not found"
2387 with_tcltk = False
2388 else:
2389 without_tcltk_reason = "Require Tk version <= 8.4. See 'scons -h'"
2390 with_tcltk = False
2391 else:
2392 without_tcltk_reason = "Tk not found."
2393 with_tcltk = False
2394 else:
2395 without_tcltk_reason = "Require Tcl <= 8.4 Tcl."
2396 with_tcltk = False
2397
2398 else:
2399 without_tcltk_reason = "Tcl not found."
2400 with_tcltk = False
2401
2402 if env['STATIC_TCLTK']:
2403 conf.CheckX11()
2404
2405 # Python... obviously we're already running python, so we just need to
2406 # check that we can link to the python library OK:
2407
2408 if not conf.CheckPythonLib():
2409 without_python_reason = 'libpython2.x not found or not linkable'
2410 with_python = False
2411 env['WITH_PYTHON']=False
2412
2413 # SWIG version
2414
2415 if with_python and conf.CheckSwigVersion() is False:
2416 without_python_reason = 'SWIG >= 1.3.24 is required'
2417 with_python = False
2418 env['WITH_PYTHON']=False
2419
2420 # CUnit
2421
2422 if with_cunit:
2423 if not conf.CheckCUnit():
2424 without_cunit_reason = 'CUnit not found'
2425 with_cunit = False
2426 #print "CUNIT NOT FOUND, LIBS=",conf.env.get('LIBS')
2427
2428 # DMALLOC
2429
2430 if with_dmalloc:
2431 if not conf.CheckDMalloc():
2432 without_dmalloc_reason = 'dmalloc not found'
2433 with_dmalloc = False
2434
2435 # GRAPHVIZ
2436
2437 if with_graphviz:
2438 if not conf.CheckGraphVizCgraph():
2439 if not conf.CheckGraphVizAgraph():
2440 without_graphviz_reason = 'graphviz not found (cgraph nor agraph)'
2441 with_graphviz = False
2442 env['WITH_GRAPHVIZ'] = False
2443 env['HAVE_GRAPHVIZ_BOOLEAN'] = conf.CheckGraphVizBoolean()
2444
2445 # UFSPARSE
2446
2447 if with_ufsparse:
2448 if not conf.CheckUFSparse():
2449 without_ufsparse_reason = 'ufsparse not found'
2450 with_ufsparse = False
2451 env['WITH_UFSPARSE'] = False
2452
2453 # IDA
2454
2455 if with_ida:
2456 if not conf.CheckSUNDIALS():
2457 with_ida = False
2458 without_ida_reason = "SUNDIALS not found, or bad version"
2459 elif not conf.CheckIDA():
2460 with_ida = False
2461 without_ida_reason = "Unable to compile/link against SUNDIALS/IDA"
2462
2463 # CONOPT
2464
2465 if not with_conopt:
2466 without_conopt_reason = "Not selected (see config option WITH_SOLVERS)"
2467 elif conf.CheckCONOPT() is False:
2468 if conf.env.get('CONOPT_LINKED'):
2469 conf.env['CONOPT_LINKED'] = False
2470 # we no longer require CONOPT at buildtime in order to build support for it
2471 #with_conopt = False
2472 #without_conpt_reason = "CONOPT not found"
2473
2474 # IPOPT
2475
2476 if not with_ipopt:
2477 without_ipopt_reason = "Not selected (see config option WITH_SOLVERS)"
2478 elif not conf.CheckIPOPT():
2479 with_ipopt = False
2480 without_ipopt_reason = "IPOPT not found"
2481
2482 # BLAS
2483
2484 need_blas=False
2485
2486 if with_lsode:
2487 need_fortran = True
2488 need_fortran_reasons.append("LSODE")
2489 need_blas=True
2490
2491 if with_ipopt:
2492 need_blas=True
2493
2494 if need_blas:
2495 if conf.CheckLib('blas'):
2496 with_local_blas = False
2497 without_local_blas_reason = "Found BLAS installed on system"
2498 else:
2499 with_local_blas = True
2500 need_fortran = True
2501 need_fortran_reasons.append("BLAS")
2502 else:
2503 with_local_blas= False;
2504 without_local_blas_reason = "BLAS not required"
2505
2506 # FORTRAN
2507
2508 # we'll assume now (2012) that we always have gfortran available on our system.
2509
2510 if need_fortran and conf.CheckFortran() is False:
2511 print "Failed to build simple test file with your Fortran compiler."
2512 print "Check your compiler is installed and running correctly."
2513 print "You can set your Fortran compiler using the FORTRAN scons option."
2514 print "The fortran compiler is REQUIRED to build:",", ".join(need_fortran_reasons)
2515 print "Perhaps try examining the value of your WITH_SOLVERS option (remove LSODE, etc)."
2516 Exit(1)
2517
2518 #else:
2519 # print "FORTRAN not required"
2520
2521 # F2C
2522
2523 if need_fortran:
2524 if platform.system()=="Windows":
2525 pass
2526 #conf.env.Append(LIBPATH='c:\mingw\lib')
2527
2528 # scrollkeeper
2529
2530 if with_scrollkeeper:
2531 if conf.CheckScrollkeeperConfig() is False:
2532 with_scrollkeeper=False
2533 without_scrollkeeper_reason="unable to detect scrollkeeper-config"
2534
2535 # lyx
2536
2537 if with_doc_build:
2538 if not conf.CheckLyx():
2539 with_doc_build = False
2540 without_doc_build_reason="unable to locate LyX"
2541
2542 # TODO: -D_HPUX_SOURCE is needed
2543
2544 # TODO: detect if dynamic libraries are possible or not
2545
2546 if platform.system()=="Windows" and env.has_key('MSVS'):
2547 _found_windows_h = conf.CheckHeader('Windows.h')
2548
2549 if not _found_windows_h:
2550 print "Could not locate 'Windows.h' in CPPPATH. Check your configuration."
2551 Exit(1)
2552
2553 if with_python and conf.CheckHeader(['basetsd.h','BaseTsd.h']) is False:
2554 with_python = 0;
2555 without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
2556
2557 conf.Finish()
2558
2559 #print "-=-=-=-=-=-=-=-=- LIBS =",env.get('LIBS')
2560
2561 #---------------------------------------
2562 # SUBSTITUTION DICTIONARY for .in files
2563
2564 release = env.get('RELEASE')
2565 if release=="0.":
2566 release="0"
2567
2568 #print "SUBSTITUTED CONOPT_LIBPATH:",c_escape(env.subst("$CONOPT_LIBPATH"))
2569
2570 subst_dict = {
2571 '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
2572 ,'@DEFAULT_ASCENDSOLVERS@':env['DEFAULT_ASCENDSOLVERS']
2573 , '@GLADE_FILE@':'ascend.glade'
2574 , '@HELP_ROOT@':''
2575 , '@ICON_EXTENSION@':icon_extension
2576 , '@INSTALL_ASCDATA@':env['INSTALL_ASCDATA']
2577 , '@INSTALL_BIN@':env['INSTALL_BIN']
2578 , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
2579 , '@INSTALL_LIB@':env['INSTALL_LIB']
2580 , '@INSTALL_MODELS@':env['INSTALL_MODELS']
2581 , '@INSTALL_SOLVERS@':env['INSTALL_SOLVERS']
2582 , '@INSTALL_PYTHON@':env['INSTALL_PYTHON']
2583 , '@INSTALL_PYTHON_ASCEND@':env['INSTALL_PYTHON_ASCEND']
2584 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
2585 , '@VERSION@':version
2586 , '@RELEASE@':release
2587 , '@SONAME_MAJOR_INT@':soname_major_int
2588 , '@DISTTAR_NAME@':env['DISTTAR_NAME']
2589 , '@WEBHELPROOT@':'http://ascendwiki.cheme.cmu.edu/Category:Documentation'
2590 , '@SHLIBSUFFIX@':env['SHLIBSUFFIX']
2591 , '@SHLIBPREFIX@':env['SHLIBPREFIX']
2592 , '@EXTLIB_SUFFIX@':env['EXTLIB_SUFFIX']
2593 , '@EXTLIB_PREFIX@':env['EXTLIB_PREFIX']
2594 , '@ASC_ENV_TK_DEFAULT@' : '$$ASCENDDIST/tcltk'
2595 , '@PYTHON@' : python_exe
2596 , '@PYVERSION@' : pyversion
2597 , '@SOURCE_ROOT@':c_escape(os.path.abspath(str(env.Dir("#"))))
2598 , '@WITH_GRAPHVIZ@': str(int(env.get('WITH_GRAPHVIZ')))
2599 #define ASC_ABSOLUTE_PATHS @ASC_ABSOLUTE_PATHS@
2600 #if ASC_ABSOLUTE_PATHS
2601 # define ASCENDDIST_DEFAULT "@ASCENDDIST_DEFAULT@"
2602 # define ASCENDTK_DEFAULT "@ASCENDTK_DEFAULT@"
2603 # define ASCENDLIBRARY_DEFAULT "@ASCENDLIBRARY_DEFAULT@"
2604 # define ASCENDSOLVERS_DEFAULT "@ASCENDSOLVERS_DEFAULT@"
2605 #else
2606 # define ASC_DIST_REL_BIN "@ASC_DIST_REL_BIN@"
2607 # define ASC_TK_REL_DIST "@ASC_TK_REL_DIST@"
2608 # define ASC_LIBRARY_REL_DIST "@ASC_LIBRARY_REL_DIST@"
2609 # define ASC_SOLVERS_REL_DIST "@ASC_SOLVERS_REL_DIST@"
2610 #endif
2611 , '@ASC_ABSOLUTE_PATHS@': str(int(env.get('ABSOLUTE_PATHS')))
2612 , '@ASCENDDIST_DEFAULT@': c_escape(env['INSTALL_PREFIX'])
2613 , '@ASCENDTK_DEFAULT@': c_escape(os.path.abspath(env.subst(env['INSTALL_TK'])))
2614 , '@ASCENDLIBRARY_DEFAULT@': c_escape(os.path.abspath(env.subst(env['DEFAULT_ASCENDLIBRARY'])))
2615 , '@ASCENDSOLVERS_DEFAULT@': c_escape(os.path.abspath(env.subst(env['DEFAULT_ASCENDSOLVERS'])))
2616 , '@ASC_DIST_REL_BIN@' : default_dist_rel_bin
2617 , '@ASC_TK_REL_DIST@' : default_tk_rel_dist
2618 , '@ASC_LIBRARY_REL_DIST@' : default_library_rel_dist
2619 , '@ASC_SOLVERS_REL_DIST@' : default_solvers_rel_dist
2620 , '@SIZEOF_VOID_P@' : env['SIZEOF_VOID_P']
2621 , '@SIZEOF_INT@' : env['SIZEOF_INT']
2622 , '@SIZEOF_LONG@' : env['SIZEOF_LONG']
2623 , '@SIZEOF_LONG_LONG@' : env['SIZEOF_LONG_LONG']
2624 , '@SIZEOF_UINT@' : env['SIZEOF_UINT']
2625 , '@SIZEOF_ULONG@' : env['SIZEOF_ULONG']
2626 , '@SIZEOF_ULONGLONG@' : env['SIZEOF_ULONGLONG']
2627 }
2628
2629 if env.get('WITH_DOC'):
2630 #print "WITH_DOC:",env['WITH_DOC']
2631 subst_dict['@HELP_ROOT@']=env['HELP_ROOT']
2632
2633 # bool options...
2634 for k,v in {
2635 'ASC_WITH_DMALLOC':with_dmalloc
2636 ,'ASC_WITH_UFSPARSE':with_ufsparse
2637 ,'ASC_WITH_MMIO':with_mmio
2638 ,'ASC_SIGNAL_TRAPS':with_signals
2639 ,'ASC_RESETNEEDED':env.get('ASC_RESETNEEDED')
2640 ,'HAVE_C99FPE':env.get('HAVE_C99FPE')
2641 ,'HAVE_IEEE':env.get('HAVE_IEEE')
2642 ,'HAVE_ERF':env.get('HAVE_ERF')
2643 ,'ASC_XTERM_COLORS':env.get('WITH_XTERM_COLORS')
2644 ,'MALLOC_DEBUG':env.get('MALLOC_DEBUG')
2645 ,'ASC_HAVE_LEXDESTROY':env.get('HAVE_LEXDESTROY')
2646 ,'HAVE_SNPRINTF':env.get('HAVE_SNPRINTF')
2647 ,'HAVE__SNPRINTF':env.get('HAVE__SNPRINTF')
2648 }.iteritems():
2649
2650 if v: subst_dict["/\\* #\\s*define %s @%s@ \\*/" % (k,k)]='# define %s 1 ' % k
2651
2652 if with_python:
2653 subst_dict['@ASCXX_USE_PYTHON@']="1"
2654 env['WITH_PYTHON']=1;
2655
2656 if with_latex2html:
2657 env['WITH_LATEX2HTML']=1
2658
2659 if env.has_key('HAVE_GCCVISIBILITY'):
2660 subst_dict['@HAVE_GCCVISIBILITY@'] = "1"
2661
2662 env.Append(SUBST_DICT=subst_dict)
2663
2664 #for k,v in subst_dict.iteritems():
2665 # print "%-50s%s" % ("'%s'"%k,v)
2666
2667 # REMOVED: long command-line support on Win2k
2668
2669 #------------------------------------------------------
2670 # RECIPE: SWIG scanner
2671
2672 import SCons.Script
2673
2674 SWIGScanner = SCons.Scanner.ClassicCPP(
2675 "SWIGScan"
2676 , ".i"
2677 , "CPPPATH"
2678 , '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
2679 )
2680
2681 env.Append(SCANNERS=[SWIGScanner])
2682
2683 #------------------------------------------------------
2684 # Recipe for 'CHMOD' ACTION
2685
2686 import SCons
2687 from SCons.Script.SConscript import SConsEnvironment
2688 SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
2689 lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
2690
2691 def InstallPerm(env, dest, files, perm):
2692 obj = env.Install(dest, files)
2693 for i in obj:
2694 env.AddPostAction(i, env.Chmod(str(i), perm))
2695
2696 def InstallPermAs(env, dest, filen, perm):
2697 obj = env.InstallAs(dest, filen)
2698 for i in obj:
2699 env.AddPostAction(i, env.Chmod(str(i), perm))
2700 return dest
2701
2702 SConsEnvironment.InstallPerm = InstallPerm
2703
2704 # define wrappers
2705 SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
2706 SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
2707 SConsEnvironment.InstallShared = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
2708 SConsEnvironment.InstallSharedAs = lambda env, dest, files: InstallPermAs(env, dest, files, 0644)
2709 SConsEnvironment.InstallLibraryAs = lambda env, dest, files: InstallPermAs(env, dest, files, 0644)
2710
2711 #------------------------------------------------------
2712 # BUILD...
2713
2714 # so that #include <ascend/modulename/headername.h> works across all modules...
2715 env.AppendUnique(CPPPATH=['#'])
2716
2717 if env['DEBUG']:
2718 env.Append(
2719 CCFLAGS=['-g']
2720 ,LINKFLAGS=['-g']
2721 )
2722
2723 if env['GCOV']:
2724 env.Append(
2725 CPPFLAGS=['-g','-fprofile-arcs','-ftest-coverage']
2726 , LIBS=['gcov']
2727 , LINKFLAGS=['-fprofile-arcs','-ftest-coverage']
2728 )
2729
2730 #FIXME there must be a better way of doing this...
2731
2732 if with_ida:
2733 env.Append(WITH_IDA=1)
2734
2735 if with_conopt:
2736 env.Append(WITH_CONOPT=1)
2737
2738 if with_ipopt:
2739 env.Append(WITH_IPOPT=1)
2740
2741 if with_dopri5:
2742 env.Append(WITH_DOPRI5=1)
2743
2744 if with_radau5:
2745 env.Append(WITH_RADAU5=1)
2746
2747 if with_makemps:
2748 env.Append(WITH_MAKEMPS=1)
2749
2750 if with_graphviz and env.get('GRAPHVIZ_RPATH'):
2751 env.Append(RPATH=env['GRAPHVIZ_RPATH'])
2752
2753 #-------------
2754 # TCL/TK GUI
2755
2756 if with_tcltk:
2757 env.SConscript(['tcltk/SConscript'],'env')
2758 else:
2759 print "Skipping... Tcl/Tk bindings aren't being built:",without_tcltk_reason
2760
2761 #-------------
2762 # PYTHON INTERFACE
2763
2764 if with_python:
2765 env.SConscript(['ascxx/SConscript'],'env')
2766 env.SConscript(['pygtk/SConscript'],'env')
2767 else:
2768 print "Skipping... Python bindings aren't being built:",without_python_reason
2769
2770 #------------
2771 # BASE/GENERIC SUBDIRECTORIES
2772
2773 libascend_env = env.Clone()
2774
2775 dirs = ['general','utilities','compiler','system','solver','integrator','packages','linear']
2776
2777 srcs = []
2778 for d in dirs:
2779 heresrcs = libascend_env.SConscript('ascend/'+d+'/SConscript','libascend_env')
2780 srcs += heresrcs
2781
2782 #-------------
2783 # IMPORTED CODE: LSODE, BLAS, etc
2784
2785 if with_local_blas:
2786 env['blasobjs'] = env.SConscript(['blas/SConscript'],'env')
2787 else:
2788 env['blasobjs'] = []
2789 print "Skipping... BLAS won't be built:", without_local_blas_reason
2790
2791 if not with_ida:
2792 print "Skipping... IDA won't be built:", without_ida_reason
2793
2794 if not with_dopri5:
2795 print "Skipping... DOPRI5 won't be built:", without_dopri5_reason
2796
2797 if with_mmio:
2798 srcs += env.SConscript(['mmio/SConscript'],'env')
2799 else:
2800 print "Skipping... MMIO export won't be built:", without_mmio_reason
2801 #-------------
2802 # LIBASCEND -- all 'core' functionality
2803
2804 # FIXME want to move these bits to ascend/SConscript
2805
2806 libascend_env.Append(
2807 CPPPATH=['#']
2808 ,LIBS=['m']
2809 )
2810
2811 if platform.system()=="Linux":
2812 libascend_env.Append(LIBS=['dl'])
2813
2814 if with_dmalloc:
2815 libascend_env.Append(LIBS=['dmalloc'])
2816
2817 if with_ufsparse:
2818 libascend_env.Append(LIBS=['cxsparse'])
2819
2820 if platform.system()=="Linux":
2821 libascend_env.Append(LINKFLAGS=['-Wl,-soname,%s' % soname_full])
2822
2823 libascend = libascend_env.SharedLibrary('ascend',srcs)
2824
2825 # create local symlink for the soname stuff.
2826 #print "SONAME =",env.subst(soname_full)
2827
2828 env['libascend'] = libascend
2829 libtargets = [libascend]
2830
2831 if platform.system()=="Linux":
2832 if soname_major:
2833 libascend_env.Command(soname_full,libascend,Move("$TARGET","$SOURCE"))
2834 #print "MAKING LINK, SONAME_MAJOR =",soname_major
2835 liblink = libascend_env.Command(soname_full, libascend, "ln -s $SOURCE $TARGET")
2836 libtargets.append(liblink)
2837
2838 # for use in declaring dependent shared libraries in SConscript files (eg solvers/*/SConscript)
2839
2840 env.Alias('libascend',libtargets)
2841
2842 #-------------
2843 # UNIT TESTS (C CODE)
2844
2845 test_env = env.Clone()
2846 test_env.Append(
2847 CPPPATH="#"
2848 )
2849
2850 if with_cunit:
2851 testdirs = ['general','solver','utilities','linear','compiler','system','packages','integrator']
2852 testsrcs = []
2853 for testdir in testdirs:
2854 path = 'ascend/'+testdir+'/test/'
2855 test_env.SConscript([path+'SConscript'],'test_env')
2856 testsrcs += [i.path for i in test_env['TESTSRCS_'+testdir.upper()]]
2857 test_env['TESTDIRS'] = testdirs
2858
2859 #print "TESTSRCS =",testsrcs
2860
2861 test_env.SConscript(['test/SConscript'],'test_env')
2862
2863 env.Alias('test',[env.Dir('test')])
2864
2865 else:
2866 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
2867
2868 #-------------
2869 # EXTERNAL SOLVERS
2870
2871 env['extfns']=[]
2872 env['BUILDING_ASCEND'] = 1
2873
2874 env.SConscript(['solvers/SConscript'],'env')
2875
2876 #-------------
2877 # EXTERNAL FUNCTIONS
2878
2879 modeldirs = env.SConscript(['models/SConscript'],'env')
2880
2881 if not with_extfns:
2882 print "Skipping... External modules aren't being built:",without_extfns_reason
2883
2884 for _f in env['extfns']:
2885 env.Depends(_f,'libascend')
2886 env.Alias('extfns',env['extfns'])
2887
2888 #-------------
2889 # FPROPS python bindings
2890
2891 env.Alias('pyfprops',env.get('pyfprops'))
2892
2893 #------------------------------------------------------
2894 # CREATE ASCEND-CONFIG scriptlet
2895
2896 ascendconfig = env.SubstInFile('ascend-config.in')
2897
2898 #------------------------------------------------------
2899 # INSTALLATION
2900
2901 if env.get('CAN_INSTALL'):
2902
2903 dirs = ['INSTALL_BIN','INSTALL_ASCDATA','INSTALL_LIB', 'INSTALL_INCLUDE','INSTALL_DOC','INSTALL_PYTHON']
2904 install_dirs = [Dir(env.subst("$INSTALL_ROOT$"+d)) for d in dirs]
2905 install_dirs += modeldirs + [Dir(env.subst("$INSTALL_ROOT$INSTALL_SOLVERS"))]
2906
2907 #env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_LIB")),libascend)
2908
2909 libname = "${INSTALL_LIB}/%s%s" % (soname_full,soname_minor)
2910 install_lib = env.InstallLibraryAs("${INSTALL_ROOT}"+libname, [libascend])
2911 if env['ABSOLUTE_PATHS']:
2912 link_target = libname
2913 else:
2914 link_target = "%s%s" % (soname_full,soname_minor)
2915
2916 link1 = "${INSTALL_LIB}/%s" % soname_clean
2917 install_link1 = None
2918 if env.subst(link1) != env.subst(libname):
2919 # v--link to create v--file to link to command
2920 install_link1 = env.Command("${INSTALL_ROOT}"+link1,install_lib
2921 # v-- command to do it (note the trick about
2922 ,"ln -f -s %s $TARGET" % link_target
2923 )
2924
2925 link2 = "${INSTALL_LIB}/%s" % soname_full
2926 install_link2 = None
2927 if soname_minor:
2928 install_link2 = env.Command("${INSTALL_ROOT}"+link2,install_lib
2929 ,"ln -f -s %s $TARGET" % link_target
2930 )
2931
2932 env.InstallProgram(Dir(env.subst("$INSTALL_ROOT$INSTALL_BIN")),ascendconfig)
2933
2934 # MAC OS X INSTALL STUFF
2935 # in this case, we're installing to INSTALL_PREFIX, assumed to be a folder
2936 # created using Disk Utility as a new DMG which will be distributed.
2937 if platform.system()=="Darwin":
2938 # extra stuff for inside the .app
2939 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_BIN")),"mac/Info.plist")
2940 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_BIN/Resources/")),"mac/ascend.icns")
2941
2942 # related files the .dmg folder
2943 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX")),"README-osx.txt")
2944 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX")),"LICENSE.txt")
2945 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX")),"CHANGELOG.txt")
2946 env.Command("$INSTALL_ROOT$INSTALL_PREFIX/Applications Folder","/Applications","ln -f -s $SOURCE $TARGET")
2947 install_dirs += [Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX"))]
2948
2949 # GTK libraries and related files
2950 gtkfiles = []
2951 gtksource = "dist/PyGTK.bundle/"
2952 def visit(gtkfiles,dirname,fnames):
2953 gtkfiles += Glob("%s/*" % dirname)
2954 os.path.walk(gtksource,visit,gtkfiles)
2955
2956 #print "GTKFILES ="
2957 #
2958 for f in gtkfiles:
2959 r = os.path.commonprefix([gtksource,f.path])
2960 dirname,filename = os.path.split(f.path[len(r):])
2961 dest = os.path.join(env.subst("$INSTALL_ROOT$INSTALL_BIN/PyGTK.bundle"),dirname)
2962 # print "%s --> %s" %(f,dest)
2963 env.Install(Dir(dest),f)
2964
2965 # ALIAS FOR ALL INSTALLATION
2966 env.Alias('install',install_dirs)
2967
2968 #------------------------------------------------------
2969 # WINDOWS INSTALLER
2970
2971 if not env.get('NSIS'):
2972 with_installer = False
2973 without_installer_reason = "NSIS not found"
2974
2975 if with_installer:
2976 pyarch = ""
2977 instarch = "win32"
2978 if platform.architecture()[0] == "64bit":
2979 instarch = "x64"
2980 pyarch = ".amd64"
2981 inst64 = 1
2982 nsisdefs = {
2983 'OUTFILE':"#dist/$WIN_INSTALLER_NAME"
2984 ,"VERSION":version
2985 ,'PYVERSION':pyversion
2986 ,'PYPATCH':".%d"%sys.version_info[2]
2987 ,'PYARCH':str(pyarch)
2988 ,'INSTARCH':str(instarch)
2989 }
2990 # support up to 5 extra dependency DLLs to accompany IPOPT
2991 for i in range(5):
2992 _fl = ''; _dl = ''
2993 if env.get('IPOPT_DLL%d'%(i+1)):
2994 _fl = "File %s"%os.path.normcase(os.path.normpath(env.subst("$IPOPT_DLL%d"%(i+1))))
2995 _dl = "Delete \"$$INSTDIR\\%s\""%os.path.split(env.subst("$IPOPT_DLL%d"%(i+1)))[1]
2996 nsisdefs['FILE_IPOPT_%d'%(i+1)] = _fl
2997 nsisdefs['DEL_IPOPT_%d'%(i+1)] = _dl
2998 env.Append(NSISDEFINES=nsisdefs)
2999 installer = env.Installer('nsis/installer.nsi')
3000
3001 for i in range(5):
3002 if env.get('IPOPT_DLL%d'%(i+1)):
3003 env.Depends(installer,env['IPOPT_DLL%d'%(i+1)])
3004
3005 env.Depends(installer,["pygtk","ascxx","tcltk","ascend.dll","models","solvers","ascend-config",'pygtk/ascend'])
3006 env.Depends(installer,"doc/book.pdf")
3007 env.Depends(installer,["nsis/detect.nsi","nsis/dependencies.nsi","nsis/download.nsi"])
3008 env.Alias('installer',installer)
3009 else:
3010 print "Skipping... Windows installer isn't being built:",without_installer_reason
3011
3012 #------------------------------------------------------
3013 # CREATE the SPEC file for generation of RPM packages
3014
3015 if platform.system()=="Linux":
3016 env.SubstInFile('ascend.spec.in')
3017
3018 #------------------------------------------------------
3019 # CREATE OMF FILE FOR USE WITH SCROLLKEEPER
3020
3021 #if with_scrollkeeper:
3022 # #env.SubstInFile('#/pygtk/gnome/ascend.omf.in')
3023 # #env.InstallShared(env['INSTALL_ROOT']+env['OMFDIR'],"#/pygtk/gnome/ascend.omf")
3024
3025 #------------------------------------------------------
3026 # DISTRIBUTION TAR FILE
3027
3028 env['DISTTAR_FORMAT']='bz2'
3029 env.Append(
3030 DISTTAR_EXCLUDEEXTS=['.o','.os','.so','.a','.dll','.lib','.cc','.cache',
3031 '.pyc','.cvsignore','.dblite','.log','.pl','.out','.exe','.aux','.idx',
3032 '.toc','.lof','.lot','.mm','.warnings','.tm2','.swp',',tmp','.gz',
3033 '.bz2','.7z','.deb','.dsc','.changes','.bak','.tex','.tmp','.def']
3034 , DISTTAR_EXCLUDEDIRS=['CVS','.svn','.sconf_temp', 'dist','debian','doxy']
3035 , DISTTAR_EXCLUDERES=[r"_wrap\.cc?$", r"~$", r"ascxx/ascpy\.py","ascxx/testipopt$"
3036 ,r"/lib.*\.so\.[.0-9]+$", r"tcltk/asc4dev$", r"tcltk/interface/typelex\.c$"
3037 ,r"ascend/compiler/ascParse\.[ch]$", r"ascend/solver/conoptconfig\.h$"
3038 ,r"ascend/utilities/config\.h$", r"pygtk/config\.h$", r"pygtk/config\.py$"
3039 ,r"pygtk/ascdev$", r"ascxx/testconopt$", r"ascend/compiler/scanner\.c$"
3040 ,r"datareader/.*TY\.csv$"
3041 ,r"[a-z]+/.*/.*\.spec$"
3042 ,r"ascxx/ascpy_wrap\.h",r"ascxx/config\.h$"
3043 ,r"tcltk/interface/ascend4$",r"ascxx/testslvreq$",r"test/test$"
3044 ,r"models/johnpye/datareader/.*\.tm2\.Z$"
3045 ,r"models/johnpye/fprops/[a-z][a-z0-9]+(.*\.exe)?$" # FPROPS test executables
3046 ,r"fprops/fluids/fluids_list\.h$" # FPROPS fluids list
3047 ,r"fprops/test/ph$"
3048 ,r"fprops/test/sat$"
3049 ,r"fprops/test/sat1$"
3050 ]
3051 )
3052
3053 tar = env.DistTar("dist/"+env['DISTTAR_NAME']
3054 , [env.Dir('#')]
3055 )
3056
3057 env.Depends(tar,'ascend.spec')
3058 env.Depends(tar,'doc/book.pdf')
3059
3060 #------------------------------------------------------
3061 # DEBIAN TARBALL for use with Build Service
3062
3063 import glob
3064 deb_files = glob.glob('debian/*.install')
3065 deb_files += glob.glob('debian/*.docs')
3066 deb_files += glob.glob('debian/*.dirs')
3067 deb_files += glob.glob('debian/*.man')
3068 deb_files += glob.glob('debian/*.manpages')
3069 deb_files += ['debian/%s' % s for s in ['rules','control','changelog','compat','copyright','dirs']]
3070
3071 deb_tar = env.Tar(
3072 'dist/debian.tar.gz'
3073 ,deb_files
3074 ,TARFLAGS = ['cz']
3075 )
3076
3077 Alias('dist',[tar,deb_tar])
3078
3079 #------------------------------------------------------
3080 # DOCUMENTATION
3081
3082 #print "WITH_DOC_BUILD = ",with_doc_build
3083
3084 if with_doc_build:
3085 #user's manual
3086 env.SConscript('doc/SConscript',['env'])
3087 else:
3088 print "Skipping... Documentation isn't being built:",without_doc_build_reason
3089
3090 #------------------------------------------------------
3091 # RPM BUILD
3092
3093 # for RPM builds, 'scons dist' then 'rpmbuild -ta dist/ascend-*.tar.bz2'
3094 # (check * for the version number used to create the tarball)
3095
3096 #------------------------------------------------------
3097 # DEFAULT TARGETS
3098
3099 default_targets =['libascend','solvers']
3100 if with_tcltk:
3101 default_targets.append('tcltk')
3102 if with_python:
3103 default_targets.append('ascxx')
3104 default_targets.append('pygtk')
3105 default_targets.append('pyfprops')
3106 if with_extfns:
3107 default_targets.append('extfns')
3108 if with_doc_build:
3109 default_targets.append('doc')
3110
3111 env.Default(default_targets)
3112
3113 print "Building targets:"," ".join([str(i) for i in BUILD_TARGETS])
3114
3115 # vim: set syntax=python:

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