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

Contents of /branches/georgy/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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