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