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