c3a46812e33ce02cb5bd40811a38d06abf3fa9a2
[ardour.git] / SConstruct
1 # -*- python -*-
2
3 import os
4 import sys
5 import re
6 import shutil
7 import glob
8 import errno
9 import time
10 import SCons.Node.FS
11
12 SConsignFile()
13 EnsureSConsVersion(0, 96)
14
15 version = '1.9beta1'
16
17 subst_dict = { }
18
19 #
20 # Command-line options
21 #
22
23 opts = Options('scache.conf')
24 opts.AddOptions(
25     BoolOption('ALTIVEC', 'Compile using Altivec instructions', 0),
26   ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
27     BoolOption('SYSLIBS', 'USE AT YOUR OWN RISK: CANCELS ALL SUPPORT FROM ARDOUR AUTHORS: Use existing system versions of various libraries instead of internal ones', 0),
28     BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
29     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
30     BoolOption('DEVBUILD', 'Use shared libardour (developers only)', 0),
31     BoolOption('NLS', 'Set to turn on i18n support', 1),
32     BoolOption('NOARCH', 'Do not use architecture-specific compilation flags', 0),
33     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
34     BoolOption('VST', 'Compile with support for VST', 0),
35     BoolOption('VERSIONED', 'Add version information to ardour/gtk executable name inside the build directory', 0),
36     BoolOption('USE_SSE_EVERYWHERE', 'Ask the compiler to use x86/SSE instructions and also our hand-written x86/SSE optimizations when possible (off by default)', 0),
37     BoolOption('BUILD_SSE_OPTIMIZATIONS', 'Use our hand-written x86/SSE optimizations when possible (off by default)', 0)
38   )
39
40 #----------------------------------------------------------------------
41 # a handy helper that provides a way to merge compile/link information
42 # from multiple different "environments"
43 #----------------------------------------------------------------------
44 #
45 class LibraryInfo(Environment):
46     def __init__(self,*args,**kw):
47         Environment.__init__ (self,*args,**kw)
48         
49     def Merge (self,others):
50         for other in others:
51             self.Append (LIBS = other.get ('LIBS',[]))
52             self.Append (LIBPATH = other.get ('LIBPATH', []))   
53             self.Append (CPPPATH = other.get('CPPPATH', []))
54             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
55
56
57 env = LibraryInfo (options = opts,
58                    CPPPATH = [ '.' ],
59                    VERSION = version,
60                    TARBALL='ardour-' + version + '.tar.bz2',
61                    DISTFILES = [ ],
62                    DISTTREE  = '#ardour-' + version,
63                    DISTCHECKDIR = '#ardour-' + version + '/check'
64                    )
65
66
67 #----------------------------------------------------------------------
68 # Builders
69 #----------------------------------------------------------------------
70
71 # Handy subst-in-file builder
72
73
74 def do_subst_in_file(targetfile, sourcefile, dict):
75         """Replace all instances of the keys of dict with their values.
76         For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
77         then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
78         """
79         try:
80             f = open(sourcefile, 'rb')
81             contents = f.read()
82             f.close()
83         except:
84             raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
85         for (k,v) in dict.items():
86             contents = re.sub(k, v, contents)
87         try:
88             f = open(targetfile, 'wb')
89             f.write(contents)
90             f.close()
91         except:
92             raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
93         return 0 # success
94  
95 def subst_in_file(target, source, env):
96         if not env.has_key('SUBST_DICT'):
97             raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
98         d = dict(env['SUBST_DICT']) # copy it
99         for (k,v) in d.items():
100             if callable(v):
101                 d[k] = env.subst(v())
102             elif SCons.Util.is_String(v):
103                 d[k]=env.subst(v)
104             else:
105                 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
106         for (t,s) in zip(target, source):
107             return do_subst_in_file(str(t), str(s), d)
108  
109 def subst_in_file_string(target, source, env):
110         """This is what gets printed on the console."""
111         return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
112                           for (t,s) in zip(target, source)])
113  
114 def subst_emitter(target, source, env):
115         """Add dependency from substituted SUBST_DICT to target.
116         Returns original target, source tuple unchanged.
117         """
118         d = env['SUBST_DICT'].copy() # copy it
119         for (k,v) in d.items():
120             if callable(v):
121                 d[k] = env.subst(v())
122             elif SCons.Util.is_String(v):
123                 d[k]=env.subst(v)
124         Depends(target, SCons.Node.Python.Value(d))
125         # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
126         return target, source
127  
128 subst_action = Action (subst_in_file, subst_in_file_string)
129 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
130
131 #
132 # internationalization
133 #
134
135 # po_helper
136 #
137 # this is not a builder. we can't list the .po files as a target,
138 # because then scons -c will remove them (even Precious doesn't alter
139 # this). this function is called whenever a .mo file is being
140 # built, and will conditionally update the .po file if necessary.
141 #
142
143 def po_helper(po,pot):
144     args = [ 'msgmerge',
145              '--update',
146              po,
147              pot,
148              ]
149     print 'Updating ' + po
150     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
151
152 # mo_builder: builder function for (binary) message catalogs (.mo)
153 #
154 # first source:  .po file
155 # second source: .pot file
156 #
157
158 def mo_builder(target,source,env):
159     po_helper (source[0].get_path(), source[1].get_path())
160     args = [ 'msgfmt',
161              '-c',
162              '-o',
163              target[0].get_path(),
164              source[0].get_path()
165              ]
166     return os.spawnvp (os.P_WAIT, 'msgfmt', args)
167
168 mo_bld = Builder (action = mo_builder)
169 env.Append(BUILDERS = {'MoBuild' : mo_bld})
170
171 # pot_builder: builder function for message templates (.pot)
172 #
173 # source: list of C/C++ etc. files to extract messages from
174 #
175
176 def pot_builder(target,source,env):
177     args = [ 'xgettext', 
178              '--keyword=_',
179              '--keyword=N_',
180              '--from-code=UTF-8',
181              '-o', target[0].get_path(), 
182              "--default-domain=" + env['PACKAGE'],
183              '--copyright-holder="Paul Davis"' ]
184     args += [ src.get_path() for src in source ]
185
186     return os.spawnvp (os.P_WAIT, 'xgettext', args)
187
188 pot_bld = Builder (action = pot_builder)
189 env.Append(BUILDERS = {'PotBuild' : pot_bld})
190
191 #
192 # utility function, not a builder
193 #
194
195 def i18n (buildenv, sources, installenv):
196     domain = buildenv['PACKAGE']
197     potfile = buildenv['POTFILE']
198
199     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
200
201     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
202     languages = [ po.replace ('.po', '') for po in p_oze ]
203     m_oze = [ po.replace (".po", ".mo") for po in p_oze ]
204     
205     for mo in m_oze[:]:
206         po = 'po/' + mo.replace (".mo", ".po")
207         installenv.Alias ('install', buildenv.MoBuild (mo, [ po, potfile ]))
208         
209     for lang in languages[:]:
210         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
211         moname = domain + '.mo'
212         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
213
214 #
215 # A generic builder for version.cc files
216
217 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
218 # note: assumes one source files, the header that declares the version variables
219
220 def version_builder (target, source, env):
221    text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
222    text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
223    text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
224
225    try:
226       o = file (target[0].get_path(), 'w')
227       o.write (text)
228       o.close ();
229    except IOError:
230       print "Could not open", target[0].get_path(), " for writing\n"
231       sys.exit (-1)
232
233    text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n";
234    text += "#define __" + env['DOMAIN'] + "_version_h__\n";
235    text += "extern int " + env['DOMAIN'] + "_major_version;\n"
236    text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
237    text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
238    text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n";
239
240    try:
241       o = file (target[1].get_path(), 'w')
242       o.write (text)
243       o.close ();
244    except IOError:
245       print "Could not open", target[1].get_path(), " for writing\n"
246       sys.exit (-1)
247   
248    return None
249
250 version_bld = Builder (action = version_builder)
251 env.Append (BUILDERS = {'VersionBuild' : version_bld})
252
253 #
254 # a builder that makes a hard link from the 'source' executable to a name with
255 # a "build ID" based on the most recent CVS activity that might be reasonably
256 # related to version activity. this relies on the idea that the SConscript
257 # file that builds the executable is updated with new version info and committed
258 # to the source code repository whenever things change.
259 #
260
261 def versioned_builder(target,source,env):
262     # build ID is composed of a representation of the date of the last CVS transaction
263     # for this (SConscript) file
264     
265     try:
266         o = file (source[0].get_dir().get_path() +  '/CVS/Entries', "r")
267     except IOError:
268         print "Could not CVS/Entries for reading"
269         return -1
270
271     last_date = ""        
272     lines = o.readlines()
273     for line in lines:
274         if line[0:12] == '/SConscript/':
275             parts = line.split ("/")
276             last_date = parts[3]
277             break
278     o.close ()
279
280     if last_date == "":
281         print "No SConscript CVS update info found - versioned executable cannot be built"
282         return -1
283
284     tag = time.strftime ('%Y%M%d%H%m', time.strptime (last_date));
285     print "The current build ID is " + tag
286
287     tagged_executable = source[0].get_path() + '-' + tag
288
289     if os.path.exists (tagged_executable):
290         print "Replacing existing executable with the same build tag."
291         os.unlink (tagged_executable)
292
293     return os.link (source[0].get_path(), tagged_executable)
294
295 verbuild = Builder (action = versioned_builder)
296 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
297
298 #
299 # source tar file builder
300 #
301
302 def distcopy (target, source, env):
303     treedir = str (target[0])
304
305     try:
306         os.mkdir (treedir)
307     except OSError, (errnum, strerror):
308         if errnum != errno.EEXIST:
309             print 'mkdir ', treedir, ':', strerror
310
311     cmd = 'tar cf - '
312     #
313     # we don't know what characters might be in the file names
314     # so quote them all before passing them to the shell
315     #
316     all_files = ([ str(s) for s in source ])
317     cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
318     cmd += ' | (cd ' + treedir + ' && tar xf -)'
319     p = os.popen (cmd)
320     return p.close ();
321
322 def tarballer (target, source, env):            
323     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'"
324     print 'running ', cmd, ' ... '
325     p = os.popen (cmd)
326     return p.close ()
327
328 dist_bld = Builder (action = distcopy,
329                     target_factory = SCons.Node.FS.default_fs.Entry,
330                     source_factory = SCons.Node.FS.default_fs.Entry,
331                     multi = 1)
332
333 tarball_bld = Builder (action = tarballer,
334                        target_factory = SCons.Node.FS.default_fs.Entry,
335                        source_factory = SCons.Node.FS.default_fs.Entry)
336
337 env.Append (BUILDERS = {'Distribute' : dist_bld})
338 env.Append (BUILDERS = {'Tarball' : tarball_bld})
339
340 # ----------------------------------------------------------------------
341 # Construction environment setup
342 # ----------------------------------------------------------------------
343
344 libraries = { }
345
346 libraries['core'] = LibraryInfo (CPPPATH = [ '#libs'])
347
348 libraries['sndfile'] = LibraryInfo()
349 libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
350
351 libraries['lrdf'] = LibraryInfo()
352 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
353
354 libraries['raptor'] = LibraryInfo()
355 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
356
357 libraries['samplerate'] = LibraryInfo()
358 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
359
360 libraries['jack'] = LibraryInfo()
361 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
362
363 libraries['xml'] = LibraryInfo()
364 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
365
366 libraries['glib2'] = LibraryInfo()
367 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
368 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
369 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
370
371 libraries['gtk2'] = LibraryInfo()
372 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
373
374 libraries['pango'] = LibraryInfo()
375 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
376
377 libraries['libgnomecanvas2'] = LibraryInfo()
378 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
379
380 libraries['glade2'] = LibraryInfo()
381 libraries['glade2'].ParseConfig ('pkg-config --cflags --libs libglade-2.0')
382
383 libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
384
385 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
386 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
387 libraries['pbd3']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
388 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
389 #libraries['cassowary'] = LibraryInfo(LIBS='cassowary', LIBPATH='#libs/cassowary', CPPPATH='#libs/cassowary')
390
391 libraries['fst'] = LibraryInfo()
392 if env['VST']:
393     libraries['fst'].ParseConfig('pkg-config --cflags --libs libfst')
394
395 #
396 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
397
398
399 conf = Configure(env)
400
401 if conf.CheckCHeader('alsa/asoundlib.h'):
402     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
403     env['SYSMIDI'] = 'ALSA Sequencer'
404     subst_dict['%MIDITAG%'] = "seq"
405     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
406 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
407     # this line is needed because scons can't handle -framework in ParseConfig() yet.
408     libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -bind_at_load')
409     env['SYSMIDI'] = 'CoreMIDI'
410     subst_dict['%MIDITAG%'] = "ardour"
411     subst_dict['%MIDITYPE%'] = "coremidi"
412
413 env = conf.Finish()
414
415 if env['SYSLIBS']:
416
417     libraries['sigc2'] = LibraryInfo()
418     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
419
420     libraries['gtkmm2'] = LibraryInfo()
421     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.0')
422     
423     libraries['libglademm'] = LibraryInfo()
424     libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
425     
426     libraries['soundtouch'] = LibraryInfo(LIBS='SoundTouch')
427
428     coredirs = [
429         'templates'
430     ]
431
432     subdirs = [
433 #       'libs/cassowary',
434         'libs/pbd3',
435         'libs/midi++2',
436         'libs/ardour',
437         'templates'
438         ]
439
440     gtk_subdirs = [
441         'libs/gtkmm2ext',
442         'gtk2_ardour',
443         ]
444
445 else:
446     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
447                                     LIBPATH='#libs/sigc++2',
448                                     CPPPATH='#libs/sigc++2')
449     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
450                                     LIBPATH='#libs/glibmm2',
451                                     CPPPATH='#libs/glibmm2')
452     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
453                                     LIBPATH='#libs/gtkmm2/pango',
454                                     CPPPATH='#libs/gtkmm2/pango')
455     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
456                                      LIBPATH='#libs/gtkmm2/atk',
457                                      CPPPATH='#libs/gtkmm2/atk')
458     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
459                                       LIBPATH='#libs/gtkmm2/gdk',
460                                       CPPPATH='#libs/gtkmm2/gdk')
461     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
462                                      LIBPATH="#libs/gtkmm2/gtk",
463                                      CPPPATH='#libs/gtkmm2/gtk/')
464     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
465                                                 LIBPATH='#libs/libgnomecanvasmm',
466                                                 CPPPATH='#libs/libgnomecanvasmm')
467
468     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
469                                           LIBPATH='#libs/soundtouch',
470                                           CPPPATH=['#libs', '#libs/soundtouch'])
471     libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
472                                           LIBPATH='#libs/libglademm',
473                                           CPPPATH='#libs/libglademm')
474
475     coredirs = [
476         'libs/soundtouch',
477         'templates'
478     ]
479
480     subdirs = [
481 #       'libs/cassowary',
482         'libs/sigc++2',
483         'libs/pbd3',
484         'libs/midi++2',
485         'libs/ardour'
486         ]
487
488     gtk_subdirs = [
489         'libs/glibmm2',
490         'libs/gtkmm2/pango',
491         'libs/gtkmm2/atk',
492         'libs/gtkmm2/gdk',
493         'libs/gtkmm2/gtk',
494         'libs/libglademm',
495         'libs/libgnomecanvasmm',
496         'libs/flowcanvas',
497         'libs/gtkmm2ext',
498         'gtk2_ardour'
499         ]
500
501 opts.Save('scache.conf', env)
502 Help(opts.GenerateHelpText(env))
503
504 if os.environ.has_key('PATH'):
505     env.Append(PATH = os.environ['PATH'])
506
507 if os.environ.has_key('PKG_CONFIG_PATH'):
508     env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
509
510 if os.environ.has_key('CC'):
511     env['CC'] = os.environ['CC']
512
513 if os.environ.has_key('CXX'):
514     env['CXX'] = os.environ['CXX']
515
516 if os.environ.has_key('DISTCC_HOSTS'):
517     env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
518     env['ENV']['HOME'] = os.environ['HOME']
519     
520 final_prefix = '$PREFIX'
521 install_prefix = '$DESTDIR/$PREFIX'
522
523 if env['PREFIX'] == '/usr':
524     final_config_prefix = '/etc'
525 else:
526     final_config_prefix = env['PREFIX'] + '/etc'
527
528 config_prefix = '$DESTDIR' + final_config_prefix
529
530
531 # SCons should really do this for us
532
533 conf = Configure (env)
534
535 have_cxx = conf.TryAction (Action (env['CXX'] + ' --version'));
536 if have_cxx[0] != 1:
537     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
538     exit (1);
539 else:
540     print "Congratulations, you have a functioning C++ compiler."
541     
542 env = conf.Finish()
543
544 #
545 # Compiler flags and other system-dependent stuff
546 #
547
548 opt_flags = []
549 debug_flags = [ '-g' ]
550
551 # guess at the platform, used to define compiler flags
552
553 config_guess = os.popen("tools/config.guess").read()[:-1]
554
555 config_cpu = 0;
556 config_arch = 1;
557 config_kernel = 2;
558 config_os = 3;
559 config = config_guess.split ("-")
560
561 #
562 # on OS X darwinports puts things in /opt/local by default
563 #
564 if config[config_arch] == 'apple':
565     if os.path.isdir('/opt/local/lib'):
566         libraries['core'].Append (LIBPATH = [ '/opt/local/lib' ])
567     if os.path.isdir('/opt/local/include'):
568         libraries['core'].Append (CPPPATH = [ '/opt/local/include' ])
569 if config[config_cpu] == 'powerpc':
570     #
571     # Apple/PowerPC optimization options
572     #
573     # -mcpu=7450 does not reliably work with gcc 3.*
574     #
575     if env['NOARCH'] == 0:
576         if env['ALTIVEC'] == 1:
577             if config[config_arch] == 'apple':
578                 opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
579             else:
580                 opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"]) 
581         else:
582             opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
583         opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
584
585 elif ((re.search ("i[0-9]86", config[config_cpu]) != None) or (re.search ("x86_64", config[config_cpu]) != None)):
586
587     build_host_supports_sse = 0
588     
589     if env['NOARCH'] == 0:
590
591         debug_flags.append ("-DARCH_X86")
592         opt_flags.append ("-DARCH_X86")
593
594         if config[config_kernel] == 'linux' :
595
596             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
597             x86_flags = flag_line.split (": ")[1:][0].split (' ')
598
599             if "mmx" in x86_flags:
600                 opt_flags.append ("-mmmx")
601             if "sse" in x86_flags:
602                 build_host_supports_sse = 1
603             if "3dnow" in x86_flags:
604                 opt_flags.append ("-m3dnow")
605
606             if config[config_cpu] == "i586":
607                 opt_flags.append ("-march=i586")
608             elif config[config_cpu] == "i686":
609                 opt_flags.append ("-march=i686")
610
611         if env['USE_SSE_EVERYWHERE'] == 1:
612                 opt_flags.extend (["-msse", "-mfpmath=sse"])
613                 debug_flags.extend (["-msse", "-mfpmath=sse"])
614                 if build_host_supports_sse != 1:
615                     print "\nWarning: you are building Ardour with SSE support even though your system does not support these instructions. (This may not be an error, especially if you are a package maintainer)"
616
617         if env['BUILD_SSE_OPTIMIZATIONS'] == 1:
618                 opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
619                 debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
620                 if build_host_supports_sse != 1:
621                     print "\nWarning: you are building Ardour with SSE support even though your system does not support these instructions. (This may not be an error, especially if you are a package maintainer)"
622                     
623 # end of processor-specific section
624
625 #
626 # ARCH="..." overrides all 
627 #
628
629 if env['ARCH'] != '':
630     opt_flags = env['ARCH'].split()
631
632 #
633 # prepend boiler plate optimization flags
634 #
635
636 opt_flags[:0] = [
637     "-O3",
638     "-fomit-frame-pointer",
639     "-ffast-math",
640     "-fstrength-reduce"
641     ]
642
643 if env['DEBUG'] == 1:
644     env.Append(CCFLAGS=" ".join (debug_flags))
645 else:
646     env.Append(CCFLAGS=" ".join (opt_flags))
647
648 env.Append(CCFLAGS="-Wall")
649
650 if env['VST']:
651     env.Append(CCFLAGS="-DVST_SUPPORT")
652
653
654 # check endianness
655 if sys.byteorder == "big":
656     print "Host is big endian"
657     env.Append(CCFLAGS="-DWORDS_BIGENDIAN")
658 else:
659     print "Host is little endian"
660
661
662 #
663 # everybody needs this
664 #
665
666 env.Merge ([ libraries['core'] ])
667
668 #
669 # i18n support 
670 #
671
672 conf = Configure (env)
673
674 if env['NLS']:
675     print 'Checking for internationalization support ...'
676     have_gettext = conf.TryAction(Action('xgettext --version'))
677     if have_gettext[0] != 1:
678         print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
679         env['NLS'] = 0
680         
681     if conf.CheckCHeader('libintl.h') == None:
682         print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
683         env['NLS'] = 0
684
685
686 env = conf.Finish()
687
688 if env['NLS'] == 1:
689     env.Append(CCFLAGS="-DENABLE_NLS")
690
691
692 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
693
694 #
695 # the configuration file may be system dependent
696 #
697
698 conf = env.Configure ()
699
700 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
701     subst_dict['%JACK_BACKEND%'] = "coreaudio:Built-in Audio:in"
702 else:
703     subst_dict['%JACK_BACKEND%'] = "alsa_pcm:playback_"
704
705 # posix_memalign available
706 if not conf.CheckFunc('posix_memalign'):
707     print 'Did not find posix_memalign(), using malloc'
708     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
709
710
711 env = conf.Finish()
712
713 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
714
715 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour_system.rc'))
716 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.rc'))
717
718 Default (rcbuild)
719
720 # source tarball
721
722 Precious (env['DISTTREE'])
723
724 #
725 # note the special "cleanfirst" source name. this triggers removal
726 # of the existing disttree
727 #
728
729 env.Distribute (env['DISTTREE'],
730                 [ 'SConstruct',
731                   'COPYING', 'PACKAGER_README', 'README',
732                   'ardour.rc.in',
733                   'ardour_system.rc',
734                   'tools/config.guess'
735                   ] +
736                 glob.glob ('DOCUMENTATION/AUTHORS*') +
737                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
738                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
739                 glob.glob ('DOCUMENTATION/BUILD*') +
740                 glob.glob ('DOCUMENTATION/FAQ*') +
741                 glob.glob ('DOCUMENTATION/README*')
742                 )
743                 
744 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
745 env.Alias ('srctar', srcdist)
746 #
747 # don't leave the distree around 
748 #
749 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
750 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
751
752 #
753 # the subdirs
754
755
756 for subdir in coredirs:
757     SConscript (subdir + '/SConscript')
758
759 for sublistdir in [subdirs, gtk_subdirs]:
760         for subdir in sublistdir:
761                 SConscript (subdir + '/SConscript')
762
763 # cleanup
764 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
765