/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


Revision 502 - (hide annotations) (download)
Tue Apr 18 12:57:30 2006 UTC (19 years ago) by johnpye
File size: 28335 byte(s)
Added check to see that YACC runs OK.
Fixing build with MSVC++ 2005.
All builds now except for some problems in the SWIG-generated code.
1 johnpye 393 import os, commands, platform, distutils.sysconfig, os.path
2 johnpye 385
3 johnpye 439 version = "0.9.6rc0"
4    
5 johnpye 385 #------------------------------------------------------
6     # OPTIONS
7 johnpye 392 #
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 johnpye 385
11     opts = Options(['options.cache', 'config.py'])
12 johnpye 464 #print "PLATFORM = ",platform.system()
13 johnpye 385
14 johnpye 464 if platform.system()=="Windows":
15     default_tcl_lib = "tcl83"
16     default_tk_lib = "tk83"
17     default_tktable_lib = "Tktable28"
18 johnpye 499 default_install_assets = "glade/"
19     icon_extension = '.png'
20 johnpye 464 else:
21     default_tcl_lib = "tcl"
22     default_tk_lib = "tk"
23     default_tktable_lib = "Tktable2.8"
24 johnpye 499 default_install_assets = "$INSTALL_DATA/ascend/glade/"
25     icon_extension = '.svg'
26 johnpye 463
27    
28 johnpye 385 # Package linking option
29 johnpye 386 opts.Add(EnumOption(
30     'PACKAGE_LINKING'
31 johnpye 385 , 'Style of linking for external libraries'
32     , 'DYNAMIC_PACKAGES'
33 johnpye 386 , ['DYNAMIC_PACKAGES', 'STATIC_PACKAGES', 'NO_PACKAGES']
34     ))
35 johnpye 385
36 johnpye 392 # You can turn off building of Tcl/Tk interface
37 johnpye 386 opts.Add(BoolOption(
38 johnpye 465 'WITHOUT_TCLTK'
39 johnpye 386 ,"Set to True if you don't want to build the original Tcl/Tk GUI."
40     , False
41     ))
42    
43 johnpye 392 # You can turn off the building of the Python interface
44 johnpye 387 opts.Add(BoolOption(
45     'WITHOUT_PYTHON'
46     ,"Set to True if you don't want to build Python wrappers."
47     , False
48     ))
49    
50 johnpye 392 # Which solvers will we allow?
51     opts.Add(ListOption(
52     'WITH_SOLVERS'
53 johnpye 393 ,"List of the solvers you want to build. The default is the minimum that"
54     +" works."
55 johnpye 392 ,["QRSLV","CMSLV"]
56     ,['QRSLV','MPS','SLV','OPTSQP'
57     ,'NGSLV','CMSLV','LRSLV','MINOS','CONOPT'
58     ,'LSOD','OPTSQP'
59     ]
60     ))
61    
62 johnpye 393 # Where will the local copy of the help files be kept?
63     opts.Add(PackageOption(
64     'WITH_LOCAL_HELP'
65     , "Directory containing the local copy of the help files (optional)"
66     , "no"
67     ))
68    
69     # Will bintoken support be enabled?
70     opts.Add(BoolOption(
71     'WITH_BINTOKEN'
72     ,"Enable bintoken support? This means compiling models as C-code before"
73     +" running them, to increase solving speed for large models."
74     ,False
75     ))
76    
77 johnpye 398 # What should the default ASCENDLIBRARY path be?
78     # Note: users can change it by editing their ~/.ascend.ini
79 johnpye 393 opts.Add(
80     'DEFAULT_ASCENDLIBRARY'
81     ,"Set the default value of the ASCENDLIBRARY -- the location where"
82     +" ASCEND will look for models when running ASCEND"
83 johnpye 459 ,"$INSTALL_DATA/models"
84 johnpye 393 )
85    
86 johnpye 398 # Where is SWIG?
87     opts.Add(
88     'SWIG'
89     ,"SWIG location, probably only required for MinGW and MSVC users."
90     +" Enter the location as a Windows-style path, for example"
91 johnpye 404 +" 'c:\\msys\\1.0\\home\\john\\swigwin-1.3.29\\swig.exe'."
92 johnpye 398 )
93    
94 johnpye 400 # Build the test suite?
95     opts.Add(BoolOption(
96     'WITH_CUNIT_TESTS'
97     ,"Whether to build the CUnit tests. Default is off. If set to on,"
98     +" you must have CUnit installed somewhere that SCons can"
99 johnpye 463 +" find it, or else use the CUNIT_* options to specify."
100 johnpye 400 ,False
101     ))
102 johnpye 393
103 johnpye 400 # Where are the CUnit includes?
104     opts.Add(PackageOption(
105     'CUNIT_CPPPATH'
106     ,"Where are your CUnit include files?"
107 johnpye 459 ,'off'
108 johnpye 400 ))
109 johnpye 392
110 johnpye 404 # Where are the CUnit libraries?
111 johnpye 400 opts.Add(PackageOption(
112     'CUNIT_LIBPATH'
113 johnpye 404 ,"Where are your CUnit libraries?"
114 johnpye 459 ,'off'
115 johnpye 400 ))
116    
117 johnpye 404 # Where are the Tcl includes?
118     opts.Add(PackageOption(
119     'TCL_CPPPATH'
120     ,"Where are your Tcl include files?"
121 johnpye 463 ,"disable"
122 johnpye 404 ))
123    
124     # Where are the Tcl libs?
125     opts.Add(PackageOption(
126     'TCL_LIBPATH'
127     ,"Where are your Tcl libraries?"
128 johnpye 459 ,'off'
129 johnpye 404 ))
130    
131 johnpye 428 # What is the name of the Tcl lib?
132     opts.Add(
133     'TCL_LIB'
134     ,"Name of Tcl lib (eg 'tcl' or 'tcl83')"
135 johnpye 464 ,default_tcl_lib
136 johnpye 428 )
137    
138 johnpye 405 # Where are the Tk includes?
139     opts.Add(PackageOption(
140     'TK_CPPPATH'
141     ,"Where are your Tk include files?"
142 johnpye 464 ,'$TCL_CPPPATH'
143 johnpye 405 ))
144 johnpye 404
145 johnpye 405 # Where are the Tk libs?
146     opts.Add(PackageOption(
147     'TK_LIBPATH'
148     ,"Where are your Tk libraries?"
149 johnpye 464 ,'$TCL_LIBPATH'
150 johnpye 405 ))
151    
152 johnpye 428 # What is the name of the Tk lib?
153     opts.Add(
154     'TK_LIB'
155     ,"Name of Tk lib (eg 'tk' or 'tk83')"
156 johnpye 464 ,default_tk_lib
157 johnpye 435 )
158    
159 johnpye 460 # Static linking to TkTable
160    
161     opts.Add(BoolOption(
162     'STATIC_TKTABLE'
163     ,'Use static linking to TkTable or not'
164     ,False
165     ))
166    
167 johnpye 464 opts.Add(
168 johnpye 460 'TKTABLE_LIBPATH'
169     ,'Location of TkTable static library'
170 johnpye 464 ,'$TCL_LIBPATH/Tktable2.8'
171     )
172 johnpye 460
173 johnpye 435 opts.Add(
174 johnpye 460 'TKTABLE_LIB'
175     ,'Name of TkTable static library (excluding suffix/prefix, eg libtktable2.8.so -> tktable2.8)'
176 johnpye 464 ,default_tktable_lib
177 johnpye 460 )
178    
179     opts.Add(
180 johnpye 435 'INSTALL_PREFIX'
181     ,'Root location for installed files'
182 johnpye 449 ,'/usr/local'
183 johnpye 428 )
184    
185 johnpye 435 opts.Add(
186     'INSTALL_BIN'
187     ,'Location to put binaries during installation'
188     ,"$INSTALL_PREFIX/bin"
189     )
190    
191     opts.Add(
192 johnpye 463 'INSTALL_LIB'
193     ,'Location to put binaries during installation'
194     ,"$INSTALL_PREFIX/lib"
195     )
196    
197     opts.Add(
198 johnpye 435 'INSTALL_DATA'
199     ,'Location to put data files during installation'
200     ,"$INSTALL_PREFIX/share"
201     )
202    
203     opts.Add(
204     'INSTALL_INCLUDE'
205     ,'Location to put header files during installation'
206     ,"$INSTALL_PREFIX/include"
207     )
208    
209 johnpye 448 opts.Add(
210 johnpye 455 'PYGTK_ASSETS'
211     ,'Default location for Glade assets (placed in pygtk/interface/config.py)'
212     ,default_install_assets
213     )
214    
215     opts.Add(
216 johnpye 448 'INSTALL_ROOT'
217     ,'For use by RPM only: location of %{buildroot} during rpmbuild'
218     ,""
219     )
220    
221 johnpye 466 if platform.system()=="Windows":
222     opts.Add(BoolOption(
223     'WITH_INSTALLER'
224     ,'Build the Windows Installer (setup program) using NSIS'
225     ,False
226     ))
227    
228 johnpye 392 # TODO: OTHER OPTIONS?
229     # TODO: flags for optimisation
230 johnpye 393 # TODO: turning on/off bintoken functionality
231 johnpye 427 # TODO: Where will the 'Makefile.bt' file be installed?
232 johnpye 393
233 johnpye 498 # Import the outside environment
234    
235     if os.environ.has_key('OSTYPE') and os.environ['OSTYPE']=='msys':
236     env = Environment(ENV=os.environ, tools=['mingw','swig','lex','yacc'])
237     else:
238 johnpye 499 env = Environment(ENV=os.environ)
239     Tool('lex')(env)
240     Tool('yacc')(env)
241     Tool('fortran')(env)
242     Tool('swig')(env)
243 johnpye 498
244     if platform.system()=='Windows' and env.has_key('MSVS'):
245     print "INCLUDE =",env['ENV']['INCLUDE']
246     print "LIB =",env['ENV']['LIB']
247     print "LINK =",env['LINK']
248     print "LINKCOM =",env['LINKCOM']
249     print "AR =",env['AR']
250     print "ARCOM =",env['ARCOM']
251     #env['AR']='link /lib'
252     env.Append(CPPPATH=env['ENV']['INCLUDE'])
253     env.Append(LIBPATH=env['ENV']['LIB'])
254     env.Append(CPPDEFINES=['_CRT_SECURE_NO_DEPRECATED','_CRT_SECURE_NO_DEPRECATE'])
255    
256 johnpye 385 opts.Update(env)
257     opts.Save('options.cache',env)
258    
259     Help(opts.GenerateHelpText(env))
260    
261 johnpye 465 with_tcltk_gui = (env['WITHOUT_TCLTK']==False)
262 johnpye 427 without_tcltk_reason = "disabled by options/config.py"
263 johnpye 386
264 johnpye 387 with_python = (env['WITHOUT_PYTHON']==False)
265 johnpye 427 without_python_reason = "disabled by options/config.py"
266 johnpye 387
267 johnpye 400 with_cunit_tests = env['WITH_CUNIT_TESTS']
268 johnpye 427 without_cunit_reason = "not requested"
269 johnpye 400
270 johnpye 464 #print "SOLVERS:",env['WITH_SOLVERS']
271     #print "WITH_BINTOKEN:",env['WITH_BINTOKEN']
272     #print "DEFAULT_ASCENDLIBRARY:",env['DEFAULT_ASCENDLIBRARY']
273 johnpye 393
274     subst_dict = {
275     '@WEBHELPROOT@':'http://pye.dyndns.org/ascend/manual/'
276 johnpye 436 , '@GLADE_FILE@':'ascend.glade'
277 johnpye 393 , '@DEFAULT_ASCENDLIBRARY@':env['DEFAULT_ASCENDLIBRARY']
278 johnpye 455 , '@ICON_EXTENSION@':icon_extension
279 johnpye 393 , '@HELP_ROOT@':''
280 johnpye 436 , '@INSTALL_DATA@':env['INSTALL_DATA']
281     , '@INSTALL_BIN@':env['INSTALL_BIN']
282     , '@INSTALL_INCLUDE@':env['INSTALL_INCLUDE']
283 johnpye 455 , '@PYGTK_ASSETS@':env['PYGTK_ASSETS']
284 johnpye 439 , '@VERSION@':version
285 johnpye 393 }
286    
287     if env['WITH_LOCAL_HELP']:
288 johnpye 464 print "WITH_LOCAL_HELP:",env['WITH_LOCAL_HELP']
289 johnpye 393 subst_dict['@HELP_ROOT@']=env['WITH_LOCAL_HELP']
290 johnpye 463
291 johnpye 500 if with_python:
292     subst_dict['@ASCXX_USE_PYTHON@']="1"
293    
294 johnpye 463 can_install = True
295     if platform.system()=='Windows':
296     can_install = False
297    
298     env['CAN_INSTALL']=can_install
299    
300 johnpye 393 env.Append(SUBST_DICT=subst_dict)
301    
302 johnpye 385 #------------------------------------------------------
303 johnpye 398 # SPECIAL CONFIGURATION TESTS
304    
305 johnpye 463 need_fortran = False
306    
307 johnpye 400 #----------------
308     # SWIG
309    
310 johnpye 398 import os,re
311    
312 johnpye 413 def get_swig_version(env):
313 johnpye 403 cmd = env['SWIG']+' -version'
314 johnpye 427 (cin,coutcerr) = os.popen4(cmd)
315 johnpye 403 output = coutcerr.read()
316 johnpye 398
317 johnpye 403 restr = "SWIG\\s+Version\\s+(?P<maj>[0-9]+)\\.(?P<min>[0-9]+)\\.(?P<pat>[0-9]+)\\s*$"
318     expr = re.compile(restr,re.M);
319 johnpye 398 m = expr.search(output);
320     if not m:
321 johnpye 413 return None
322 johnpye 398 maj = int(m.group('maj'))
323     min = int(m.group('min'))
324     pat = int(m.group('pat'))
325 johnpye 413
326     return (maj,min,pat)
327 johnpye 398
328 johnpye 413
329     def CheckSwigVersion(context):
330    
331     try:
332     context.Message("Checking version of SWIG... ")
333     maj,min,pat = get_swig_version(context.env)
334     except:
335     context.Result("Failed to detect version, or failed to run SWIG")
336     return 0;
337    
338 johnpye 478 context.env['SWIGVERSION']=tuple([maj,min,pat])
339    
340 johnpye 398 if maj == 1 and (
341 johnpye 400 min > 3
342     or (min == 3 and pat >= 24)
343 johnpye 398 ):
344     context.Result("ok, %d.%d.%d" % (maj,min,pat))
345     return 1;
346 johnpye 401 else:
347     context.Result("too old, %d.%d.%d" % (maj,min,pat))
348     return 0;
349 johnpye 398
350 johnpye 400 #----------------
351     # General purpose library-and-header test
352    
353 johnpye 404 class KeepContext:
354     def __init__(self,context,varprefix):
355     self.keep = {}
356     for k in ['LIBS','LIBPATH','CPPPATH']:
357     if context.env.has_key(k):
358     self.keep[k] = context.env[k]
359 johnpye 463 else:
360     self.keep[k] = None
361 johnpye 404
362     libpath_add = []
363     if context.env.has_key(varprefix+'_LIBPATH'):
364     libpath_add = [env[varprefix+'_LIBPATH']]
365 johnpye 428 #print "Adding '"+str(libpath_add)+"' to lib path"
366 johnpye 400
367 johnpye 404 cpppath_add = []
368     if context.env.has_key(varprefix+'_CPPPATH'):
369     cpppath_add = [env[varprefix+'_CPPPATH']]
370 johnpye 428 #print "Adding '"+str(cpppath_add)+"' to cpp path"
371    
372     libs_add = []
373     if context.env.has_key(varprefix+'_LIB'):
374     libs_add = [env[varprefix+'_LIB']]
375 johnpye 464 #print "Adding '"+str(libs_add)+"' to libs"
376 johnpye 428
377 johnpye 405 context.env.Append(
378     LIBPATH = libpath_add
379     , CPPPATH = cpppath_add
380 johnpye 428 , LIBS = libs_add
381 johnpye 405 )
382 johnpye 404
383     def restore(self,context):
384 johnpye 464 #print "RESTORING CONTEXT"
385     #print self.keep
386     #print "..."
387 johnpye 404 for k in self.keep:
388 johnpye 463 if self.keep[k]==None:
389 johnpye 464 #print "Clearing "+str(k)
390 johnpye 463 del context.env[k];
391     else:
392 johnpye 464 #print "Restoring "+str(k)+" to '"+self.keep[k]+"'"
393 johnpye 463 context.env[k]=self.keep[k];
394 johnpye 404
395 johnpye 400 def CheckExtLib(context,libname,text,ext='.c',varprefix=None):
396     """This method will check for variables LIBNAME_LIBPATH
397     and LIBNAME_CPPPATH and try to compile and link the
398     file with the provided text, linking with the
399     library libname."""
400    
401 johnpye 405 context.Message( 'Checking for '+libname+'... ' )
402 johnpye 400
403     if varprefix==None:
404     varprefix = libname.upper()
405    
406 johnpye 404 keep = KeepContext(context,varprefix)
407 johnpye 400
408 johnpye 428 if not context.env.has_key(varprefix+'_LIB'):
409 johnpye 463 # if varprefix_LIB were in env, KeepContext would
410     # have appended it already
411 johnpye 451 context.env.Append(LIBS=libname)
412 johnpye 428
413 johnpye 404 is_ok = context.TryLink(text,ext)
414 johnpye 428
415     # print "Link success? ",(is_ok != 0)
416 johnpye 400
417 johnpye 405 keep.restore(context)
418 johnpye 400
419 johnpye 428 # print "Restored CPPPATH="+str(context.env['CPPPATH'])
420     # print "Restored LIBS="+libname
421     # print "Restored LIBPATH="+str(context.env['LIBPATH'])
422    
423 johnpye 404 context.Result(is_ok)
424     return is_ok
425    
426     #----------------
427 johnpye 502 # GCC
428    
429     gcc_test_text = """
430     #ifndef __GNUC__
431     # error "Not using GCC"
432     #endif
433    
434     int main(void){
435     return __GNUC__;
436     }
437     """
438    
439     def CheckGcc(context):
440     context.Message("Checking for GCC... ")
441     is_ok = context.TryCompile(gcc_test_text,".c")
442     context.Result(is_ok)
443     return is_ok
444    
445     #----------------
446 johnpye 500 # GCC VISIBILITY feature
447    
448     gccvisibility_test_text = """
449     #if __GNUC__ < 4
450     # error "Require GCC version 4 or newer"
451     #endif
452    
453     __attribute__ ((visibility("default"))) int x;
454    
455     int main(void){
456     extern int x;
457     x = 4;
458     }
459     """
460    
461     def CheckGccVisibility(context):
462     context.Message("Checking for GCC 'visibility' capability... ")
463     is_ok = context.TryCompile(gccvisibility_test_text,".c")
464     context.Result(is_ok)
465     return is_ok
466 johnpye 502
467 johnpye 500 #----------------
468 johnpye 502 # YACC
469    
470     yacc_test_text = """
471     %start ROOT
472     %token MSG
473     %%
474    
475     ROOT:
476     MSG { print("HELLO"); }
477     ;
478     """
479    
480     def CheckYacc(context):
481     context.Message("Checking for Yacc... ")
482     is_ok = context.TryCompile(yacc_test_text,".y")
483     context.Result(is_ok)
484     return is_ok
485    
486     #----------------
487 johnpye 404 # CUnit test
488    
489 johnpye 400 cunit_test_text = """
490 johnpye 451 #include <CUnit/CUnit.h>
491 johnpye 400 int maxi(int i1, int i2){
492     return (i1 > i2) ? i1 : i2;
493     }
494    
495     void test_maxi(void){
496     CU_ASSERT(maxi(0,2) == 2);
497     CU_ASSERT(maxi(0,-2) == 0);
498     CU_ASSERT(maxi(2,2) == 2);
499    
500     }
501     int main(void){
502     /* CU_initialize_registry() */
503 johnpye 404 return 0;
504 johnpye 400 }
505     """
506    
507     def CheckCUnit(context):
508 johnpye 451 return CheckExtLib(context,'cunit',cunit_test_text)
509 johnpye 400
510 johnpye 404 #----------------
511 johnpye 405 # Tcl test
512 johnpye 404
513     tcl_check_text = r"""
514     #include <tcl.h>
515     #include <stdio.h>
516     int main(void){
517     printf("%s",TCL_PATCH_LEVEL);
518     return 0;
519     }
520     """
521    
522     def CheckTcl(context):
523 johnpye 405 return CheckExtLib(context,'tcl',tcl_check_text)
524    
525     def CheckTclVersion(context):
526 johnpye 404 keep = KeepContext(context,'TCL')
527 johnpye 405 context.Message("Checking Tcl version... ")
528     (is_ok,output) = context.TryRun(tcl_check_text,'.c')
529 johnpye 404 keep.restore(context)
530     if not is_ok:
531 johnpye 405 context.Result("failed to run check")
532 johnpye 404 return 0
533 johnpye 405
534     major,minor,patch = tuple(int(i) for i in output.split("."))
535     if major != 8 or minor > 3:
536 johnpye 428 context.Result(output+" (bad version)")
537 johnpye 405 # bad version
538     return 0
539    
540     # good version
541 johnpye 428 context.Result(output+" (good)")
542 johnpye 404 return 1
543    
544 johnpye 405 #----------------
545 johnpye 463 # Tk test
546 johnpye 405
547     tk_check_text = r"""
548     #include <tk.h>
549     #include <stdio.h>
550     int main(void){
551     printf("%s",TK_PATCH_LEVEL);
552     return 0;
553     }
554     """
555     def CheckTk(context):
556 johnpye 428 return CheckExtLib(context,'tk',tcl_check_text)
557 johnpye 405
558 johnpye 428
559 johnpye 405 def CheckTkVersion(context):
560     keep = KeepContext(context,'TK')
561     context.Message("Checking Tk version... ")
562     (is_ok,output) = context.TryRun(tk_check_text,'.c')
563 johnpye 404 keep.restore(context)
564     if not is_ok:
565     context.Result("failed to run check")
566     return 0
567     context.Result(output)
568    
569     major,minor,patch = tuple(int(i) for i in output.split("."))
570     if major != 8 or minor > 3:
571     # bad version
572     return 0
573 johnpye 400
574 johnpye 404 # good version
575     return 1
576 johnpye 485
577     #----------------
578     # GCC Version sniffing
579    
580     # TODO FIXME
581    
582     gcc_version4 = False
583    
584 johnpye 398 #------------------------------------------------------
585 johnpye 385 # CONFIGURATION
586    
587     conf = Configure(env
588     , custom_tests = {
589 johnpye 398 'CheckSwigVersion' : CheckSwigVersion
590 johnpye 400 , 'CheckCUnit' : CheckCUnit
591 johnpye 404 , 'CheckTcl' : CheckTcl
592     , 'CheckTclVersion' : CheckTclVersion
593 johnpye 405 , 'CheckTk' : CheckTk
594     , 'CheckTkVersion' : CheckTkVersion
595 johnpye 502 , 'CheckGcc' : CheckGcc
596 johnpye 500 , 'CheckGccVisibility' : CheckGccVisibility
597 johnpye 502 , 'CheckYacc' : CheckYacc
598 johnpye 400 # , 'CheckIsNan' : CheckIsNan
599     # , 'CheckCppUnitConfig' : CheckCppUnitConfig
600 johnpye 385 }
601 johnpye 459 # , config_h = "config.h"
602 johnpye 385 )
603    
604 johnpye 398
605 johnpye 385 # Math library
606    
607 johnpye 427 #if not conf.CheckFunc('sinh') and not conf.CheckLibWithHeader(['m','c','libc'], 'math.h', 'C'):
608     # print 'Did not find math library, exiting!'
609     # Exit(1)
610    
611 johnpye 385 # Where is 'isnan'?
612    
613     if not conf.CheckFunc('isnan'):
614     print "Didn't find isnan"
615 johnpye 414 # Exit(1)
616 johnpye 385
617 johnpye 500 # GCC visibility
618    
619 johnpye 502 if conf.CheckGcc():
620     conf.env['HAVE_GCC']=True;
621     if conf.CheckGccVisibility():
622     conf.env['HAVE_GCCVISIBILITY']=True;
623 johnpye 501 conf.env.Append(CCFLAGS=['-fvisibility=hidden'])
624 johnpye 500
625 johnpye 502
626     # YACC
627    
628    
629     if conf.CheckYacc():
630     conf.env['HAVE_YACC']=True
631    
632     conf.env['HAVE_LEX']=True
633    
634 johnpye 387 # Tcl/Tk
635 johnpye 386
636 johnpye 428 if conf.CheckTcl():
637     if with_tcltk_gui and conf.CheckTclVersion():
638     if conf.CheckTk():
639     if with_tcltk_gui and not conf.CheckTkVersion():
640     without_tcltk_reason = "Require Tk version <= 8.3. See 'scons -h'"
641     with_tcltk_gui = False
642     else:
643     without_tcltk_reason = "Tk not found."
644     with_tcltk_gui = False
645     else:
646 johnpye 405 without_tcltk_reason = "Require Tcl <= 8.3 Tcl."
647 johnpye 404 with_tcltk_gui = False
648 johnpye 386
649 johnpye 405 else:
650 johnpye 428 without_tcltk_reason = "Tcl not found."
651 johnpye 412 with_tcltk_gui = False
652    
653 johnpye 395 # Python... obviously we're already running python, so we just need to
654     # check that we can link to the python library OK:
655    
656 johnpye 391 if platform.system()=="Windows":
657 johnpye 395 python_lib='python24'
658 johnpye 391 else:
659 johnpye 395 python_lib='python2.4'
660 johnpye 391
661 johnpye 395 # SWIG version
662    
663 johnpye 413 if not conf.CheckSwigVersion():
664     without_python_reason = 'SWIG >= 1.3.24 is required'
665     with_python = False
666    
667 johnpye 400 # CUnit
668    
669     if with_cunit_tests:
670 johnpye 404 if not conf.CheckCUnit():
671 johnpye 427 without_cunit_reason = 'CUnit not found'
672    
673     # BLAS
674    
675 johnpye 459 need_blas=False
676     if with_tcltk_gui:
677     need_blas=True
678     if need_blas:
679     if conf.CheckLib('blas'):
680     print "FOUND BLAS"
681     with_local_blas = False
682     without_local_blas_reason = "Found BLAS installed on system"
683     else:
684     print "DIDN'T FIND BLAS"
685     with_local_blas = True
686     need_fortran = True
687 johnpye 427
688     # FORTRAN
689    
690     if need_fortran:
691     conf.env.Tool('f77')
692     detect_fortran = conf.env.Detect(['g77','f77'])
693     if detect_fortran:
694     # For some reason, g77 doesn't get detected properly on MinGW
695     if not env.has_key('F77'):
696     conf.env.Replace(F77=detect_fortran)
697     conf.env.Replace(F77COM='$F77 $F77FLAGS -c -o $TARGET $SOURCE')
698     conf.env.Replace(F77FLAGS='')
699 johnpye 428 #print "F77:",conf.env['F77']
700     #print "F77COM:",conf.env['F77COM']
701     #print "F77FLAGS:",conf.env['F77FLAGS']
702 johnpye 427 fortran_builder = Builder(
703     action='$F77COM'
704     , suffix='.o'
705     , src_suffix='.f'
706     )
707     conf.env.Append(BUILDERS={'Fortran':fortran_builder})
708     else:
709     print "FORTRAN-77 required but not found"
710 johnpye 404 Exit(1)
711 johnpye 464 #else:
712     # print "FORTRAN not required"
713 johnpye 400
714 johnpye 385 # TODO: -D_HPUX_SOURCE is needed
715    
716     # TODO: check size of void*
717    
718 johnpye 393 # TODO: detect if dynamic libraries are possible or not
719    
720 johnpye 427 if platform.system()=="Windows" and env.has_key('MSVS'):
721     if not conf.CheckHeader('windows.h') and env['PACKAGE_LINKING']=='DYNAMIC_PACKAGES':
722     print "Reverting to STATIC_PACKAGES since windows.h is not available. Probably you "\
723     +"need to install the Microsoft Windows Server 2003 Platform SDK, or similar."
724     env['PACKAGE_LINKING']='STATIC_PACKAGES'
725    
726     if with_python and not conf.CheckHeader('basetsd.h'):
727     with_python = 0;
728     without_python_reason = "Header file 'basetsd.h' not found. Install the MS Platform SDK."
729    
730     conf.env.Append(CPPDEFINES=env['PACKAGE_LINKING'])
731    
732 johnpye 395 conf.Finish()
733    
734     env.Append(PYTHON_LIBPATH=[distutils.sysconfig.PREFIX+"/libs"])
735     env.Append(PYTHON_LIB=[python_lib])
736     env.Append(PYTHON_CPPPATH=[distutils.sysconfig.get_python_inc()])
737    
738 johnpye 385 #------------------------------------------------------
739 johnpye 393 # RECIPE: 'SubstInFile', used in pygtk SConscript
740    
741     import re
742 johnpye 395 from SCons.Script import * # the usual scons stuff you get in a SConscript
743 johnpye 393
744 johnpye 395 def TOOL_SUBST(env):
745     """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
746     from the source to the target.
747     The values of SUBST_DICT first have any construction variables expanded
748     (its keys are not expanded).
749     If a value of SUBST_DICT is a python callable function, it is called and
750     the result is expanded as the value.
751     If there's more than one source and more than one target, each target gets
752     substituted from the corresponding source.
753 johnpye 393 """
754 johnpye 395 env.Append(TOOLS = 'SUBST')
755     def do_subst_in_file(targetfile, sourcefile, dict):
756     """Replace all instances of the keys of dict with their values.
757     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
758     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
759     """
760     try:
761     f = open(sourcefile, 'rb')
762     contents = f.read()
763     f.close()
764     except:
765     raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
766     for (k,v) in dict.items():
767     contents = re.sub(k, v, contents)
768     try:
769     f = open(targetfile, 'wb')
770     f.write(contents)
771     f.close()
772     except:
773     raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
774     return 0 # success
775 johnpye 393
776 johnpye 395 def subst_in_file(target, source, env):
777     if not env.has_key('SUBST_DICT'):
778     raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
779     d = dict(env['SUBST_DICT']) # copy it
780     for (k,v) in d.items():
781     if callable(v):
782     d[k] = env.subst(v())
783     elif SCons.Util.is_String(v):
784     d[k]=env.subst(v)
785     else:
786     raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
787     for (t,s) in zip(target, source):
788     return do_subst_in_file(str(t), str(s), d)
789 johnpye 393
790 johnpye 395 def subst_in_file_string(target, source, env):
791     """This is what gets printed on the console."""
792     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
793     for (t,s) in zip(target, source)])
794 johnpye 393
795 johnpye 395 def subst_emitter(target, source, env):
796     """Add dependency from substituted SUBST_DICT to target.
797     Returns original target, source tuple unchanged.
798     """
799     d = env['SUBST_DICT'].copy() # copy it
800     for (k,v) in d.items():
801     if callable(v):
802     d[k] = env.subst(v())
803     elif SCons.Util.is_String(v):
804     d[k]=env.subst(v)
805     Depends(target, SCons.Node.Python.Value(d))
806     return target, source
807 johnpye 393
808 johnpye 395 subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string)
809     env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
810    
811     TOOL_SUBST(env)
812    
813 johnpye 393 #------------------------------------------------------
814 johnpye 463 # Recipe for 'CHMOD' ACTION
815 johnpye 439
816     import SCons
817     from SCons.Script.SConscript import SConsEnvironment
818     SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
819     lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
820    
821     def InstallPerm(env, dest, files, perm):
822     obj = env.Install(dest, files)
823     for i in obj:
824     env.AddPostAction(i, env.Chmod(str(i), perm))
825    
826     SConsEnvironment.InstallPerm = InstallPerm
827    
828     # define wrappers
829     SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
830     SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
831 johnpye 463
832 johnpye 439 #------------------------------------------------------
833 johnpye 466 # NSIS Support for SCons
834 johnpye 385
835 johnpye 466 # Adapted version by John Pye, April 2006.
836     # from http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/NsisSconsTool
837     # Written by Mike Elkins, January 2004.
838 johnpye 393
839 johnpye 466 #This tool provides SCons support for the Nullsoft Scriptable Install System
840     #a windows installer builder available at http://nsis.sourceforge.net/home
841    
842     #In addition, if you set NSISDEFINES to a dictionary, those variables will be passed
843     #to NSIS.
844    
845     import SCons.Builder
846     import SCons.Util
847     import SCons.Scanner
848     import SCons.Sig
849     import os.path
850     import glob
851    
852     def nsis_parse( sources, keyword, multiple ):
853     """
854     A function that knows how to read a .nsi file and figure
855     out what files are referenced, or find the 'OutFile' line.
856    
857    
858     sources is a list of nsi files.
859     keyword is the command ('File' or 'OutFile') to look for
860     multiple is true if you want all the args as a list, false if you
861     just want the first one.
862     """
863     stuff = []
864     for s in sources:
865     c = s.get_contents()
866     for l in c.split('\n'):
867     semi = l.find(';')
868     if (semi != -1):
869     l = l[:semi]
870     hash = l.find('#')
871     if (hash != -1):
872     l = l[:hash]
873     # Look for the keyword
874     l = l.strip()
875     spl = l.split(None,1)
876     if len(spl) > 1:
877     if spl[0].capitalize() == keyword.capitalize():
878     arg = spl[1]
879     if arg.startswith('"') and arg.endswith('"'):
880     arg = arg[1:-1]
881     if multiple:
882     stuff += [ arg ]
883     else:
884     return arg
885     return stuff
886    
887    
888     def nsis_path( filename, nsisdefines, rootdir ):
889     """
890     Do environment replacement, and prepend with the SCons root dir if
891     necessary
892     """
893     # We can't do variables defined by NSIS itself (like $INSTDIR),
894     # only user supplied ones (like ${FOO})
895     varPos = filename.find('${')
896     while varPos != -1:
897     endpos = filename.find('}',varPos)
898     assert endpos != -1
899     if not nsisdefines.has_key(filename[varPos+2:endpos]):
900     raise KeyError ("Could not find %s in NSISDEFINES" % filename[varPos+2:endpos])
901     val = nsisdefines[filename[varPos+2:endpos]]
902     if type(val) == list:
903     if varPos != 0 or endpos+1 != len(filename):
904     raise Exception("Can't use lists on variables that aren't complete filenames")
905     return val
906     filename = filename[0:varPos] + val + filename[endpos+1:]
907     varPos = filename.find('${')
908     return filename
909    
910    
911     def nsis_scanner( node, env, path ):
912     """
913     The scanner that looks through the source .nsi files and finds all lines
914     that are the 'File' command, fixes the directories etc, and returns them.
915     """
916     nodes = node.rfile()
917     if not node.exists():
918     return []
919     nodes = []
920     source_dir = node.get_dir()
921     for include in nsis_parse([node],'file',1):
922     exp = nsis_path(include,env['NSISDEFINES'],source_dir)
923     if type(exp) != list:
924     exp = [exp]
925     for p in exp:
926     for filename in glob.glob( os.path.abspath(
927     os.path.join(str(source_dir),p))):
928     # Why absolute path? Cause it breaks mysteriously without it :(
929     nodes.append(filename)
930     return nodes
931    
932    
933     def nsis_emitter( source, target, env ):
934     """
935     The emitter changes the target name to match what the command actually will
936     output, which is the argument to the OutFile command.
937     """
938     nsp = nsis_parse(source,'outfile',0)
939     if not nsp:
940     return (target,source)
941     x = (
942     nsis_path(nsp,env['NSISDEFINES'],''),
943     source)
944     return x
945    
946     def quoteIfSpaced(text):
947     if ' ' in text:
948     return '"'+text+'"'
949     else:
950     return text
951    
952     def toString(item,env):
953     if type(item) == list:
954     ret = ''
955     for i in item:
956     if ret:
957     ret += ' '
958     val = toString(i,env)
959     if ' ' in val:
960     val = "'"+val+"'"
961     ret += val
962     return ret
963     else:
964     # For convienence, handle #s here
965     if str(item).startswith('#'):
966     item = env.File(item).get_abspath()
967     return str(item)
968    
969     def runNSIS(source,target,env,for_signature):
970     ret = env['NSIS']+" "
971     if env.has_key('NSISFLAGS'):
972     for flag in env['NSISFLAGS']:
973     ret += flag
974     ret += ' '
975     if env.has_key('NSISDEFINES'):
976     for d in env['NSISDEFINES']:
977     ret += '/D'+d
978     if env['NSISDEFINES'][d]:
979     ret +='='+quoteIfSpaced(toString(env['NSISDEFINES'][d],env))
980     ret += ' '
981     for s in source:
982     ret += quoteIfSpaced(str(s))
983     return ret
984    
985     def find_nsis(env):
986     """
987     Try and figure out if NSIS is installed on this machine, and if so,
988     where.
989     """
990     if SCons.Util.can_read_reg:
991     # If we can read the registry, get the NSIS command from it
992     try:
993     k = SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
994     'SOFTWARE\\NSIS')
995     val, tok = SCons.Util.RegQueryValueEx(k,None)
996     ret = val + os.path.sep + 'makensis.exe'
997     if os.path.exists(ret):
998     return '"' + ret + '"'
999     else:
1000     return None
1001     except:
1002     pass # Couldn't find the key, just act like we can't read the registry
1003     # Hope it's on the path
1004     return env.WhereIs('makensis.exe')
1005    
1006     def nsis_exists(env):
1007     """
1008     Is NSIS findable on this machine?
1009     """
1010     if find_nsis(env) != None:
1011     return 1
1012     return 0
1013    
1014     env['BUILDERS']['Nsis'] = SCons.Builder.Builder(generator=runNSIS,
1015     src_suffix='.nsi',
1016     emitter=nsis_emitter)
1017    
1018     env.Append(SCANNERS = SCons.Scanner.Scanner( function = nsis_scanner,
1019     skeys = ['.nsi']))
1020    
1021     if not env.has_key('NSISDEFINES'):
1022     env['NSISDEFINES'] = {}
1023     env['NSIS'] = find_nsis(env)
1024    
1025 johnpye 463 #------------------------------------------------------
1026     # BUILD...
1027 johnpye 385
1028 johnpye 463 # so that #include <modulename/headername.h> works across all modules...
1029     env.Append(CPPPATH=['#base/generic'])
1030 johnpye 385
1031 johnpye 485 if gcc_version4:
1032     env.Append(CCFLAGS=['-fvisibility=hidden'])
1033    
1034 johnpye 463 #-------------
1035     # TCL/TK GUI
1036 johnpye 385
1037 johnpye 463 if with_tcltk_gui:
1038     if with_local_blas:
1039     env.SConscript(['blas/SConscript'],'env')
1040     else:
1041     print "Skipping... BLAS won't be build:", without_local_blas_reason
1042 johnpye 385
1043 johnpye 463 env.SConscript(['lsod/SConscript'],'env')
1044 johnpye 385
1045 johnpye 463 env.SConscript(['linpack/SConscript'],'env')
1046 johnpye 386 env.SConscript(['tcltk98/generic/interface/SConscript'],'env')
1047 johnpye 391 else:
1048 johnpye 405 print "Skipping... Tcl/Tk GUI isn't being built:",without_tcltk_reason
1049 johnpye 386
1050 johnpye 463 #-------------
1051     # PYTHON INTERFACE
1052    
1053 johnpye 387 if with_python:
1054     env.SConscript(['pygtk/interface/SConscript'],'env')
1055 johnpye 391 else:
1056 johnpye 413 print "Skipping... Python GUI isn't being built:",without_python_reason
1057 johnpye 400
1058 johnpye 463 #------------
1059     # BASE/GENERIC SUBDIRECTORIES
1060    
1061     dirs = ['general','utilities','compiler','solver','packages']
1062    
1063     srcs = []
1064     for d in dirs:
1065     heresrcs = env.SConscript('base/generic/'+d+'/SConscript','env')
1066     srcs += heresrcs
1067    
1068     #-------------
1069     # LIBASCEND -- all base/generic functionality
1070    
1071     libascend = env.SharedLibrary('ascend',srcs)
1072    
1073     #-------------
1074     # UNIT TESTS
1075    
1076 johnpye 400 if with_cunit_tests:
1077     testdirs = ['general','solver','utilities']
1078     for testdir in testdirs:
1079     path = 'base/generic/'+testdir+'/test/'
1080     env.SConscript([path+'SConscript'],'env')
1081     env.SConscript(['test/SConscript'],'env')
1082     env.SConscript(['base/generic/test/SConscript'],'env')
1083    
1084    
1085     else:
1086 johnpye 427 print "Skipping... CUnit tests aren't being built:",without_cunit_reason
1087 johnpye 400
1088 johnpye 427
1089 johnpye 463 #------------------------------------------------------
1090     # INSTALLATION
1091 johnpye 427
1092 johnpye 463 if env.has_key('CAN_INSTALL') and env['CAN_INSTALL']:
1093     # the models directory only needs to be processed for installation, no other processing required.
1094     env.SConscript(['models/SConscript'],'env')
1095 johnpye 427
1096 johnpye 463 dirs = ['INSTALL_BIN','INSTALL_DATA','INSTALL_LIB']
1097     install_dirs = [env['INSTALL_ROOT']+env[d] for d in dirs]
1098 johnpye 449
1099 johnpye 463 # TODO: add install options
1100     env.Alias('install',install_dirs)
1101 johnpye 400
1102 johnpye 463 env.Install(env['INSTALL_ROOT']+env['INSTALL_LIB'],libascend)
1103 johnpye 435
1104 johnpye 438 #------------------------------------------------------
1105     # CREATE the SPEC file for generation of RPM packages
1106    
1107 johnpye 463 if platform.system()=="Linux":
1108     env.SubstInFile('ascend.spec.in')

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