/[ascend]/trunk/SConstruct
ViewVC logotype

Contents of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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