Fix plugins with MSVC, thanks to Gulam Faruque.
[syx.git] / SConstruct
blobe6025219ff27183ccb154f057ccf94eefeac3a3f
1 #################################################################################
2 # #
3 # Copyright (c) 2007-2008 Luca Bruno #
4 # #
5 # This file is part of Smalltalk YX. #
6 # #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy #
8 # of this software and associated documentation files (the "Software"), to deal #
9 # in the Software without restriction, including without limitation the rights #
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #
11 # copies of the Software, and to permit persons to whom the Software is #
12 # furnished to do so, subject to the following conditions: #
13 # #
14 # The above copyright notice and this permission notice shall be included in #
15 # all copies or substantial portions of the Software. #
16 # #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #
23 # DEALINGS IN THE SOFTWARE. #
24 # #
25 #################################################################################
27 import os, glob
28 from SCons import Conftest
30 env = Environment ()
32 opts = Options ('options.cache')
34 if env['PLATFORM'] == 'win32':
35 opts.AddOptions (PathOption('prefix',
36 'Installation prefix',
37 'C:\\\\Syx', PathOption.PathAccept))
38 env['bindir'] = env['datadir'] = env['rootdir'] = env['libdir'] = '$prefix'
39 env['plugindir'] = '$prefix\\\\lib'
40 env['imagepath'] = '$prefix\\\\default.sim'
41 env['includedir'] = '$prefix\\\\include'
42 env['docdir'] = '$prefix\\\\doc'
43 else:
44 opts.AddOptions (
45 PathOption('prefix',
46 'Installation prefix',
47 '/usr/local', PathOption.PathAccept),
48 PathOption('exec_prefix',
49 'Installation prefix for executables and object code libraries',
50 '$prefix', PathOption.PathAccept),
51 PathOption('bindir',
52 'Installation prefix for user executables',
53 '$exec_prefix/bin', PathOption.PathAccept),
54 PathOption('datadir',
55 'Installation prefix for machine-independent data',
56 '$prefix/share', PathOption.PathAccept),
57 PathOption('rootdir',
58 'Installation prefix for all smalltalk data',
59 '$datadir/syx', PathOption.PathAccept),
60 PathOption('imagepath',
61 'Installation path for the default binary image',
62 '$rootdir/default.sim', PathOption.PathAccept),
63 PathOption('docdir',
64 'Installation prefix for documentation',
65 '$datadir/doc', PathOption.PathAccept),
66 PathOption('libdir',
67 'Installation prefix for object code libraries',
68 '$exec_prefix/lib', PathOption.PathAccept),
69 PathOption('plugindir',
70 'Installation prefix for object code plugins',
71 '$libdir/syx', PathOption.PathAccept),
72 PathOption('includedir',
73 'Installation prefix for C header files',
74 '$prefix/include', PathOption.PathAccept))
76 opts.AddOptions (
77 ('host', """cross-compile to build programs to run on HOST""", ''),
78 EnumOption ('endianness',
79 """Specify manually the endianness of the host machine (auto, big, little)""",
80 'auto', allowed_values=('auto', 'little', 'big'), ignorecase=True),
81 BoolOption ('shared', """Build shared library objects""", True),
82 BoolOption ('static', """Build static library objects""", True),
83 BoolOption ('plugins', """Build with plugins support""", True),
84 BoolOption ('bignum', """Build with infinite-precision numbers (needs gmp library)""", True),
85 BoolOption ('attach', """Attach a debugger for test failures""", False),
86 EnumOption ('debug', """Debug output and symbols""", 'normal',
87 allowed_values=('no', 'normal', 'info', 'full'),
88 ignorecase=True),
89 BoolOption ('profile', """Compile and link statically with -pg (gprof)""", False),
90 BoolOption ('iprofile', """Enable internal profiling""", False),
91 BoolOption ('doc', """Build reference documentation (needs Doxygen)""", True),
93 BoolOption ('GTK', """Build the syx-gtk plugin to support graphical user interfaces""", True),
94 BoolOption ('WINGUI', """Build the syx-wingui plugin to support native windows user interfaces""", True),
95 BoolOption ('READLINE', """Build the syx-readline plugin to add more console features""", True),
96 BoolOption ('X11', """Build the syx-x11 plugin to wrap the X11 library""", True))
98 opts.Update (env)
99 opts.Save ('options.cache', env)
101 CC=os.getenv ('CC')
102 LINK=os.getenv ('LINK')
103 AR=os.getenv ('AR')
104 if CC:
105 env.Replace(CC = env.WhereIs (CC))
106 if not LINK:
107 env.Replace(LINK = env.WhereIs (CC))
108 if LINK:
109 env.Replace(LINK = env.WhereIs (LINK))
110 if AR:
111 env.Replace(AR = env.WhereIs (AR))
113 # Custimize the help message
114 env.Help (opts.GenerateHelpText (env) + """
115 Type: 'scons' to build Syx.
116 'scons doc=no' to create disable building the reference
117 documentation.
119 'scons endianness=auto,big,little'
120 specify the endianness of the target
121 machine (default: auto)
123 'scons host=arch-os' cross-compile to build programs
124 to run on the specified host
126 'scons debug=no' release build with high optimization.
127 'scons debug=normal' add debug symbols (default).
128 'scons debug=info' display more messages.
129 'scons debug=full' trace the entire execution stack of Smalltalk.
130 'scons profile=yes' compile and link statically with -pg (gprof).
131 'scons test' to test Syx.
132 'scons test attach=yes'
133 to test Syx and attach a debugger if a
134 test fails
136 'scons install' to install Syx.
137 'scons sdist' to create a directory with source distribution.
138 'scons bdist' to create a directory with binary distribution
139 (implies 'scons install').
140 """)
142 # Configuration
144 def check_endianness (ctx):
145 ctx.Message ("Checking for machine endianness...")
146 if env['endianness'] != 'auto':
147 if env['endianness'] == 'big':
148 Conftest._Have (ctx, 'WORDS_BIGENDIAN', 1)
149 else:
150 Conftest._Have (ctx, 'WORDS_BIGENDIAN', 0)
151 ctx.Result (env['endianness'])
152 return True
154 ret = ctx.TryRun ("""
155 #include <stdio.h>
156 int main (int argc, char **argv)
158 static const int i = 1;
159 if ((*(char*)&i) == 0)
160 printf ("big");
161 else
162 printf ("little");
164 return 0;
166 """, '.c')
167 if ret[0]:
168 if ret[1] == 'big':
169 Conftest._Have (ctx, 'WORDS_BIGENDIAN', 1)
170 else:
171 Conftest._Have (ctx, 'WORDS_BIGENDIAN', 0)
172 ctx.Result (ret[1])
173 return True
174 else:
175 print "Can't build Syx without determining machine endianness"
176 ctx.Result (0)
177 return False
179 def check_inline (ctx):
180 ctx.Message ("Checking for inline...")
181 ret = ctx.TryRun ("""
182 #undef inline
183 inline int foo () { return 0; }
184 int main () { return foo (); }
185 """, '.c')
186 if ret[0]:
187 Conftest._Have (ctx, 'HAVE_INLINE', 1)
188 ctx.Result (True)
189 else:
190 Conftest._Have (ctx, 'HAVE_INLINE', 0)
191 ctx.Result (False)
193 def check__inline (ctx):
194 ctx.Message ("Checking for __inline...")
195 ret = ctx.TryRun ("""
196 __inline int foo () { return 0; }
197 int main () { return foo (); }
198 """, '.c')
199 if ret[0]:
200 Conftest._Have (ctx, 'HAVE__INLINE', 1)
201 ctx.Result (True)
202 else:
203 Conftest._Have (ctx, 'HAVE__INLINE', 0)
204 ctx.Result (False)
206 def check__inline__ (ctx):
207 ctx.Message ("Checking for __inline__...")
208 ret = ctx.TryRun ("""
209 __inline__ int foo () { return 0; }
210 int main () { return foo (); }
211 """, '.c')
212 if ret[0]:
213 Conftest._Have (ctx, 'HAVE__INLINE__', 1)
214 ctx.Result (True)
215 else:
216 Conftest._Have (ctx, 'HAVE__INLINE__', 0)
217 ctx.Result (False)
219 conf = Configure (env, custom_tests={ 'CheckEndianness' : check_endianness,
220 'CheckInline' : check_inline,
221 'Check__Inline': check__inline,
222 'Check__Inline__': check__inline__}, config_h="syx/syx-config.h")
225 # Cross compiling
227 if env['host']:
228 cenv = env.Clone (ENV=os.environ)
229 print
230 print 'Cross-compile to run on %s...' % env['host']
232 tool = env['host']+'-gcc'
233 env['CC'] = cenv.WhereIs (tool)
234 print 'Checking for %s... %s' % (tool, env['CC'])
235 if not env['CC']:
236 print "Can't find a valid C compiler"
237 env.Exit(1)
239 tool = env['host']+'-ar'
240 env['AR'] = cenv.WhereIs (tool)
241 print 'Checking for %s... %s' % (tool, env['AR'])
243 tool = env['host']+'-as'
244 env['AS'] = cenv.WhereIs (tool)
245 print 'Checking for %s... %s' % (tool, env['AS'])
247 tool = env['host']+'-ranlib'
248 env['RANLIB'] = cenv.WhereIs (tool)
249 print 'Checking for %s... %s' % (tool, env['RANLIB'])
251 tool = env['host']+'-windres'
252 env['RC'] = cenv.WhereIs (tool)
253 print 'Checking for %s... %s' % (tool, env['RC'])
255 if 'wince' in env['host']:
256 env.MergeFlags("-DWINCE")
258 # Do configuration
261 print 'Mandatory headers...'
263 for h in ['string.h', 'sys/stat.h', 'time.h', 'stdio.h', 'assert.h', 'fcntl.h',
264 'sys/types.h']:
265 if not conf.CheckCHeader (h):
266 print "Can't build Syx without %s header!" % h
267 env.Exit (1)
269 print
270 print 'Optional headers...'
272 for h in ['stdarg.h', 'byteswap.h', 'errno.h', 'unistd.h', 'stdint.h', 'sys/time.h']:
273 conf.CheckCHeader (h)
274 for t in ['int64_t']:
275 conf.CheckType (t, '#include <stdint.h>', 'c')
277 if env['PLATFORM'] == 'win32':
278 have_windows_h = conf.CheckCHeader ('windows.h')
280 print
281 print 'Mandatory functions...'
283 for f in ['strtol', 'strtod']:
284 if not conf.CheckFunc (f):
285 print "Can't build Syx without %s function!" % f
286 env.Exit (1)
288 if env['PLATFORM'] == 'win32':
289 lib = 'wsock32'
290 if 'wince' in env['host']:
291 lib = 'winsock'
292 conf.CheckLib ('coredll')
294 if not conf.CheckLibWithHeader (lib, 'winsock2.h', 'c', 'select(0, NULL, NULL, NULL, NULL);'):
295 print "Can't build Syx without select function!"
296 env.Exit (1)
297 else:
298 if not conf.CheckFunc ('select'):
299 print "Can't build Syx without select function!"
300 env.Exit (1)
302 if not conf.CheckLibWithHeader ('m', 'math.h', 'c', 'floor((double)3.4) == (double)3.0;'):
303 print "Can't build Syx without the math library!"
304 env.Exit (1)
306 if not conf.CheckEndianness ():
307 env.Exit (1)
309 "Assume we have __inline__"
310 if not (conf.CheckInline () or conf.Check__Inline () or conf.Check__Inline__ ()) and env['host']:
311 env.MergeFlags ("-DHAVE__INLINE__")
313 print
314 print 'Optional functions...'
316 for f in ['fstat', 'access', 'getenv', 'perror', 'signal']:
317 conf.CheckFunc (f)
319 if env['bignum']:
320 if not conf.CheckLibWithHeader ('gmp', 'gmp.h', 'c', 'mpz_t t; mpz_init (t); mpz_clear (t);'):
321 print "WARNING: gmp library not found. Multiple-precision numbers won't be supported"
323 if env['plugins']:
324 if (env['PLATFORM'] == 'win32' and have_windows_h) or conf.CheckLibWithHeader ('dl', 'dlfcn.h', 'c', 'dlopen(0, 0);'):
325 env.MergeFlags ('-DWITH_PLUGINS')
326 else:
327 print 'WARNING: building without plugins support'
328 env['plugins'] = False
330 conf.Finish ()
335 # Flags
336 env.MergeFlags ('-Wall -Wno-strict-aliasing -I#.')
337 env.MergeFlags (os.getenv('CFLAGS'))
338 env['LINKFLAGS'].append (os.getenv('CFLAGS'))
340 if env['PLATFORM'] == 'darwin':
341 env.MergeFlags ('-fno-common')
343 if env['iprofile']:
344 env.MergeFlags ('-DSYX_PROFILE')
346 if 'wince' in env['host']:
347 env.MergeFlags ('-DROOT_PATH="" -DIMAGE_PATH="default.sim" -DPLUGIN_PATH="lib"')
348 elif env['PLATFORM'] == 'win32':
349 env.MergeFlags ('-DROOT_PATH="." -DIMAGE_PATH="default.sim" -DPLUGIN_PATH="lib"')
350 else:
351 env.MergeFlags ('-DROOT_PATH="$rootdir" -DIMAGE_PATH="$imagepath" -DPLUGIN_PATH="$plugindir"')
353 if env['debug'] == 'no':
354 env.MergeFlags ('-O3')
355 elif env['debug'] == 'normal':
356 env.MergeFlags ('-g -O2')
357 elif env['debug'] == 'info':
358 env.MergeFlags ('-g -O -DSYX_DEBUG_INFO')
359 elif env['debug'] == 'full':
360 env.MergeFlags ('-g -O -DSYX_DEBUG_INFO -DSYX_DEBUG_FULL')
362 if env['PLATFORM'] == 'win32':
363 env.MergeFlags ('-DWINDOWS')
365 distdir = '#syx-0.1.7'
367 # Installation
369 def builder_syxinstall (target, sources):
370 t1 = env.Install (target, sources)
371 env.Alias ('install', t1)
372 if env['PLATFORM'] != 'win32':
373 t = env.Install (os.path.join (distdir, target), sources)
374 env.Alias ('bdist', t)
375 return t1
377 setattr (env, 'SyxInstall', builder_syxinstall)
379 # Build
381 env.MergeFlags ('-L#build/lib')
383 if (env['profile']):
384 env['LINKFLAGS'].append('-pg')
385 env.MergeFlags ('-pg')
386 env['shared'] = False
387 env['static'] = True
389 env.BuildDir ('build/lib', 'syx', False)
390 env.SConscript (dirs=['build/lib'], exports=['env', 'distdir'])
392 env.BuildDir ('build/bin', 'src', False)
393 env.SConscript (dirs=['build/bin'], exports=['env', 'distdir'])
395 env.BuildDir ('build/plugins', 'plugins', False)
396 env.SConscript (dirs=['build/plugins'], exports=['env', 'distdir'])
398 env.SConscript (dirs=['tests'], exports=['env', 'distdir'])
399 env.SConscript (dirs=['examples'], exports=['env', 'distdir'])
401 # Doc builder
403 env['doxygen'] = env.WhereIs ('doxygen')
404 if env['doc'] and env['doxygen']:
405 target = env.Command ('doc/reference', '#Doxyfile', '$doxygen $SOURCES')
406 Default (target)
407 path = os.path.join (env['docdir'], distdir[1:])
408 t1 = env.SyxInstall (path, target)
409 env.Alias ('install', t1)
410 env.Clean ('install', t1)
412 # Install data
414 kernel_sources = glob.glob ('st/kernel/*.st')
415 path = os.path.join (env['rootdir'], 'st', 'kernel')
416 env.SyxInstall (path, kernel_sources)
418 foreign_sources = glob.glob ('st/foreign/*.st')
419 path = os.path.join (env['rootdir'], 'st', 'foreign')
420 env.SyxInstall (path, foreign_sources)
422 if env['PLATFORM'] == 'posix':
423 desktoppath = os.path.join (env['datadir'], 'applications')
424 desktopapps = [os.path.join ('#share', 'syx.desktop'), os.path.join ('#share', 'syximage.desktop')]
425 env.SyxInstall (desktoppath, desktopapps)
427 path = os.path.join (env['datadir'], 'pixmaps')
428 env.SyxInstall (path, os.path.join ('#share', 'syx.png'))
429 env.SyxInstall (path, os.path.join ('#share', 'gnome-application-syx.png'))
431 path = os.path.join (env['datadir'], 'application-registry')
432 env.SyxInstall (path, os.path.join ('#share', 'syx.applications'))
434 path = os.path.join (env['datadir'], 'mime-info')
435 env.SyxInstall (path, os.path.join ('#share', 'syx.keys'))
436 mimepath = os.path.join (env['datadir'], 'mime')
437 mimesource = os.path.join ('#share', 'syx.xml')
438 env.SyxInstall (os.path.join (mimepath, 'packages'), mimesource)
440 update_mime_database = env.WhereIs ('update-mime-database')
441 if update_mime_database:
442 target = env.Command (mimepath, mimesource, 'update-mime-database $TARGET')
443 env.Alias ('install', target)
445 update_desktop_database = env.WhereIs ('update-desktop-database')
446 if update_desktop_database:
447 target = env.Command (desktoppath, desktopapps, 'update-desktop-database')
448 env.Alias ('install', target)
450 # Source distribution
452 path = os.path.join (distdir, 'st', 'kernel')
453 target = env.Install (path, kernel_sources)
454 env.Alias ('sdist', target)
456 path = os.path.join (distdir, 'st', 'foreign')
457 target = env.Install (path, foreign_sources)
458 env.Alias ('sdist', target)
460 sources = ['INSTALL', 'README', 'AUTHORS', 'ChangeLog', 'COPYING', 'SConstruct', 'TODO', 'NEWS', 'Doxyfile',
461 'README-BINARIES', 'syx.sln', 'syx.vcproj', 'makefile.vc',
462 'autogen.sh', 'compile', 'missing', 'mkinstalldirs', 'ltmain.sh', 'install-sh',
463 'configure', 'configure.ac', 'aclocal.m4', 'config.guess', 'config.sub', 'depcomp',
464 'Makefile.in', 'Makefile.am']
465 target = env.Install (distdir, sources)
466 env.Alias ('sdist', target)
468 sources = ['#share/syx.desktop', '#share/syx.png', '#share/gnome-application-syx.png',
469 '#share/syx.applications', '#share/syx.keys', '#share/syx.xml', '#share/syximage.desktop']
470 target = env.Install (os.path.join (distdir, 'share'), sources)
471 env.Alias ('sdist', target)
473 target = env.Install (os.path.join (distdir, 'doc', 'reference', 'html', 'extras'), '#doc/reference/html/extras/footer.html')
474 env.Alias ('sdist', target)
476 # Binary distribution
478 target = env.Install (distdir, '#README-BINARIES')
479 env.Alias ('bdist', target)