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

Contents of /branches/georgy/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3135 - (show annotations) (download)
Sun Jun 26 21:19:37 2016 UTC (3 years, 2 months ago) by georgy
File size: 82036 byte(s)
Request Python environment when using msys2.
1 #!/usr/bin/env 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 def CheckWindowsPythonEnvironment(context):
1567 context.Message("Checking for Windows Python environment...")
1568
1569 windows_python = 'undefined'
1570
1571 if sys.platform == 'win32':
1572 if os.name == 'nt':
1573 # native win32 Python
1574 if os.path.sep == '\\':
1575 windows_python = 'native'
1576 # mingw64 Python
1577 elif os.path.sep == '/':
1578 windows_python = 'mingw64'
1579 else:
1580 pass
1581
1582 elif sys.platform == 'msys':
1583 # msys2 Python
1584 if os.name == 'posix' and os.path.sep == '/':
1585 windows_python = 'msys2'
1586
1587 else:
1588 pass
1589
1590 context.env['WINDOWS_PYTHON'] = windows_python
1591
1592 return windows_python
1593
1594 #----------------
1595 # libpython test
1596
1597 libpython_test_text = """
1598 #include <Python.h>
1599 PyObject *get10(void){
1600 PyObject *p = Py_BuildValue("i", 10);
1601 return p;
1602 }
1603 int main(void){
1604 return 0;
1605 }
1606 """
1607
1608 def pythoncall(env,expr1):
1609 """
1610 Evaluate a Python string, using the version of Python specified
1611 """
1612 import subprocess
1613 import os
1614 fn = "scons%d" % os.getpid()
1615 while os.path.exists(fn):
1616 fn = fn + "0"
1617 try:
1618 f = file(fn,"w")
1619 f.write("#!python\nimport sys\nprint sys.argv[1]")
1620 f.close()
1621 p1 = subprocess.Popen(
1622 ["sh.exe","-c","%s -c \"%s\""%(env['PYTHON'],expr1,)]
1623 ,stdout=subprocess.PIPE
1624 )
1625 out = p1.communicate()[0].strip()
1626 except Exception,e:
1627 print "FAILED: %s"%str(e)
1628 finally:
1629 os.unlink(fn)
1630 return out
1631
1632
1633 def CheckPythonLib(context):
1634 context.Message('Checking for libpython... ')
1635
1636 if context.env['WINDOWS_PYTHON'] == 'msys2':
1637 context.Result("PYTHON not specified (using msys2); Provide either native or mingw64 Python executable")
1638
1639 elif 0 and context.env['PYTHON'] is not None:
1640 # get the parameters by running a specified python executable
1641 context.Result("PYTHON specified; not yet implemented")
1642 else:
1643 # get the parameter from this python that is powering SCons
1644 python_cpppath = [distutils.sysconfig.get_python_inc()]
1645 python_h = os.path.join(python_cpppath[0],"python.h")
1646 v = distutils.sysconfig.get_config_vars()
1647 python_lib = "python%s"%v['VERSION']
1648 if sys.platform=="win32":
1649 # 'native' win32 is a special case for library name and location
1650 python_so = "python%s%s"%(v['VERSION'],context.env.get('SHLIBSUFFIX'))
1651 python_libpath = [os.path.join(sys.prefix,"Libs")]
1652 else:
1653 python_so = v['INSTSONAME']
1654 python_libpath = [v['LIBDIR']]
1655 python_cpppath += [v['INCLUDEDIR']]
1656
1657 # TODO restore settings for Darwin here... LIBPL and LIBS
1658
1659 # check that header and library files were found
1660 if not os.path.exists(python_h):
1661 context.Result("'python.h' not found.")
1662 if not os.path.exists(os.path.join(python_libpath[0],python_so)):
1663 context.Results("'%s' not found."%python_so)
1664
1665 context.env['PYTHON_LIBS']=[python_lib]
1666 context.env['PYTHON_LIBPATH']=python_libpath
1667 context.env['PYTHON_CPPPATH']=python_cpppath
1668 context.env['PYTHON_LIBFLAGS']=[]
1669
1670 # check that we can link against the python library
1671 return CheckExtLib(context,python_lib,libpython_test_text,varprefix="PYTHON")
1672
1673 if 0:
1674 if sys.platform=="msys":
1675 print "\nsys.executable",sys.executable
1676 print "PYTHON =",env['PYTHON']
1677 print "PYTHON sys.executable",pythoncall(env,"import sys;print sys.executable")
1678 print "PYTHON get_python_inc()",pythoncall(env,"import distutils.sysconfig as d;print d.get_python_inc()")
1679 print "PYTHON LIBDIR",pythoncall(env,"import distutils.sysconfig as d;print d.get_config_vars()['LIBDIR']")
1680 print "PYTHON LDLIBRARY",pythoncall(env,"import distutils.sysconfig as d;print d.get_config_vars()['LDLIBRARY']")
1681
1682 python_lib='python%d.%d'
1683 if sys.platform=="win32":
1684 python_lib='python%d%d'
1685 try:
1686 python_libs = [python_lib % (sys.version_info[0],sys.version_info[1])]
1687 python_cpppath = [distutils.sysconfig.get_python_inc()]
1688 cfig = distutils.sysconfig.get_config_vars()
1689 except:
1690 context.Result("not found")
1691 return 0
1692
1693 lastLIBS = context.env.get('LIBS')
1694 lastLIBPATH = context.env.get('LIBPATH')
1695 lastCPPPATH = context.env.get('CPPPATH')
1696 lastLINKFLAGS = context.env.get('LINKFLAGS')
1697
1698 python_libpath = []
1699 python_linkflags = []
1700 if sys.platform=="win32":
1701 python_libpath += [os.path.join(sys.prefix,"libs")]
1702 elif sys.platform=="msys2":
1703 python_libpath += pythoncall(env,
1704 "import distutils.sysconfig as d;print d.get_config_vars()['LIBDIR']")
1705 print
1706 elif platform.system()=="Darwin":
1707 python_libpath += [cfig['LIBPL']]
1708 python_linkflags += cfig['LIBS'].split(' ')
1709 else:
1710 # checked on Linux and SunOS
1711 if cfig['LDLIBRARY']==cfig['LIBRARY']:
1712 sys.stdout.write("(static)")
1713 python_libpath += [cfig['LIBPL']]
1714 python_linkflags += cfig['LIBS'].split(' ')
1715
1716 context.env.AppendUnique(LIBS=python_libs)
1717 context.env.AppendUnique(LIBPATH=python_libpath)
1718 context.env.AppendUnique(CPPPATH=python_cpppath)
1719 context.env.AppendUnique(LINKFLAGS=python_linkflags)
1720 result = context.TryLink(libpython_test_text,".c");
1721
1722 context.Result(result)
1723
1724 if(result):
1725 context.env['PYTHON_LIBPATH']=python_libpath
1726 context.env['PYTHON_LIB']=python_libs
1727 context.env['PYTHON_CPPPATH']=python_cpppath
1728 context.env['PYTHON_LINKFLAGS']=python_linkflags
1729
1730 context.env['LIBS'] = lastLIBS
1731 context.env['LIBPATH'] = lastLIBPATH
1732 context.env['CPPPATH'] = lastCPPPATH
1733 context.env['LINKFLAGS'] = lastLINKFLAGS
1734
1735 return result
1736
1737 #----------------
1738 # IDA test
1739
1740 sundials_version_major_required = 2
1741 sundials_version_minor_min = 4
1742 sundials_version_minor_max = 4
1743
1744 sundials_version_text = """
1745 #include <sundials/sundials_config.h>
1746 #include <stdio.h>
1747 int main(){
1748 printf("%s",SUNDIALS_PACKAGE_VERSION);
1749 return 0;
1750 }
1751 """
1752
1753 ida_test_text = """
1754 #if SUNDIALS_VERSION_MAJOR==2 && SUNDIALS_VERSION_MINOR==2
1755 # include <sundials/sundials_config.h>
1756 # include <sundials/sundials_nvector.h>
1757 # include <nvector_serial.h>
1758 # include <ida.h>
1759 # include <ida/ida_spgmr.h>
1760 #else
1761 # include <sundials/sundials_config.h>
1762 # include <nvector/nvector_serial.h>
1763 # include <ida/ida.h>
1764 #endif
1765 int main(){
1766 void *ida_mem;
1767 ida_mem = IDACreate();
1768 return 0;
1769 }
1770 """
1771
1772 # slightly changed calling convention (IDACalcID) in newer versions of SUNDIALS,
1773 # so detect the version and act accordingly.
1774 def CheckSUNDIALS(context):
1775 keep = KeepContext(context,'SUNDIALS')
1776 context.Message("Checking for SUNDIALS... ")
1777 (is_ok,output) = context.TryRun(sundials_version_text,'.c')
1778 keep.restore(context)
1779 if not is_ok:
1780 context.Result(0)
1781 return 0
1782
1783 major,minor,patch = tuple([int(i) for i in output.split(".")])
1784 context.env['SUNDIALS_VERSION_MAJOR'] = major
1785 context.env['SUNDIALS_VERSION_MINOR'] = minor
1786 if major != sundials_version_major_required \
1787 or minor < sundials_version_minor_min \
1788 or minor > sundials_version_minor_max:
1789 context.Result(output+" (bad version)")
1790 # bad version
1791 return 0
1792
1793 # good version
1794 context.Result("%d.%d.%d, good" % (major,minor,patch))
1795
1796 return 1
1797
1798
1799 def CheckIDA(context):
1800 context.Message( 'Checking for IDA... ' )
1801
1802 keep = KeepContext(context,"SUNDIALS")
1803
1804 major = context.env['SUNDIALS_VERSION_MAJOR']
1805 minor = context.env['SUNDIALS_VERSION_MINOR']
1806
1807 cppdef = context.env.get('CPPDEFINES')
1808
1809 context.env.Append(CPPDEFINES=[
1810 ('SUNDIALS_VERSION_MAJOR',"$SUNDIALS_VERSION_MAJOR")
1811 ,('SUNDIALS_VERSION_MINOR',"$SUNDIALS_VERSION_MINOR")
1812 ])
1813
1814 context.env['SUNDIALS_CPPPATH_EXTRA']=[]
1815 if major==2 and minor==2:
1816 context.env.Append(SUNDIALS_CPPPATH_EXTRA = ["$SUNDIALS_CPPPATH/sundials"])
1817
1818 context.env.Append(CPPDEFINES=[('SUNDIALS_VERSION_MAJOR',"$SUNDIALS_VERSION_MAJOR"),('SUNDIALS_VERSION_MINOR',"$SUNDIALS_VERSION_MINOR")])
1819 context.env.AppendUnique(LIBS=context.env['SUNDIALS_LIBS'])
1820 context.env.AppendUnique(CPPPATH=context.env['SUNDIALS_CPPPATH_EXTRA'])
1821
1822 is_ok = context.TryLink(ida_test_text,".c")
1823 context.Result(is_ok)
1824
1825 if cppdef:
1826 context.env['CPPDEFINES']=cppdef
1827 else:
1828 del context.env['CPPDEFINES']
1829
1830 keep.restore(context)
1831
1832 return is_ok
1833
1834
1835 #----------------
1836 # CONOPT test
1837
1838 conopt_test_text = """
1839 #if !defined(_WIN32)
1840 # define FNAME_LCASE_DECOR
1841 #endif
1842
1843 #include <conopt.h>
1844 #include <stdlib.h>
1845 int main(){
1846 int s, *v, e;
1847 s = COIDEF_Size();
1848 v = (int *)malloc(s*sizeof(int));
1849 e = COIDEF_Ini(v);
1850 return e;
1851 }
1852 """
1853
1854 def CheckCONOPT(context):
1855 context.Message( 'Checking for CONOPT... ' )
1856
1857 keep = KeepContext(context,"CONOPT")
1858
1859 is_ok = context.TryLink(conopt_test_text,".c")
1860 context.Result(is_ok)
1861
1862 keep.restore(context)
1863
1864 return is_ok
1865
1866 #----------------
1867 # IPOPT test
1868
1869 ipopt_test_text = """
1870 #if !defined(_WIN32)
1871 # define FNAME_LCASE_DECOR
1872 #endif
1873
1874 #include <coin/IpStdCInterface.h>
1875 int main(){
1876 Number n;
1877 IpoptProblem nlp = 0;
1878 n = 1;
1879 FreeIpoptProblem(nlp); // probably a crash if you run this
1880 return 0;
1881 }
1882 """
1883
1884 def CheckIPOPT(context):
1885 context.Message( 'Checking for IPOPT... ' )
1886
1887 keep = KeepContext(context,"IPOPT")
1888 is_ok = context.TryLink(ipopt_test_text,".c")
1889 context.Result(is_ok)
1890
1891 keep.restore(context)
1892
1893 return is_ok
1894
1895 #----------------
1896 # Tcl test
1897
1898 # TCL and TK required version 8.1 through 8.5:
1899 tcltk_minor_newest_acceptable = 5
1900 tcltk_major_required = 8
1901
1902 tcl_check_text = r"""
1903 #include <tcl.h>
1904 #include <stdio.h>
1905 int main(void){
1906 printf("%s",TCL_PATCH_LEVEL);
1907 return 0;
1908 }
1909 """
1910
1911 def CheckTcl(context):
1912 return CheckExtLib(context,'tcl',tcl_check_text,static=env['STATIC_TCLTK'])
1913
1914 def CheckTclVersion(context):
1915 keep = KeepContext(context,'TCL',static=env['STATIC_TCLTK'])
1916 context.Message("Checking Tcl version... ")
1917 (is_ok,output) = context.TryRun(tcl_check_text,'.c')
1918 keep.restore(context)
1919 if not is_ok:
1920 context.Result("failed to run check")
1921 return 0
1922
1923 major,minor,patch = tuple([int(i) for i in output.split(".")])
1924 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
1925 context.Result(output+" (bad version)")
1926 # bad version
1927 return 0
1928
1929 # good version
1930 context.Result(output+", good")
1931 return 1
1932
1933 #----------------
1934 # Tk test
1935
1936 tk_check_text = r"""
1937 #include <tk.h>
1938 #include <stdio.h>
1939 int main(void){
1940 printf("%s",TK_PATCH_LEVEL);
1941 return 0;
1942 }
1943 """
1944 def CheckTk(context):
1945 return CheckExtLib(context,'tk',tk_check_text,static=env['STATIC_TCLTK'])
1946
1947
1948 def CheckTkVersion(context):
1949 keep = KeepContext(context,'TK',static=context.env['STATIC_TCLTK'])
1950 context.Message("Checking Tk version... ")
1951 #print "LINKFLAGS =",context.env['LINKFLAGS']
1952 (is_ok,output) = context.TryRun(tk_check_text,'.c')
1953 keep.restore(context)
1954 if not is_ok:
1955 context.Result("failed to run check")
1956 return 0
1957
1958 major,minor,patch = tuple([int(i) for i in output.split(".")])
1959 if major != tcltk_major_required or minor > tcltk_minor_newest_acceptable:
1960 # bad version
1961 context.Result(output+" (bad version)")
1962 return 0
1963
1964 # good version
1965 context.Result(output+" (good)")
1966 return 1
1967
1968 #----------------
1969 # Tktable test
1970
1971 tktable_check_text = r"""
1972 #include <tkTable.h>
1973 #include <stdio.h>
1974 int main(void){
1975 Table mytable;
1976 return 0;
1977 }
1978 """
1979
1980 def CheckTkTable(context):
1981 return CheckExtLib(context,'tktable',tktable_check_text,static=env['STATIC_TCLTK'])
1982
1983 #---------------
1984 # X11 test
1985
1986 x11_check_text = r"""
1987 #include <X11/Xlib.h>
1988 #include <X11/IntrinsicP.h>
1989 #include <X11/Intrinsic.h>
1990 #include <X11/ObjectP.h>
1991 #include <X11/Object.h>
1992 int main(void){
1993 Object mything;
1994 return 0;
1995 }
1996 """
1997
1998 def CheckX11(context):
1999 return CheckExtLib(context,'X11',x11_check_text)
2000
2001 #----------------
2002 # Check that we can raise and catch sigint
2003
2004 sigint_test_text = r"""
2005 #include <signal.h>
2006 #include <setjmp.h>
2007 #include <stdlib.h>
2008 static jmp_buf g_jmpenv;
2009 void sighandler(int sig){
2010 longjmp(g_jmpenv,sig);
2011 }
2012 void testsigint(){
2013 raise(SIGINT);
2014 }
2015 int main(void){
2016 signal(SIGINT,&sighandler);
2017 switch(setjmp(g_jmpenv)){
2018 case 0:
2019 testsigint();
2020 exit(1);
2021 case SIGINT:
2022 exit(0);
2023 default:
2024 exit(2);
2025 }
2026 }
2027 """
2028
2029 def CheckSIGINT(context):
2030 context.Message("Checking SIGINT is catchable... ")
2031 (is_ok,output)=context.TryRun(sigint_test_text,".c")
2032 context.Result(is_ok)
2033 return is_ok
2034
2035 #----------------
2036 # Check that we're able to catch floating point errors
2037
2038 sigfpe_test_text = r"""
2039 #include <signal.h>
2040 #include <setjmp.h>
2041 #include <stdlib.h>
2042 #include <fenv.h>
2043 static jmp_buf g_jmpenv;
2044 void fpehandler(int sig){
2045 longjmp(g_jmpenv,sig);
2046 }
2047 int main(void){
2048 fenv_t myfenv;
2049 fegetenv(&myfenv);
2050 fesetenv(&myfenv);
2051 feenableexcept(FE_ALL_EXCEPT);
2052 signal(SIGFPE,&fpehandler);
2053 double x;
2054 switch(setjmp(g_jmpenv)){
2055 case 0:
2056 x = 1.0 / 0.0;
2057 /* failed to catch */
2058 exit(1);
2059 case SIGFPE:
2060 exit(0);
2061 }
2062 }
2063 """
2064
2065 def CheckFPE(context):
2066 context.Message("Checking C99 FPE behaviour... ")
2067 (is_ok,output) = context.TryRun(sigfpe_test_text,'.c')
2068 context.Result(is_ok)
2069 return is_ok
2070
2071 #----------------
2072 # signal reset needed?
2073
2074 sigreset_test_text = r"""
2075 #include <signal.h>
2076 #include <setjmp.h>
2077 #include <stdlib.h>
2078 #include <stdio.h>
2079 typedef void SigHandlerFn(int);
2080 static jmp_buf g_jmpenv;
2081 void sighandler(int sig){
2082 longjmp(g_jmpenv,sig);
2083 }
2084 void testsigint(){
2085 /* fprintf(stderr,"Raising SIGINT\n"); */
2086 raise(SIGINT);
2087 }
2088 int main(void){
2089 SigHandlerFn *last,*saved;
2090 saved = signal(SIGINT,&sighandler);
2091 if(saved!=SIG_DFL){
2092 fprintf(stderr,"Default handler (%p) was not correctly set\n",SIG_DFL);
2093 exit(3);
2094 }
2095 switch(setjmp(g_jmpenv)){
2096 case 0:
2097 testsigint();
2098 fprintf(stderr,"Back from SIGINT\n");
2099 exit(1);
2100 case SIGINT:
2101 break;
2102 default:
2103 exit(2);
2104 };
2105 last = signal(SIGINT,SIG_DFL);
2106 if(last!=&sighandler){
2107 printf("1");
2108 exit(0);
2109 }
2110 printf("0");
2111 exit(0);
2112 }
2113 """
2114
2115 def CheckSigReset(context):
2116 context.Message("Checking signal handler reset... ")
2117 libsave=context.env.get('LIBS')
2118 context.env.AppendUnique(LIBS=['m'])
2119 (is_ok,output) = context.TryRun(sigreset_test_text,'.c')
2120
2121 if libsave is None:
2122 del(context.env['LIBS'])
2123 else:
2124 context.env['LIBS']=libsave
2125
2126 if not is_ok:
2127 context.Result("ERROR")
2128 return False
2129 if int(output)==1:
2130 context.Result("required");
2131 context.env['ASC_RESETNEEDED'] = True
2132 else:
2133 context.Result("not required");
2134 context.env['ASC_RESETNEEDED'] = False
2135 return True
2136
2137 #----------------
2138 # LyX on this system?
2139
2140 def CheckLyx(context):
2141 context.Message("Checking for LyX... ")
2142 r = context.env.WhereIs("lyx")
2143 if r:
2144 context.Result(r)
2145 else:
2146 context.Result(0)
2147 return r
2148
2149 #----------------
2150 # Latex2HTML on this system?
2151
2152 def CheckLatex2HTML(context):
2153 context.Message("Checking for latex2html...")
2154 if context.env.WhereIs("latex2html"):
2155 r = True
2156 else:
2157 r = False
2158 context.Result(r)
2159 return r
2160
2161 #----------------
2162 # Check usable 'erf' function
2163
2164 erf_test_text = r"""
2165 #include <math.h>
2166 int main(){
2167 double x = erf(0.5);
2168 return 0;
2169 }
2170 """
2171 def CheckErf(context):
2172 context.Message("Checking for erf... ")
2173 libsave=context.env.get('LIBS')
2174 context.env.AppendUnique(LIBS=['m'])
2175 (is_ok,output) = context.TryRun(erf_test_text,'.c')
2176 context.Result(is_ok)
2177
2178 #----------------
2179 # GCC Version sniffing
2180
2181 # TODO FIXME
2182
2183 gcc_version4 = False
2184
2185 #------------------------------------------------------
2186 # CONFIGURATION
2187
2188 conf = Configure(env
2189 , custom_tests = {
2190 'CheckCC' : CheckCC
2191 , 'CheckCXX' : CheckCXX
2192 , 'CheckFortran' : CheckFortran
2193 , 'CheckMath' : CheckMath
2194 , 'CheckMalloc' : CheckMalloc
2195 , 'CheckASan' : CheckASan
2196 , 'CheckDLOpen' : CheckDLOpen
2197 , 'CheckSwigVersion' : CheckSwigVersion
2198 , 'CheckWindowsPythonEnvironment' : CheckWindowsPythonEnvironment
2199 , 'CheckPythonLib' : CheckPythonLib
2200 , 'CheckCUnit' : CheckCUnit
2201 , 'CheckDMalloc' : CheckDMalloc
2202 , 'CheckLyx' : CheckLyx
2203 , 'CheckLatex2HTML' : CheckLatex2HTML
2204 , 'CheckGraphVizAgraph' : CheckGraphVizAgraph
2205 , 'CheckGraphVizCgraph' : CheckGraphVizCgraph
2206 , 'CheckGraphVizBoolean' : CheckGraphVizBoolean
2207 , 'CheckUFSparse' : CheckUFSparse
2208 , 'CheckTcl' : CheckTcl
2209 , 'CheckTclVersion' : CheckTclVersion
2210 , 'CheckTk' : CheckTk
2211 , 'CheckTkVersion' : CheckTkVersion
2212 , 'CheckGcc' : CheckGcc
2213 , 'CheckGccVisibility' : CheckGccVisibility
2214 , 'CheckYacc' : CheckYacc
2215 , 'CheckLex' : CheckLex
2216 , 'CheckLexDestroy' : CheckLexDestroy
2217 , 'CheckTkTable' : CheckTkTable
2218 , 'CheckX11' : CheckX11
2219 , 'CheckIDA' : CheckIDA
2220 , 'CheckSUNDIALS' : CheckSUNDIALS
2221 , 'CheckCONOPT' : CheckCONOPT
2222 , 'CheckIPOPT' : CheckIPOPT
2223 , 'CheckScrollkeeperConfig' : CheckScrollkeeperConfig
2224 , 'CheckFPE' : CheckFPE
2225 , 'CheckSIGINT' : CheckSIGINT
2226 , 'CheckSigReset' : CheckSigReset
2227 , 'CheckErf' : CheckErf
2228 # , 'CheckIsNan' : CheckIsNan
2229 # , 'CheckCppUnitConfig' : CheckCppUnitConfig
2230 }
2231 # , config_h = "config.h"
2232 )
2233
2234 def sconsversioncheck():
2235
2236 # uncomment the following line to skip the version check:
2237 # return 1
2238
2239 import SCons
2240 v = SCons.__version__.split(".")
2241 if v[0] != '0':
2242 if v[0] == '1' or v[0] == '2':
2243 return 1;
2244 return 0
2245 if int(v[1]) >= 97:
2246 return 1
2247 if v[1] != '96':
2248 return 0
2249 micro = int(v[2])
2250 if micro == 92 or micro == 93 or micro == 96:
2251 return 1;
2252 return 0
2253
2254 if not sconsversioncheck():
2255 print "Scons version is not OK. Please try version 0.96.92 or 0.96.93,"
2256 print "or consult the developers in the case of newer versions. Modify"
2257 print "the function 'sconsversioncheck' in the file SConstruct if you"
2258 print "want to *force* SCons to continue."
2259 Exit(1)
2260
2261 # check C compiler
2262
2263 if conf.CheckCC() is False:
2264 print "Failed to build simple test file with your C compiler."
2265 print "Check your compiler is installed and running correctly."
2266 Exit(1)
2267
2268 if conf.CheckCXX() is False:
2269 print "Failed to build simple test file with your C++ compiler."
2270 print "Check your compiler is installed and running correctly."
2271 print "You can set your C++ compiler using the CXX scons option."
2272 Exit(1)
2273
2274 if conf.CheckASan() is False:
2275 conf.env['HAVE_ASAN'] = True
2276 else:
2277 conf.env['HAVE_ASAN'] = False
2278
2279 # stdio -- just to check that compiler is behaving
2280
2281 if conf.CheckHeader('stdio.h') is False:
2282 print "CPPPATH =",env.get('CPPPATH')
2283 print "Did not find 'stdio.h'! Check your compiler configuration."
2284 print ""
2285 print "You environment is printed here:"
2286 for k,v in os.environ.iteritems():
2287 print "%-30s%s" % ("%s :" % k, v)
2288 Exit(1)
2289
2290 # sizes of vars used in libascend eg in gl_list etc.
2291
2292 _sizes = {
2293 "VOID_P" : "void *"
2294 ,"INT" : "int"
2295 ,"LONG" : "long"
2296 ,"LONG_LONG" : "long long"
2297 ,"UINT" : "unsigned int"
2298 ,"ULONG" : "unsigned long"
2299 ,"ULONGLONG" : "unsigned long long"
2300 }
2301
2302 for _var,_type in _sizes.iteritems():
2303 _size = conf.CheckTypeSize(_type)
2304 if not _size:
2305 print "Couldn't determine 'sizeof(%s)'" % _type
2306 Exit(1)
2307 conf.env["SIZEOF_%s" % _var] = str(_size)
2308
2309 # check for some string functions
2310
2311 if conf.CheckFunc('sprintf') is False:
2312 print "Didn't find sprintf";
2313 Exit(1)
2314
2315 if conf.CheckErf() is False:
2316 print "Didn't find erf";
2317 Exit(1)
2318 else:
2319 conf.env['HAVE_ERF'] = True
2320
2321 if conf.CheckFunc('strdup'):
2322 conf.env['HAVE_STRDUP'] = True
2323
2324 if conf.CheckFunc('snprintf'):
2325 conf.env['HAVE_SNPRINTF'] = True
2326 elif conf.CheckFunc('_snprintf'):
2327 conf.env['HAVE__SNPRINTF'] = True
2328
2329 if conf.CheckFunc('cpow'):
2330 conf.env['HAVE_CPOW'] = True
2331
2332 # attempt to support MSVCRT 7.1 on Windows
2333
2334 if platform.system()=="Windows" and env.get('WITH_MSVCR71'):
2335 conf.env.Append(LIBS='msvcr71')
2336
2337 # Math library
2338
2339 conf.env['HAVE_IEEE']=True
2340
2341 if need_libm and (conf.CheckMath() is False):
2342 conf.env['HAVE_IEEE']=False
2343 print 'Did not find math library, exiting!'
2344 Exit(1)
2345
2346 # Malloc
2347
2348 if conf.CheckMalloc() is False:
2349 conf.env['HAVE_MALLOC']=False
2350 print "Did not find functioning 'malloc', exiting!"
2351 Exit(1)
2352
2353 # dlopen/LoadLibrary
2354
2355 # CURRENTLY BREAKS LATER TEST (libsave?)
2356 #if conf.CheckDLOpen() is False:
2357 # print "Did not find functioning dlopen/LoadLibrary, exiting!"
2358 # Exit(1)
2359
2360 # Where is 'isnan'?
2361
2362 if conf.CheckFunc('isnan') is False and conf.CheckFunc('_isnan') is False:
2363 print "Didn't find isnan"
2364 # Exit(1)
2365
2366 # GCC visibility
2367
2368 if conf.CheckGcc():
2369 conf.env['HAVE_GCC']=True;
2370 if env.get('WITH_GCCVISIBILITY') and conf.CheckGccVisibility():
2371 conf.env['HAVE_GCCVISIBILITY']=True;
2372 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
2373 conf.env.Append(CPPDEFINES=['HAVE_GCCVISIBILITY'])
2374 conf.env.Append(CCFLAGS=['-Wall'])
2375
2376 # Catching SIGINT
2377
2378 if env['WITH_SIGNALS']:
2379 if not conf.CheckSIGINT():
2380 with_signals = False
2381 without_signals_reason = "SIGINT uncatchable"
2382
2383 # Catching SIGFPE
2384
2385 if conf.CheckFPE():
2386 conf.env['HAVE_C99FPE']=True
2387 else:
2388 conf.env['HAVE_C99FPE']=False
2389
2390 # Checking for signal reset requirement
2391
2392 if conf.CheckSigReset() is False:
2393 print "Unable to determine if signal reset is required"
2394 Exit(1)
2395
2396 # YACC
2397
2398 if conf.CheckYacc():
2399 conf.env['HAVE_YACC']=True
2400
2401 if conf.CheckLex():
2402 conf.env['HAVE_LEX']=True
2403
2404 if conf.CheckLexDestroy():
2405 conf.env['HAVE_LEXDESTROY']=True
2406
2407 # Tcl/Tk
2408
2409 if with_tcltk:
2410 if conf.CheckTcl():
2411 if conf.CheckTclVersion():
2412 if conf.CheckTk():
2413 if with_tcltk and conf.CheckTkVersion():
2414 if env['STATIC_TCLTK']:
2415 if conf.CheckTkTable():
2416 pass
2417 else:
2418 without_tcltk_reason = "TkTable not found"
2419 with_tcltk = False
2420 else:
2421 without_tcltk_reason = "Require Tk version <= 8.4. See 'scons -h'"
2422 with_tcltk = False
2423 else:
2424 without_tcltk_reason = "Tk not found."
2425 with_tcltk = False
2426 else:
2427 without_tcltk_reason = "Require Tcl <= 8.4 Tcl."
2428 with_tcltk = False
2429
2430 else:
2431 without_tcltk_reason = "Tcl not found."
2432 with_tcltk = False
2433
2434 if env['STATIC_TCLTK']:
2435 conf.CheckX11()
2436
2437 # Detect Windows Python environment
2438 conf.CheckWindowsPythonEnvironment()
2439
2440 # Python... obviously we're already running python, so we just need to
2441 # check that we can link to the python library OK:
2442
2443 if not conf.CheckPythonLib():
2444 without_python_reason = 'libpython2.x not found or not linkable'
2445 with_python = False
2446 env['WITH_PYTHON']=False
2447
2448 # SWIG version
2449
2450 if with_python and conf.CheckSwigVersion() is False:
2451 without_python_reason = 'SWIG >= 1.3.24 is required'
2452 with_python = False
2453 env['WITH_PYTHON']=False
2454
2455 # CUnit
2456
2457 if with_cunit:
2458 if not conf.CheckCUnit():
2459 without_cunit_reason = 'CUnit not found'
2460 with_cunit = False
2461 #print "CUNIT NOT FOUND, LIBS=",conf.env.get('LIBS')
2462
2463 # DMALLOC
2464
2465 if with_dmalloc:
2466 if not conf.CheckDMalloc():
2467 without_dmalloc_reason = 'dmalloc not found'
2468 with_dmalloc = False
2469
2470 # GRAPHVIZ
2471
2472 if with_graphviz:
2473 if not conf.CheckGraphVizCgraph():
2474 if not conf.CheckGraphVizAgraph():
2475 without_graphviz_reason = 'graphviz not found (cgraph nor agraph)'
2476 with_graphviz = False
2477 env['WITH_GRAPHVIZ'] = False
2478 env['HAVE_GRAPHVIZ_BOOLEAN'] = conf.CheckGraphVizBoolean()
2479
2480 # UFSPARSE
2481
2482 if with_ufsparse:
2483 if not conf.CheckUFSparse():
2484 without_ufsparse_reason = 'ufsparse not found'
2485 with_ufsparse = False
2486 env['WITH_UFSPARSE'] = False
2487
2488 # IDA
2489
2490 if with_ida:
2491 if not conf.CheckSUNDIALS():
2492 with_ida = False
2493 without_ida_reason = "SUNDIALS not found, or bad version"
2494 elif not conf.CheckIDA():
2495 with_ida = False
2496 without_ida_reason = "Unable to compile/link against SUNDIALS/IDA"
2497
2498 # CONOPT
2499
2500 if not with_conopt:
2501 without_conopt_reason = "Not selected (see config option WITH_SOLVERS)"
2502 elif conf.CheckCONOPT() is False:
2503 if conf.env.get('CONOPT_LINKED'):
2504 conf.env['CONOPT_LINKED'] = False
2505 # we no longer require CONOPT at buildtime in order to build support for it
2506 #with_conopt = False
2507 #without_conpt_reason = "CONOPT not found"
2508
2509 # IPOPT
2510
2511 if not with_ipopt:
2512 without_ipopt_reason = "Not selected (see config option WITH_SOLVERS)"
2513 elif not conf.CheckIPOPT():
2514 with_ipopt = False
2515 without_ipopt_reason = "IPOPT not found"
2516
2517 # BLAS
2518
2519 need_blas=False
2520
2521 if with_lsode:
2522 need_fortran = True
2523 need_fortran_reasons.append("LSODE")
2524 need_blas=True
2525
2526 if with_ipopt:
2527 need_blas=True
2528
2529 if need_blas:
2530 if conf.CheckLib('blas'):
2531 with_local_blas = False
2532 without_local_blas_reason = "Found BLAS installed on system"
2533 else:
2534 with_local_blas = True
2535 need_fortran = True
2536 need_fortran_reasons.append("BLAS")
2537 else:
2538 with_local_blas= False;
2539 without_local_blas_reason = "BLAS not required"
2540
2541 # FORTRAN
2542
2543 # we'll assume now (2012) that we always have gfortran available on our system.
2544
2545 if need_fortran and conf.CheckFortran() is False:
2546 print "Failed to build simple test file with your Fortran compiler."
2547 print "Check your compiler is installed and running correctly."
2548 print "You can set your Fortran compiler using the FORTRAN scons option."
2549 print "The fortran compiler is REQUIRED to build:",", ".join(need_fortran_reasons)
2550 print "Perhaps try examining the value of your WITH_SOLVERS option (remove LSODE, etc)."
2551 Exit(1)
2552
2553 #else:
2554 # print "FORTRAN not required"
2555
2556 # F2C
2557
2558 if need_fortran:
2559 if platform.system()=="Windows":
2560 pass
2561 #conf.env.Append(LIBPATH='c:\mingw\lib')
2562
2563 # scrollkeeper
2564
2565 if with_scrollkeeper:
2566 if conf.CheckScrollkeeperConfig() is False:
2567 with_scrollkeeper=False
2568 without_scrollkeeper_reason="unable to detect scrollkeeper-config"
2569
2570 # lyx
2571
2572 if with_doc_build:
2573 if not conf.CheckLyx():
2574 with_doc_build = False
2575 without_doc_build_reason="unable to locate LyX"
2576
2577 # TODO: -D_HPUX_SOURCE is needed
2578
2579 # TODO: detect if dynamic libraries are possible or not
2580
2581 if platform.system()=="Windows" and env.has_key('MSVS'):
2582 _found_windows_h = conf.CheckHeader('Windows.h')
2583
2584 if not _found_windows_h:
2585 print "Could not locate 'Windows.h' in CPPPATH. Check your configuration."
2586 Exit(1)
2587
2588 if with_python and conf.CheckHeader(['basetsd.h','BaseTsd.h']) is False:
2589 with_python = 0;
2590 without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
2591
2592 conf.Finish()
2593
2594 #print "-=-=-=-=-=-=-=-=- LIBS =",env.get('LIBS')
2595
2596 #---------------------------------------
2597 # SUBSTITUTION DICTIONARY for .in files
2598
2599 release = env.get('RELEASE')
2600 if release=="0.":
2601 release="0"
2602
2603 #print "SUBSTITUTED CONOPT_LIBPATH:",c_escape(env.subst("$CONOPT_LIBPATH"))
2604
2605 subst_dict = {
2606 '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
2607 ,'@DEFAULT_ASCENDSOLVERS@':env['DEFAULT_ASCENDSOLVERS']
2608 , '@GLADE_FILE@':'ascend.glade'
2609 , '@HELP_ROOT@':''
2610 , '@ICON_EXTENSION@':icon_extension
2611 , '@INSTALL_ASCDATA@':env['INSTALL_ASCDATA']
2612 , '@INSTALL_BIN@':env['INSTALL_BIN']
2613 , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
2614 , '@INSTALL_LIB@':env['INSTALL_LIB']
2615 , '@INSTALL_MODELS@':env['INSTALL_MODELS']
2616 , '@INSTALL_SOLVERS@':env['INSTALL_SOLVERS']
2617 , '@INSTALL_PYTHON@':env['INSTALL_PYTHON']
2618 , '@INSTALL_PYTHON_ASCEND@':env['INSTALL_PYTHON_ASCEND']
2619 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
2620 , '@VERSION@':version
2621 , '@RELEASE@':release
2622 , '@SONAME_MAJOR_INT@':soname_major_int
2623 , '@DISTTAR_NAME@':env['DISTTAR_NAME']
2624 , '@WEBHELPROOT@':'http://ascendwiki.cheme.cmu.edu/Category:Documentation'
2625 , '@SHLIBSUFFIX@':env['SHLIBSUFFIX']
2626 , '@SHLIBPREFIX@':env['SHLIBPREFIX']
2627 , '@EXTLIB_SUFFIX@':env['EXTLIB_SUFFIX']
2628 , '@EXTLIB_PREFIX@':env['EXTLIB_PREFIX']
2629 , '@ASC_ENV_TK_DEFAULT@' : '$$ASCENDDIST/tcltk'
2630 , '@PYTHON@' : python_exe
2631 , '@PYVERSION@' : pyversion
2632 , '@SOURCE_ROOT@':c_escape(os.path.abspath(str(env.Dir("#"))))
2633 , '@WITH_GRAPHVIZ@': str(int(env.get('WITH_GRAPHVIZ')))
2634 #define ASC_ABSOLUTE_PATHS @ASC_ABSOLUTE_PATHS@
2635 #if ASC_ABSOLUTE_PATHS
2636 # define ASCENDDIST_DEFAULT "@ASCENDDIST_DEFAULT@"
2637 # define ASCENDTK_DEFAULT "@ASCENDTK_DEFAULT@"
2638 # define ASCENDLIBRARY_DEFAULT "@ASCENDLIBRARY_DEFAULT@"
2639 # define ASCENDSOLVERS_DEFAULT "@ASCENDSOLVERS_DEFAULT@"
2640 #else
2641 # define ASC_DIST_REL_BIN "@ASC_DIST_REL_BIN@"
2642 # define ASC_TK_REL_DIST "@ASC_TK_REL_DIST@"
2643 # define ASC_LIBRARY_REL_DIST "@ASC_LIBRARY_REL_DIST@"
2644 # define ASC_SOLVERS_REL_DIST "@ASC_SOLVERS_REL_DIST@"
2645 #endif
2646 , '@ASC_ABSOLUTE_PATHS@': str(int(env.get('ABSOLUTE_PATHS')))
2647 , '@ASCENDDIST_DEFAULT@': c_escape(env['INSTALL_PREFIX'])
2648 , '@ASCENDTK_DEFAULT@': c_escape(os.path.abspath(env.subst(env['INSTALL_TK'])))
2649 , '@ASCENDLIBRARY_DEFAULT@': c_escape(os.path.abspath(env.subst(env['DEFAULT_ASCENDLIBRARY'])))
2650 , '@ASCENDSOLVERS_DEFAULT@': c_escape(os.path.abspath(env.subst(env['DEFAULT_ASCENDSOLVERS'])))
2651 , '@ASC_DIST_REL_BIN@' : default_dist_rel_bin
2652 , '@ASC_TK_REL_DIST@' : default_tk_rel_dist
2653 , '@ASC_LIBRARY_REL_DIST@' : default_library_rel_dist
2654 , '@ASC_SOLVERS_REL_DIST@' : default_solvers_rel_dist
2655 , '@SIZEOF_VOID_P@' : env['SIZEOF_VOID_P']
2656 , '@SIZEOF_INT@' : env['SIZEOF_INT']
2657 , '@SIZEOF_LONG@' : env['SIZEOF_LONG']
2658 , '@SIZEOF_LONG_LONG@' : env['SIZEOF_LONG_LONG']
2659 , '@SIZEOF_UINT@' : env['SIZEOF_UINT']
2660 , '@SIZEOF_ULONG@' : env['SIZEOF_ULONG']
2661 , '@SIZEOF_ULONGLONG@' : env['SIZEOF_ULONGLONG']
2662 }
2663
2664 if env.get('WITH_DOC'):
2665 #print "WITH_DOC:",env['WITH_DOC']
2666 subst_dict['@HELP_ROOT@']=env['HELP_ROOT']
2667
2668 # bool options...
2669 for k,v in {
2670 'ASC_WITH_DMALLOC':with_dmalloc
2671 ,'ASC_WITH_UFSPARSE':with_ufsparse
2672 ,'ASC_WITH_MMIO':with_mmio
2673 ,'ASC_SIGNAL_TRAPS':with_signals
2674 ,'ASC_RESETNEEDED':env.get('ASC_RESETNEEDED')
2675 ,'HAVE_C99FPE':env.get('HAVE_C99FPE')
2676 ,'HAVE_IEEE':env.get('HAVE_IEEE')
2677 ,'HAVE_ERF':env.get('HAVE_ERF')
2678 ,'ASC_XTERM_COLORS':env.get('WITH_XTERM_COLORS')
2679 ,'MALLOC_DEBUG':env.get('MALLOC_DEBUG')
2680 ,'ASC_HAVE_LEXDESTROY':env.get('HAVE_LEXDESTROY')
2681 ,'HAVE_SNPRINTF':env.get('HAVE_SNPRINTF')
2682 ,'HAVE__SNPRINTF':env.get('HAVE__SNPRINTF')
2683 }.iteritems():
2684
2685 if v: subst_dict["/\\* #\\s*define %s @%s@ \\*/" % (k,k)]='# define %s 1 ' % k
2686
2687 if with_python:
2688 subst_dict['@ASCXX_USE_PYTHON@']="1"
2689 env['WITH_PYTHON']=1;
2690
2691 if with_latex2html:
2692 env['WITH_LATEX2HTML']=1
2693
2694 if env.has_key('HAVE_GCCVISIBILITY'):
2695 subst_dict['@HAVE_GCCVISIBILITY@'] = "1"
2696
2697 env.Append(SUBST_DICT=subst_dict)
2698
2699 #for k,v in subst_dict.iteritems():
2700 # print "%-50s%s" % ("'%s'"%k,v)
2701
2702 # REMOVED: long command-line support on Win2k
2703
2704 #------------------------------------------------------
2705 # RECIPE: SWIG scanner
2706
2707 import SCons.Script
2708
2709 SWIGScanner = SCons.Scanner.ClassicCPP(
2710 "SWIGScan"
2711 , ".i"
2712 , "CPPPATH"
2713 , '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
2714 )
2715
2716 env.Append(SCANNERS=[SWIGScanner])
2717
2718 #------------------------------------------------------
2719 # Recipe for 'CHMOD' ACTION
2720
2721 import SCons
2722 from SCons.Script.SConscript import SConsEnvironment
2723 SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
2724 lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
2725
2726 def InstallPerm(env, dest, files, perm):
2727 obj = env.Install(dest, files)
2728 for i in obj:
2729 env.AddPostAction(i, env.Chmod(str(i), perm))
2730
2731 def InstallPermAs(env, dest, filen, perm):
2732 obj = env.InstallAs(dest, filen)
2733 for i in obj:
2734 env.AddPostAction(i, env.Chmod(str(i), perm))
2735 return dest
2736
2737 SConsEnvironment.InstallPerm = InstallPerm
2738
2739 # define wrappers
2740 SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
2741 SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
2742 SConsEnvironment.InstallShared = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
2743 SConsEnvironment.InstallSharedAs = lambda env, dest, files: InstallPermAs(env, dest, files, 0644)
2744 SConsEnvironment.InstallLibraryAs = lambda env, dest, files: InstallPermAs(env, dest, files, 0644)
2745
2746 #------------------------------------------------------
2747 # BUILD...
2748
2749 # so that #include <ascend/modulename/headername.h> works across all modules...
2750 env.AppendUnique(CPPPATH=['#'])
2751
2752 if env['DEBUG']:
2753 env.Append(
2754 CCFLAGS=['-g']
2755 ,LINKFLAGS=['-g']
2756 )
2757
2758 if env['GCOV']:
2759 env.Append(
2760 CPPFLAGS=['-g','-fprofile-arcs','-ftest-coverage']
2761 , LIBS=['gcov']
2762 , LINKFLAGS=['-fprofile-arcs','-ftest-coverage']
2763 )
2764
2765 #FIXME there must be a better way of doing this...
2766
2767 if with_ida:
2768 env.Append(WITH_IDA=1)
2769
2770 if with_conopt:
2771 env.Append(WITH_CONOPT=1)
2772
2773 if with_ipopt:
2774 env.Append(WITH_IPOPT=1)
2775
2776 if with_dopri5:
2777 env.Append(WITH_DOPRI5=1)
2778
2779 if with_radau5:
2780 env.Append(WITH_RADAU5=1)
2781
2782 if with_makemps:
2783 env.Append(WITH_MAKEMPS=1)
2784
2785 if with_graphviz and env.get('GRAPHVIZ_RPATH'):
2786 env.Append(RPATH=env['GRAPHVIZ_RPATH'])
2787
2788 #-------------
2789 # TCL/TK GUI
2790
2791 if with_tcltk:
2792 env.SConscript(['tcltk/SConscript'],'env')
2793 else:
2794 print "Skipping... Tcl/Tk bindings aren't being built:",without_tcltk_reason
2795
2796 #-------------
2797 # PYTHON INTERFACE
2798
2799 if with_python:
2800 env.SConscript(['ascxx/SConscript'],'env')
2801 env.SConscript(['pygtk/SConscript'],'env')
2802 else:
2803 print "Skipping... Python bindings aren't being built:",without_python_reason
2804
2805 #------------
2806 # BASE/GENERIC SUBDIRECTORIES
2807
2808 libascend_env = env.Clone()
2809
2810 dirs = ['general','utilities','compiler','system','solver','integrator','packages','linear']
2811
2812 srcs = []
2813 for d in dirs:
2814 heresrcs = libascend_env.SConscript('ascend/'+d+'/SConscript','libascend_env')
2815 srcs += heresrcs
2816
2817 #-------------
2818 # IMPORTED CODE: LSODE, BLAS, etc
2819
2820 if with_local_blas:
2821 env['blasobjs'] = env.SConscript(['blas/SConscript'],'env')
2822 else:
2823 env['blasobjs'] = []
2824 print "Skipping... BLAS won't be built:", without_local_blas_reason
2825
2826 if not with_ida:
2827 print "Skipping... IDA won't be built:", without_ida_reason
2828
2829 if not with_dopri5:
2830 print "Skipping... DOPRI5 won't be built:", without_dopri5_reason
2831
2832 if with_mmio:
2833 srcs += env.SConscript(['mmio/SConscript'],'env')
2834 else:
2835 print "Skipping... MMIO export won't be built:", without_mmio_reason
2836 #-------------
2837 # LIBASCEND -- all 'core' functionality
2838
2839 # FIXME want to move these bits to ascend/SConscript
2840
2841 libascend_env.Append(
2842 CPPPATH=['#']
2843 ,LIBS=['m']
2844 )
2845
2846 if platform.system()=="Linux":
2847 libascend_env.Append(LIBS=['dl'])
2848
2849 if with_dmalloc:
2850 libascend_env.Append(LIBS=['dmalloc'])
2851
2852 if with_ufsparse:
2853 libascend_env.Append(LIBS=['cxsparse'])
2854
2855 if platform.system()=="Linux":
2856 libascend_env.Append(LINKFLAGS=['-Wl,-soname,%s' % soname_full])
2857
2858 libascend = libascend_env.SharedLibrary('ascend',srcs)
2859
2860 # create local symlink for the soname stuff.
2861 #print "SONAME =",env.subst(soname_full)
2862
2863 env['libascend'] = libascend
2864 libtargets = [libascend]
2865
2866 if platform.system()=="Linux":
2867 if soname_major:
2868 libascend_env.Command(soname_full,libascend,Move("$TARGET","$SOURCE"))
2869 #print "MAKING LINK, SONAME_MAJOR =",soname_major
2870 liblink = libascend_env.Command(soname_full, libascend, "ln -s $SOURCE $TARGET")
2871 libtargets.append(liblink)
2872
2873 # for use in declaring dependent shared libraries in SConscript files (eg solvers/*/SConscript)
2874
2875 env.Alias('libascend',libtargets)
2876
2877 #-------------
2878 # UNIT TESTS (C CODE)
2879
2880 test_env = env.Clone()
2881 test_env.Append(
2882 CPPPATH="#"
2883 )
2884
2885 if with_cunit:
2886 testdirs = ['general','solver','utilities','linear','compiler','system','packages','integrator']
2887 testsrcs = []
2888 for testdir in testdirs:
2889 path = 'ascend/'+testdir+'/test/'
2890 test_env.SConscript([path+'SConscript'],'test_env')
2891 testsrcs += [i.path for i in test_env['TESTSRCS_'+testdir.upper()]]
2892 test_env['TESTDIRS'] = testdirs
2893
2894 #print "TESTSRCS =",testsrcs
2895
2896 test_env.SConscript(['test/SConscript'],'test_env')
2897
2898 env.Alias('test',[env.Dir('test')])
2899
2900 else:
2901 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
2902
2903 #-------------
2904 # EXTERNAL SOLVERS
2905
2906 env['extfns']=[]
2907 env['BUILDING_ASCEND'] = 1
2908
2909 env.SConscript(['solvers/SConscript'],'env')
2910
2911 #-------------
2912 # EXTERNAL FUNCTIONS
2913
2914 modeldirs = env.SConscript(['models/SConscript'],'env')
2915
2916 if not with_extfns:
2917 print "Skipping... External modules aren't being built:",without_extfns_reason
2918
2919 for _f in env['extfns']:
2920 env.Depends(_f,'libascend')
2921 env.Alias('extfns',env['extfns'])
2922
2923 #-------------
2924 # FPROPS python bindings
2925
2926 env.Alias('pyfprops',env.get('pyfprops'))
2927
2928 #------------------------------------------------------
2929 # CREATE ASCEND-CONFIG scriptlet
2930
2931 ascendconfig = env.SubstInFile('ascend-config.in')
2932
2933 #------------------------------------------------------
2934 # INSTALLATION
2935
2936 if env.get('CAN_INSTALL'):
2937
2938 dirs = ['INSTALL_BIN','INSTALL_ASCDATA','INSTALL_LIB', 'INSTALL_INCLUDE','INSTALL_DOC','INSTALL_PYTHON']
2939 install_dirs = [Dir(env.subst("$INSTALL_ROOT$"+d)) for d in dirs]
2940 install_dirs += modeldirs + [Dir(env.subst("$INSTALL_ROOT$INSTALL_SOLVERS"))]
2941
2942 #env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_LIB")),libascend)
2943
2944 libname = "${INSTALL_LIB}/%s%s" % (soname_full,soname_minor)
2945 install_lib = env.InstallLibraryAs("${INSTALL_ROOT}"+libname, [libascend])
2946 if env['ABSOLUTE_PATHS']:
2947 link_target = libname
2948 else:
2949 link_target = "%s%s" % (soname_full,soname_minor)
2950
2951 link1 = "${INSTALL_LIB}/%s" % soname_clean
2952 install_link1 = None
2953 if env.subst(link1) != env.subst(libname):
2954 # v--link to create v--file to link to command
2955 install_link1 = env.Command("${INSTALL_ROOT}"+link1,install_lib
2956 # v-- command to do it (note the trick about
2957 ,"ln -f -s %s $TARGET" % link_target
2958 )
2959
2960 link2 = "${INSTALL_LIB}/%s" % soname_full
2961 install_link2 = None
2962 if soname_minor:
2963 install_link2 = env.Command("${INSTALL_ROOT}"+link2,install_lib
2964 ,"ln -f -s %s $TARGET" % link_target
2965 )
2966
2967 env.InstallProgram(Dir(env.subst("$INSTALL_ROOT$INSTALL_BIN")),ascendconfig)
2968
2969 # MAC OS X INSTALL STUFF
2970 # in this case, we're installing to INSTALL_PREFIX, assumed to be a folder
2971 # created using Disk Utility as a new DMG which will be distributed.
2972 if platform.system()=="Darwin":
2973 # extra stuff for inside the .app
2974 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_BIN")),"mac/Info.plist")
2975 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_BIN/Resources/")),"mac/ascend.icns")
2976
2977 # related files the .dmg folder
2978 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX")),"README-osx.txt")
2979 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX")),"LICENSE.txt")
2980 env.InstallShared(Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX")),"CHANGELOG.txt")
2981 env.Command("$INSTALL_ROOT$INSTALL_PREFIX/Applications Folder","/Applications","ln -f -s $SOURCE $TARGET")
2982 install_dirs += [Dir(env.subst("$INSTALL_ROOT$INSTALL_PREFIX"))]
2983
2984 # GTK libraries and related files
2985 gtkfiles = []
2986 gtksource = "dist/PyGTK.bundle/"
2987 def visit(gtkfiles,dirname,fnames):
2988 gtkfiles += Glob("%s/*" % dirname)
2989 os.path.walk(gtksource,visit,gtkfiles)
2990
2991 #print "GTKFILES ="
2992 #
2993 for f in gtkfiles:
2994 r = os.path.commonprefix([gtksource,f.path])
2995 dirname,filename = os.path.split(f.path[len(r):])
2996 dest = os.path.join(env.subst("$INSTALL_ROOT$INSTALL_BIN/PyGTK.bundle"),dirname)
2997 # print "%s --> %s" %(f,dest)
2998 env.Install(Dir(dest),f)
2999
3000 # ALIAS FOR ALL INSTALLATION
3001 env.Alias('install',install_dirs)
3002
3003 #------------------------------------------------------
3004 # WINDOWS INSTALLER
3005
3006 if not env.get('NSIS'):
3007 with_installer = False
3008 without_installer_reason = "NSIS not found"
3009
3010 if with_installer:
3011 pyarch = ""
3012 instarch = "win32"
3013 if platform.architecture()[0] == "64bit":
3014 instarch = "x64"
3015 pyarch = ".amd64"
3016 inst64 = 1
3017 nsisdefs = {
3018 'OUTFILE':"#dist/$WIN_INSTALLER_NAME"
3019 ,"VERSION":version
3020 ,'PYVERSION':pyversion
3021 ,'PYPATCH':".%d"%sys.version_info[2]
3022 ,'PYARCH':str(pyarch)
3023 ,'INSTARCH':str(instarch)
3024 }
3025 # support up to 5 extra dependency DLLs to accompany IPOPT
3026 for i in range(5):
3027 _fl = ''; _dl = ''
3028 if env.get('IPOPT_DLL%d'%(i+1)):
3029 _fl = "File %s"%os.path.normcase(os.path.normpath(env.subst("$IPOPT_DLL%d"%(i+1))))
3030 _dl = "Delete \"$$INSTDIR\\%s\""%os.path.split(env.subst("$IPOPT_DLL%d"%(i+1)))[1]
3031 nsisdefs['FILE_IPOPT_%d'%(i+1)] = _fl
3032 nsisdefs['DEL_IPOPT_%d'%(i+1)] = _dl
3033 env.Append(NSISDEFINES=nsisdefs)
3034 installer = env.Installer('nsis/installer.nsi')
3035
3036 for i in range(5):
3037 if env.get('IPOPT_DLL%d'%(i+1)):
3038 env.Depends(installer,env['IPOPT_DLL%d'%(i+1)])
3039
3040 env.Depends(installer,["pygtk","ascxx","tcltk","ascend.dll","models","solvers","ascend-config",'pygtk/ascend'])
3041 env.Depends(installer,"doc/book.pdf")
3042 env.Depends(installer,["nsis/detect.nsi","nsis/dependencies.nsi","nsis/download.nsi"])
3043 env.Alias('installer',installer)
3044 else:
3045 print "Skipping... Windows installer isn't being built:",without_installer_reason
3046
3047 #------------------------------------------------------
3048 # CREATE the SPEC file for generation of RPM packages
3049
3050 if platform.system()=="Linux":
3051 env.SubstInFile('ascend.spec.in')
3052
3053 #------------------------------------------------------
3054 # CREATE OMF FILE FOR USE WITH SCROLLKEEPER
3055
3056 #if with_scrollkeeper:
3057 # #env.SubstInFile('#/pygtk/gnome/ascend.omf.in')
3058 # #env.InstallShared(env['INSTALL_ROOT']+env['OMFDIR'],"#/pygtk/gnome/ascend.omf")
3059
3060 #------------------------------------------------------
3061 # DISTRIBUTION TAR FILE
3062
3063 env['DISTTAR_FORMAT']='bz2'
3064 env.Append(
3065 DISTTAR_EXCLUDEEXTS=['.o','.os','.so','.a','.dll','.lib','.cc','.cache',
3066 '.pyc','.cvsignore','.dblite','.log','.pl','.out','.exe','.aux','.idx',
3067 '.toc','.lof','.lot','.mm','.warnings','.tm2','.swp',',tmp','.gz',
3068 '.bz2','.7z','.deb','.dsc','.changes','.bak','.tex','.tmp','.def']
3069 , DISTTAR_EXCLUDEDIRS=['CVS','.svn','.sconf_temp', 'dist','debian','doxy']
3070 , DISTTAR_EXCLUDERES=[r"_wrap\.cc?$", r"~$", r"ascxx/ascpy\.py","ascxx/testipopt$"
3071 ,r"/lib.*\.so\.[.0-9]+$", r"tcltk/asc4dev$", r"tcltk/interface/typelex\.c$"
3072 ,r"ascend/compiler/ascParse\.[ch]$", r"ascend/solver/conoptconfig\.h$"
3073 ,r"ascend/utilities/config\.h$", r"pygtk/config\.h$", r"pygtk/config\.py$"
3074 ,r"pygtk/ascdev$", r"ascxx/testconopt$", r"ascend/compiler/scanner\.c$"
3075 ,r"datareader/.*TY\.csv$"
3076 ,r"[a-z]+/.*/.*\.spec$"
3077 ,r"ascxx/ascpy_wrap\.h",r"ascxx/config\.h$"
3078 ,r"tcltk/interface/ascend4$",r"ascxx/testslvreq$",r"test/test$"
3079 ,r"models/johnpye/datareader/.*\.tm2\.Z$"
3080 ,r"models/johnpye/fprops/[a-z][a-z0-9]+(.*\.exe)?$" # FPROPS test executables
3081 ,r"fprops/fluids/fluids_list\.h$" # FPROPS fluids list
3082 ,r"fprops/test/ph$"
3083 ,r"fprops/test/sat$"
3084 ,r"fprops/test/sat1$"
3085 ]
3086 )
3087
3088 tar = env.DistTar("dist/"+env['DISTTAR_NAME']
3089 , [env.Dir('#')]
3090 )
3091
3092 env.Depends(tar,'ascend.spec')
3093 env.Depends(tar,'doc/book.pdf')
3094
3095 #------------------------------------------------------
3096 # DEBIAN TARBALL for use with Build Service
3097
3098 import glob
3099 deb_files = glob.glob('debian/*.install')
3100 deb_files += glob.glob('debian/*.docs')
3101 deb_files += glob.glob('debian/*.dirs')
3102 deb_files += glob.glob('debian/*.man')
3103 deb_files += glob.glob('debian/*.manpages')
3104 deb_files += ['debian/%s' % s for s in ['rules','control','changelog','compat','copyright','dirs']]
3105
3106 deb_tar = env.Tar(
3107 'dist/debian.tar.gz'
3108 ,deb_files
3109 ,TARFLAGS = ['cz']
3110 )
3111
3112 Alias('dist',[tar,deb_tar])
3113
3114 #------------------------------------------------------
3115 # DOCUMENTATION
3116
3117 #print "WITH_DOC_BUILD = ",with_doc_build
3118
3119 if with_doc_build:
3120 #user's manual
3121 env.SConscript('doc/SConscript',['env'])
3122 else:
3123 print "Skipping... Documentation isn't being built:",without_doc_build_reason
3124
3125 #------------------------------------------------------
3126 # RPM BUILD
3127
3128 # for RPM builds, 'scons dist' then 'rpmbuild -ta dist/ascend-*.tar.bz2'
3129 # (check * for the version number used to create the tarball)
3130
3131 #------------------------------------------------------
3132 # DEFAULT TARGETS
3133
3134 default_targets =['libascend','solvers']
3135 if with_tcltk:
3136 default_targets.append('tcltk')
3137 if with_python:
3138 default_targets.append('ascxx')
3139 default_targets.append('pygtk')
3140 default_targets.append('pyfprops')
3141 if with_extfns:
3142 default_targets.append('extfns')
3143 if with_doc_build:
3144 default_targets.append('doc')
3145
3146 env.Default(default_targets)
3147
3148 print "Building targets:"," ".join([str(i) for i in BUILD_TARGETS])
3149
3150 # vim: set syntax=python:

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