/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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