aab1b830b5009168ac8131556b4f80808fffe8fa
[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['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
393
394 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
395 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
396 libraries['pbd3']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
397 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
398 #libraries['cassowary'] = LibraryInfo(LIBS='cassowary', LIBPATH='#libs/cassowary', CPPPATH='#libs/cassowary')
399
400 libraries['fst'] = LibraryInfo()
401 if env['VST']:
402     libraries['fst'].ParseConfig('pkg-config --cflags --libs libfst')
403
404 #
405 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
406
407
408 conf = Configure(env)
409
410 if conf.CheckCHeader('alsa/asoundlib.h'):
411     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
412     env['SYSMIDI'] = 'ALSA Sequencer'
413     subst_dict['%MIDITAG%'] = "seq"
414     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
415 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
416     # this line is needed because scons can't handle -framework in ParseConfig() yet.
417     libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load')
418     env['SYSMIDI'] = 'CoreMIDI'
419     subst_dict['%MIDITAG%'] = "ardour"
420     subst_dict['%MIDITYPE%'] = "coremidi"
421
422 env = conf.Finish()
423
424 if env['SYSLIBS']:
425
426     libraries['sigc2'] = LibraryInfo()
427     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
428     libraries['glibmm2'] = LibraryInfo()
429     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
430     libraries['gdkmm2'] = LibraryInfo()
431     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
432     libraries['gtkmm2'] = LibraryInfo()
433     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
434     libraries['atkmm'] = LibraryInfo()
435     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
436     libraries['pangomm'] = LibraryInfo()
437     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
438     libraries['libgnomecanvasmm'] = LibraryInfo()
439     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
440     libraries['libglademm'] = LibraryInfo()
441     libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
442
443 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
444     libraries['soundtouch'] = LibraryInfo()
445     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
446
447     coredirs = [
448         'templates'
449     ]
450
451     subdirs = [
452         'libs/pbd3',
453         'libs/midi++2',
454         'libs/ardour'
455         ]
456
457     gtk_subdirs = [
458 #        'libs/flowcanvas',
459         'libs/gtkmm2ext',
460         'gtk2_ardour'
461         ]
462
463 else:
464     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
465                                     LIBPATH='#libs/sigc++2',
466                                     CPPPATH='#libs/sigc++2')
467     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
468                                     LIBPATH='#libs/glibmm2',
469                                     CPPPATH='#libs/glibmm2')
470     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
471                                     LIBPATH='#libs/gtkmm2/pango',
472                                     CPPPATH='#libs/gtkmm2/pango')
473     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
474                                      LIBPATH='#libs/gtkmm2/atk',
475                                      CPPPATH='#libs/gtkmm2/atk')
476     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
477                                       LIBPATH='#libs/gtkmm2/gdk',
478                                       CPPPATH='#libs/gtkmm2/gdk')
479     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
480                                      LIBPATH="#libs/gtkmm2/gtk",
481                                      CPPPATH='#libs/gtkmm2/gtk/')
482     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
483                                                 LIBPATH='#libs/libgnomecanvasmm',
484                                                 CPPPATH='#libs/libgnomecanvasmm')
485
486     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
487                                           LIBPATH='#libs/soundtouch',
488                                           CPPPATH=['#libs', '#libs/soundtouch'])
489     libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
490                                           LIBPATH='#libs/libglademm',
491                                           CPPPATH='#libs/libglademm')
492
493     coredirs = [
494         'libs/soundtouch',
495         'templates'
496     ]
497
498     subdirs = [
499 #       'libs/cassowary',
500         'libs/sigc++2',
501         'libs/pbd3',
502         'libs/midi++2',
503         'libs/ardour'
504         ]
505
506     gtk_subdirs = [
507         'libs/glibmm2',
508         'libs/gtkmm2/pango',
509         'libs/gtkmm2/atk',
510         'libs/gtkmm2/gdk',
511         'libs/gtkmm2/gtk',
512     'libs/libglademm',
513         'libs/libgnomecanvasmm',
514 #       'libs/flowcanvas',
515     'libs/gtkmm2ext',
516     'gtk2_ardour'
517         ]
518
519 opts.Save('scache.conf', env)
520 Help(opts.GenerateHelpText(env))
521
522 if os.environ.has_key('PATH'):
523     env.Append(PATH = os.environ['PATH'])
524
525 if os.environ.has_key('PKG_CONFIG_PATH'):
526     env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
527
528 if os.environ.has_key('CC'):
529     env['CC'] = os.environ['CC']
530
531 if os.environ.has_key('CXX'):
532     env['CXX'] = os.environ['CXX']
533
534 if os.environ.has_key('DISTCC_HOSTS'):
535     env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
536     env['ENV']['HOME'] = os.environ['HOME']
537     
538 final_prefix = '$PREFIX'
539 install_prefix = '$DESTDIR/$PREFIX'
540
541 if env['PREFIX'] == '/usr':
542     final_config_prefix = '/etc'
543 else:
544     final_config_prefix = env['PREFIX'] + '/etc'
545
546 config_prefix = '$DESTDIR' + final_config_prefix
547
548
549 # SCons should really do this for us
550
551 conf = Configure (env)
552
553 have_cxx = conf.TryAction (Action (env['CXX'] + ' --version'))
554 if have_cxx[0] != 1:
555     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
556     exit (1)
557 else:
558     print "Congratulations, you have a functioning C++ compiler."
559     
560 env = conf.Finish()
561
562 #
563 # Compiler flags and other system-dependent stuff
564 #
565
566 opt_flags = []
567 debug_flags = [ '-g' ]
568
569 # guess at the platform, used to define compiler flags
570
571 config_guess = os.popen("tools/config.guess").read()[:-1]
572
573 config_cpu = 0
574 config_arch = 1
575 config_kernel = 2
576 config_os = 3
577 config = config_guess.split ("-")
578
579 print "system triple: " + config_guess
580
581 # Autodetect
582 if env['DIST_TARGET'] == 'auto':
583     if config[config_arch] == 'apple':
584         # The [.] matches to the dot after the major version, "." would match any character
585         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
586             env['DIST_TARGET'] = 'panther'
587         else:
588             env['DIST_TARGET'] = 'tiger'
589     else:
590         if re.search ("x86_64", config[config_cpu]) != None:
591             env['DIST_TARGET'] = 'x86_64'
592         elif re.search("i[0-5]86", config[config_cpu]) != None:
593             env['DIST_TARGET'] = 'i386'
594         elif re.search("powerpc", config[config_cpu]) != None:
595             env['DIST_TARGET'] = 'powerpc'
596         else:
597             env['DIST_TARGET'] = 'i686'
598     print "\n*******************************"
599     print "detected DIST_TARGET = " + env['DIST_TARGET']
600     print "*******************************\n"
601
602
603 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
604     #
605     # Apple/PowerPC optimization options
606     #
607     # -mcpu=7450 does not reliably work with gcc 3.*
608     #
609     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
610         if config[config_arch] == 'apple':
611             opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
612         else:
613             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"]) 
614     else:
615         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
616     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
617
618 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':
619
620     build_host_supports_sse = 0
621     
622     debug_flags.append ("-DARCH_X86")
623     opt_flags.append ("-DARCH_X86")
624
625     if config[config_kernel] == 'linux' :
626
627         if env['DIST_TARGET'] != 'i386': 
628
629             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
630             x86_flags = flag_line.split (": ")[1:][0].split (' ')
631
632             if "mmx" in x86_flags:
633                 opt_flags.append ("-mmmx")
634             if "sse" in x86_flags:
635                 build_host_supports_sse = 1
636             if "3dnow" in x86_flags:
637                 opt_flags.append ("-m3dnow")
638
639             if config[config_cpu] == "i586":
640                 opt_flags.append ("-march=i586")
641             elif config[config_cpu] == "i686":
642                 opt_flags.append ("-march=i686")
643
644     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
645         opt_flags.extend (["-msse", "-mfpmath=sse"])
646         debug_flags.extend (["-msse", "-mfpmath=sse"])
647 # end of processor-specific section
648
649 # optimization section
650 if env['FPU_OPTIMIZATION']:
651     if env['DIST_TARGET'] == 'tiger':
652         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
653         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
654         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
655     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
656         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
657         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
658         if env['DIST_TARGET'] == 'x86_64':
659             opt_flags.append ("-DUSE_X86_64_ASM")
660             debug_flags.append ("-DUSE_X86_64_ASM")
661         if build_host_supports_sse != 1:
662             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)"
663 # end optimization section
664
665 #
666 # ARCH="..." overrides all 
667 #
668
669 if env['ARCH'] != '':
670     opt_flags = env['ARCH'].split()
671
672 #
673 # prepend boiler plate optimization flags
674 #
675
676 opt_flags[:0] = [
677     "-O3",
678     "-fomit-frame-pointer",
679     "-ffast-math",
680     "-fstrength-reduce"
681     ]
682
683 if env['DEBUG'] == 1:
684     env.Append(CCFLAGS=" ".join (debug_flags))
685 else:
686     env.Append(CCFLAGS=" ".join (opt_flags))
687
688 env.Append(CCFLAGS="-Wall")
689
690 if env['VST']:
691     env.Append(CCFLAGS="-DVST_SUPPORT")
692
693 #
694 # everybody needs this
695 #
696
697 env.Merge ([ libraries['core'] ])
698
699 #
700 # i18n support 
701 #
702
703 conf = Configure (env)
704
705 if env['NLS']:
706     print 'Checking for internationalization support ...'
707     have_gettext = conf.TryAction(Action('xgettext --version'))
708     if have_gettext[0] != 1:
709         print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
710         env['NLS'] = 0
711         
712     if conf.CheckCHeader('libintl.h') == None:
713         print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
714         env['NLS'] = 0
715
716
717 env = conf.Finish()
718
719 if env['NLS'] == 1:
720     env.Append(CCFLAGS="-DENABLE_NLS")
721
722
723 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
724
725 #
726 # the configuration file may be system dependent
727 #
728
729 conf = env.Configure ()
730
731 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
732     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
733     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
734 else:
735     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
736     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
737
738 # posix_memalign available
739 if not conf.CheckFunc('posix_memalign'):
740     print 'Did not find posix_memalign(), using malloc'
741     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
742
743
744 env = conf.Finish()
745
746 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
747
748 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
749 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.rc'))
750
751 Default (rcbuild)
752
753 # source tarball
754
755 Precious (env['DISTTREE'])
756
757 #
758 # note the special "cleanfirst" source name. this triggers removal
759 # of the existing disttree
760 #
761
762 env.Distribute (env['DISTTREE'],
763                 [ 'SConstruct',
764                   'COPYING', 'PACKAGER_README', 'README',
765                   'ardour.rc.in',
766                   'ardour_system.rc',
767                   'tools/config.guess'
768                   ] +
769                 glob.glob ('DOCUMENTATION/AUTHORS*') +
770                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
771                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
772                 glob.glob ('DOCUMENTATION/BUILD*') +
773                 glob.glob ('DOCUMENTATION/FAQ*') +
774                 glob.glob ('DOCUMENTATION/README*')
775                 )
776                 
777 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
778 env.Alias ('srctar', srcdist)
779 #
780 # don't leave the distree around 
781 #
782 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
783 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
784
785 #
786 # the subdirs
787
788
789 for subdir in coredirs:
790     SConscript (subdir + '/SConscript')
791
792 for sublistdir in [subdirs, gtk_subdirs]:
793         for subdir in sublistdir:
794                 SConscript (subdir + '/SConscript')
795
796 # cleanup
797 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
798