/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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