/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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