/[ascend]/trunk/SConstruct
ViewVC logotype

Annotation of /trunk/SConstruct

Parent Directory Parent Directory | Revision Log Revision Log


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

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