a) dynamically loadable control surface support
[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 surface_subdirs = [
522     'libs/surfaces/tranzport',
523     'libs/surfaces/generic_midi'
524     ]
525
526 opts.Save('scache.conf', env)
527 Help(opts.GenerateHelpText(env))
528
529 if os.environ.has_key('PATH'):
530     env.Append(PATH = os.environ['PATH'])
531
532 if os.environ.has_key('PKG_CONFIG_PATH'):
533     env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
534
535 if os.environ.has_key('CC'):
536     env['CC'] = os.environ['CC']
537
538 if os.environ.has_key('CXX'):
539     env['CXX'] = os.environ['CXX']
540
541 if os.environ.has_key('DISTCC_HOSTS'):
542     env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
543     env['ENV']['HOME'] = os.environ['HOME']
544     
545 final_prefix = '$PREFIX'
546 install_prefix = '$DESTDIR/$PREFIX'
547
548 if env['PREFIX'] == '/usr':
549     final_config_prefix = '/etc'
550 else:
551     final_config_prefix = env['PREFIX'] + '/etc'
552
553 config_prefix = '$DESTDIR' + final_config_prefix
554
555
556 # SCons should really do this for us
557
558 conf = Configure (env)
559
560 have_cxx = conf.TryAction (Action (env['CXX'] + ' --version'))
561 if have_cxx[0] != 1:
562     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
563     exit (1)
564 else:
565     print "Congratulations, you have a functioning C++ compiler."
566     
567 env = conf.Finish()
568
569 #
570 # Compiler flags and other system-dependent stuff
571 #
572
573 opt_flags = []
574 debug_flags = [ '-g' ]
575
576 # guess at the platform, used to define compiler flags
577
578 config_guess = os.popen("tools/config.guess").read()[:-1]
579
580 config_cpu = 0
581 config_arch = 1
582 config_kernel = 2
583 config_os = 3
584 config = config_guess.split ("-")
585
586 print "system triple: " + config_guess
587
588 # Autodetect
589 if env['DIST_TARGET'] == 'auto':
590     if config[config_arch] == 'apple':
591         # The [.] matches to the dot after the major version, "." would match any character
592         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
593             env['DIST_TARGET'] = 'panther'
594         else:
595             env['DIST_TARGET'] = 'tiger'
596     else:
597         if re.search ("x86_64", config[config_cpu]) != None:
598             env['DIST_TARGET'] = 'x86_64'
599         elif re.search("i[0-5]86", config[config_cpu]) != None:
600             env['DIST_TARGET'] = 'i386'
601         elif re.search("powerpc", config[config_cpu]) != None:
602             env['DIST_TARGET'] = 'powerpc'
603         else:
604             env['DIST_TARGET'] = 'i686'
605     print "\n*******************************"
606     print "detected DIST_TARGET = " + env['DIST_TARGET']
607     print "*******************************\n"
608
609
610 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
611     #
612     # Apple/PowerPC optimization options
613     #
614     # -mcpu=7450 does not reliably work with gcc 3.*
615     #
616     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
617         if config[config_arch] == 'apple':
618             opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
619         else:
620             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"]) 
621     else:
622         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
623     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
624
625 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':
626
627     build_host_supports_sse = 0
628     
629     debug_flags.append ("-DARCH_X86")
630     opt_flags.append ("-DARCH_X86")
631
632     if config[config_kernel] == 'linux' :
633
634         if env['DIST_TARGET'] != 'i386': 
635
636             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
637             x86_flags = flag_line.split (": ")[1:][0].split (' ')
638
639             if "mmx" in x86_flags:
640                 opt_flags.append ("-mmmx")
641             if "sse" in x86_flags:
642                 build_host_supports_sse = 1
643             if "3dnow" in x86_flags:
644                 opt_flags.append ("-m3dnow")
645
646             if config[config_cpu] == "i586":
647                 opt_flags.append ("-march=i586")
648             elif config[config_cpu] == "i686":
649                 opt_flags.append ("-march=i686")
650
651     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
652         opt_flags.extend (["-msse", "-mfpmath=sse"])
653         debug_flags.extend (["-msse", "-mfpmath=sse"])
654 # end of processor-specific section
655
656 # optimization section
657 if env['FPU_OPTIMIZATION']:
658     if env['DIST_TARGET'] == 'tiger':
659         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
660         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
661         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
662     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
663         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
664         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
665         if env['DIST_TARGET'] == 'x86_64':
666             opt_flags.append ("-DUSE_X86_64_ASM")
667             debug_flags.append ("-DUSE_X86_64_ASM")
668         if build_host_supports_sse != 1:
669             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)"
670 # end optimization section
671
672 #
673 # ARCH="..." overrides all 
674 #
675
676 if env['ARCH'] != '':
677     opt_flags = env['ARCH'].split()
678
679 #
680 # prepend boiler plate optimization flags
681 #
682
683 opt_flags[:0] = [
684     "-O3",
685     "-fomit-frame-pointer",
686     "-ffast-math",
687     "-fstrength-reduce"
688     ]
689
690 if env['DEBUG'] == 1:
691     env.Append(CCFLAGS=" ".join (debug_flags))
692 else:
693     env.Append(CCFLAGS=" ".join (opt_flags))
694
695 env.Append(CCFLAGS="-Wall")
696
697 if env['VST']:
698     env.Append(CCFLAGS="-DVST_SUPPORT")
699
700 #
701 # everybody needs this
702 #
703
704 env.Merge ([ libraries['core'] ])
705
706 #
707 # i18n support 
708 #
709
710 conf = Configure (env)
711
712 if env['NLS']:
713     print 'Checking for internationalization support ...'
714     have_gettext = conf.TryAction(Action('xgettext --version'))
715     if have_gettext[0] != 1:
716         print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
717         env['NLS'] = 0
718         
719     if conf.CheckCHeader('libintl.h') == None:
720         print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
721         env['NLS'] = 0
722
723
724 env = conf.Finish()
725
726 if env['NLS'] == 1:
727     env.Append(CCFLAGS="-DENABLE_NLS")
728
729
730 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
731
732 #
733 # the configuration file may be system dependent
734 #
735
736 conf = env.Configure ()
737
738 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
739     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
740     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
741 else:
742     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
743     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
744
745 # posix_memalign available
746 if not conf.CheckFunc('posix_memalign'):
747     print 'Did not find posix_memalign(), using malloc'
748     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
749
750
751 env = conf.Finish()
752
753 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
754
755 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
756 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.rc'))
757
758 Default (rcbuild)
759
760 # source tarball
761
762 Precious (env['DISTTREE'])
763
764 #
765 # note the special "cleanfirst" source name. this triggers removal
766 # of the existing disttree
767 #
768
769 env.Distribute (env['DISTTREE'],
770                 [ 'SConstruct',
771                   'COPYING', 'PACKAGER_README', 'README',
772                   'ardour.rc.in',
773                   'ardour_system.rc',
774                   'tools/config.guess'
775                   ] +
776                 glob.glob ('DOCUMENTATION/AUTHORS*') +
777                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
778                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
779                 glob.glob ('DOCUMENTATION/BUILD*') +
780                 glob.glob ('DOCUMENTATION/FAQ*') +
781                 glob.glob ('DOCUMENTATION/README*')
782                 )
783                 
784 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
785 env.Alias ('srctar', srcdist)
786 #
787 # don't leave the distree around 
788 #
789 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
790 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
791
792 #
793 # the subdirs
794
795
796 for subdir in coredirs:
797     SConscript (subdir + '/SConscript')
798
799 for sublistdir in [subdirs, gtk_subdirs, surface_subdirs]:
800         for subdir in sublistdir:
801                 SConscript (subdir + '/SConscript')
802
803 # cleanup
804 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
805