/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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