committed build changes needed for leopard build
[ardour.git] / SConstruct
1 # -*- python -*-
2
3 #
4 # and there we have it, or do we?
5 #
6
7 import os
8 import os.path
9 import sys
10 import re
11 import shutil
12 import glob
13 import errno
14 import time
15 import platform
16 import string
17 import commands
18 from sets import Set
19 import SCons.Node.FS
20
21 SConsignFile()
22 EnsureSConsVersion(0, 96)
23
24 ardour_version = '2.5'
25
26 subst_dict = { }
27
28 #
29 # Command-line options
30 #
31
32 opts = Options('scache.conf')
33 opts.AddOptions(
34     ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
35     ('WINDOWS_KEY', 'Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key', 'Mod4'),
36     BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
37     BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
38     BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
39     BoolOption('OLDFONTS', 'Old school font sizes', 0),
40     BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
41     BoolOption('STL_DEBUG', 'Set to build with Standard Template Library Debugging', 0),
42     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
43     EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'leopard', 'none' ), ignorecase=2),
44     BoolOption('DMALLOC', 'Compile and link using the dmalloc library', 0),
45     BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic.  Might break compilation.  For pedants', 0),
46     BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 1),
47     BoolOption('FREESOUND', 'Include Freesound database lookup', 0),
48     BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
49     BoolOption('LIBLO', 'Compile with support for liblo library', 1),
50     BoolOption('NLS', 'Set to turn on i18n support', 1),
51     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
52     BoolOption('SURFACES', 'Build support for control surfaces', 1),
53     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),
54     BoolOption('UNIVERSAL', 'Compile as universal binary.  Requires that external libraries are already universal.', 0),
55     BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
56     BoolOption('VST', 'Compile with support for VST', 0),
57     BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 0),
58     BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
59     BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
60     BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
61     BoolOption('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1)
62     
63 )
64
65 #----------------------------------------------------------------------
66 # a handy helper that provides a way to merge compile/link information
67 # from multiple different "environments"
68 #----------------------------------------------------------------------
69 #
70 class LibraryInfo(Environment):
71     def __init__(self,*args,**kw):
72         Environment.__init__ (self,*args,**kw)
73     
74     def Merge (self,others):
75         for other in others:
76             self.Append (LIBS = other.get ('LIBS',[]))
77             self.Append (LIBPATH = other.get ('LIBPATH', []))
78             self.Append (CPPPATH = other.get('CPPPATH', []))
79             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
80             self.Append (CCFLAGS = other.get('CCFLAGS', []))
81         self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
82         self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
83         #doing LINKFLAGS breaks -framework
84         #doing LIBS break link order dependency
85     
86     def ENV_update(self, src_ENV):
87         for k in src_ENV.keys():
88             if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
89                                                   'LIB', 'INCLUDE' ]:
90                 self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
91             else:
92                 self['ENV'][k]=src_ENV[k]
93
94 env = LibraryInfo (options = opts,
95                    CPPPATH = [ '.' ],
96                    VERSION = ardour_version,
97                    TARBALL='ardour-' + ardour_version + '.tar.bz2',
98                    DISTFILES = [ ],
99                    DISTTREE  = '#ardour-' + ardour_version,
100                    DISTCHECKDIR = '#ardour-' + ardour_version + '/check'
101                    )
102
103 env.ENV_update(os.environ)
104
105 #----------------------------------------------------------------------
106 # Builders
107 #----------------------------------------------------------------------
108
109 # Handy subst-in-file builder
110 #
111
112 def do_subst_in_file(targetfile, sourcefile, dict):
113     """Replace all instances of the keys of dict with their values.
114     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
115     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
116     """
117     try:
118         f = open(sourcefile, 'rb')
119         contents = f.read()
120         f.close()
121     except:
122         raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
123     for (k,v) in dict.items():
124         contents = re.sub(k, v, contents)
125     try:
126         f = open(targetfile, 'wb')
127         f.write(contents)
128         f.close()
129     except:
130         raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
131     return 0 # success
132
133 def subst_in_file(target, source, env):
134     if not env.has_key('SUBST_DICT'):
135         raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
136     d = dict(env['SUBST_DICT']) # copy it
137     for (k,v) in d.items():
138         if callable(v):
139             d[k] = env.subst(v())
140         elif SCons.Util.is_String(v):
141             d[k]=env.subst(v)
142         else:
143             raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
144     for (t,s) in zip(target, source):
145         return do_subst_in_file(str(t), str(s), d)
146
147 def subst_in_file_string(target, source, env):
148     """This is what gets printed on the console."""
149     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
150                       for (t,s) in zip(target, source)])
151
152 def subst_emitter(target, source, env):
153     """Add dependency from substituted SUBST_DICT to target.
154     Returns original target, source tuple unchanged.
155     """
156     d = env['SUBST_DICT'].copy() # copy it
157     for (k,v) in d.items():
158         if callable(v):
159             d[k] = env.subst(v())
160         elif SCons.Util.is_String(v):
161             d[k]=env.subst(v)
162     Depends(target, SCons.Node.Python.Value(d))
163     # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
164     return target, source
165
166 subst_action = Action (subst_in_file, subst_in_file_string)
167 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
168
169 #
170 # internationalization
171 #
172
173 # po_builder: builder function to copy po files to the parent directory while updating them
174 #
175 # first source:  .po file
176 # second source: .pot file
177 #
178
179 def po_builder(target,source,env):
180     os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
181     args = [ 'msgmerge',
182              '--update',
183              str(target[0]),
184              str(source[1])
185              ]
186     print 'Updating ' + str(target[0])
187     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
188
189 po_bld = Builder (action = po_builder)
190 env.Append(BUILDERS = {'PoBuild' : po_bld})
191
192 # mo_builder: builder function for (binary) message catalogs (.mo)
193 #
194 # first source:  .po file
195 #
196
197 def mo_builder(target,source,env):
198     args = [ 'msgfmt',
199              '-c',
200              '-o',
201              target[0].get_path(),
202              source[0].get_path()
203              ]
204     return os.spawnvp (os.P_WAIT, 'msgfmt', args)
205
206 mo_bld = Builder (action = mo_builder)
207 env.Append(BUILDERS = {'MoBuild' : mo_bld})
208
209 # pot_builder: builder function for message templates (.pot)
210 #
211 # source: list of C/C++ etc. files to extract messages from
212 #
213
214 def pot_builder(target,source,env):
215     args = [ 'xgettext',
216              '--keyword=_',
217              '--keyword=N_',
218              '--from-code=UTF-8',
219              '-o', target[0].get_path(),
220              "--default-domain=" + env['PACKAGE'],
221              '--copyright-holder="Paul Davis"' ]
222     args += [ src.get_path() for src in source ]
223     
224     return os.spawnvp (os.P_WAIT, 'xgettext', args)
225
226 pot_bld = Builder (action = pot_builder)
227 env.Append(BUILDERS = {'PotBuild' : pot_bld})
228
229 #
230 # utility function, not a builder
231 #
232
233 def i18n (buildenv, sources, installenv):
234     domain = buildenv['PACKAGE']
235     potfile = buildenv['POTFILE']
236     
237     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
238     
239     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
240     languages = [ po.replace ('.po', '') for po in p_oze ]
241     
242     for po_file in p_oze:
243         buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
244         mo_file = po_file.replace (".po", ".mo")
245         installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
246         installenv.Alias ('msgupdate', buildenv.MoBuild (mo_file, po_file))
247     
248     for lang in languages:
249         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
250         moname = domain + '.mo'
251         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
252
253
254 def fetch_svn_revision (path):
255     cmd = "LANG= "
256     cmd += "svn info "
257     cmd += path
258     cmd += " | awk '/^Revision:/ { print $2}'"
259     return commands.getoutput (cmd)
260
261 def create_stored_revision (target = None, source = None, env = None):
262     if os.path.exists('.svn'):    
263         rev = fetch_svn_revision ('.');
264         try:
265             text  = "#ifndef __ardour_svn_revision_h__\n"
266             text += "#define __ardour_svn_revision_h__\n"
267             text += "static const char* ardour_svn_revision = \"" + rev + "\";\n";
268             text += "#endif\n"
269             print '============> writing svn revision info to svn_revision.h\n'
270             o = file ('svn_revision.h', 'w')
271             o.write (text)
272             o.close ()
273         except IOError:
274             print "Could not open svn_revision.h for writing\n"
275             sys.exit (-1)
276     else:
277         print "You cannot use \"scons revision\" on without using a checked out"
278         print "copy of the Ardour source code repository"
279         sys.exit (-1)
280
281 #
282 # A generic builder for version.cc files
283 #
284 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
285 # note: assumes one source files, the header that declares the version variables
286 #
287
288 def version_builder (target, source, env):
289
290     text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
291     text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
292     text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
293     
294     try:
295         o = file (target[0].get_path(), 'w')
296         o.write (text)
297         o.close ()
298     except IOError:
299         print "Could not open", target[0].get_path(), " for writing\n"
300         sys.exit (-1)
301
302     text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
303     text += "#define __" + env['DOMAIN'] + "_version_h__\n"
304     text += "extern const char* " + env['DOMAIN'] + "_revision;\n"
305     text += "extern int " + env['DOMAIN'] + "_major_version;\n"
306     text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
307     text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
308     text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
309     
310     try:
311         o = file (target[1].get_path(), 'w')
312         o.write (text)
313         o.close ()
314     except IOError:
315         print "Could not open", target[1].get_path(), " for writing\n"
316         sys.exit (-1)
317         
318     return None
319
320 version_bld = Builder (action = version_builder)
321 env.Append (BUILDERS = {'VersionBuild' : version_bld})
322
323 #
324 # a builder that makes a hard link from the 'source' executable to a name with
325 # a "build ID" based on the most recent CVS activity that might be reasonably
326 # related to version activity. this relies on the idea that the SConscript
327 # file that builds the executable is updated with new version info and committed
328 # to the source code repository whenever things change.
329 #
330
331 def versioned_builder(target,source,env):
332     w, r = os.popen2( "LANG= svn info | awk '/^Revision:/ { print $2}'")
333     
334     last_revision = r.readline().strip()
335     w.close()
336     r.close()
337     if last_revision == "":
338         print "No SVN info found - versioned executable cannot be built"
339         return -1
340     
341     print "The current build ID is " + last_revision
342     
343     tagged_executable = source[0].get_path() + '-' + last_revision
344     
345     if os.path.exists (tagged_executable):
346         print "Replacing existing executable with the same build tag."
347         os.unlink (tagged_executable)
348     
349     return os.link (source[0].get_path(), tagged_executable)
350
351 verbuild = Builder (action = versioned_builder)
352 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
353
354 #
355 # source tar file builder
356 #
357
358 def distcopy (target, source, env):
359     treedir = str (target[0])
360     
361     try:
362         os.mkdir (treedir)
363     except OSError, (errnum, strerror):
364         if errnum != errno.EEXIST:
365             print 'mkdir ', treedir, ':', strerror
366     
367     cmd = 'tar cf - '
368     #
369     # we don't know what characters might be in the file names
370     # so quote them all before passing them to the shell
371     #
372     all_files = ([ str(s) for s in source ])
373     cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
374     cmd += ' | (cd ' + treedir + ' && tar xf -)'
375     p = os.popen (cmd)
376     return p.close ()
377
378 def tarballer (target, source, env):
379     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'" + " --exclude .svn --exclude '.svn/*'"
380     print 'running ', cmd, ' ... '
381     p = os.popen (cmd)
382     return p.close ()
383
384 dist_bld = Builder (action = distcopy,
385                     target_factory = SCons.Node.FS.default_fs.Entry,
386                     source_factory = SCons.Node.FS.default_fs.Entry,
387                     multi = 1)
388
389 tarball_bld = Builder (action = tarballer,
390                        target_factory = SCons.Node.FS.default_fs.Entry,
391                        source_factory = SCons.Node.FS.default_fs.Entry)
392
393 env.Append (BUILDERS = {'Distribute' : dist_bld})
394 env.Append (BUILDERS = {'Tarball' : tarball_bld})
395
396 #
397 # Make sure they know what they are doing
398 #
399
400 if env['VST']:
401     if os.path.isfile('.personal_use_only'):
402         print "Enabling VST support. Note that distributing a VST-enabled ardour\nis a violation of several different licences.\nBuild with VST=false if you intend to distribute ardour to others."
403     else:
404         sys.stdout.write ("Are you building Ardour for personal use (rather than distribution to others)? [no]: ")
405         answer = sys.stdin.readline ()
406         answer = answer.rstrip().strip()
407         if answer == "yes" or answer == "y":
408             fh = open('.personal_use_only', 'w')
409             fh.close()
410             print "OK, VST support will be enabled"
411         else:
412             print 'You cannot build Ardour with VST support for distribution to others.\nIt is a violation of several different licenses. Build with VST=false.'
413             sys.exit (-1);
414 else:
415     if os.path.isfile('.personal_use_only'):
416         os.remove('.personal_use_only')
417
418 ####################
419 # push environment
420 ####################
421
422 def pushEnvironment(context):
423     if os.environ.has_key('PATH'):
424         context.Append(PATH = os.environ['PATH'])
425         
426     if os.environ.has_key('PKG_CONFIG_PATH'):
427         context.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
428             
429     if os.environ.has_key('CC'):
430         context['CC'] = os.environ['CC']
431                 
432     if os.environ.has_key('CXX'):
433         context['CXX'] = os.environ['CXX']
434
435     if os.environ.has_key('DISTCC_HOSTS'):
436         context['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
437         context['ENV']['HOME'] = os.environ['HOME']
438
439 pushEnvironment (env)
440
441 #######################
442 # Dependency Checking #
443 #######################
444
445 deps = \
446 {
447         'glib-2.0'             : '2.10.1',
448         'gthread-2.0'          : '2.10.1',
449         'gtk+-2.0'             : '2.8.1',
450         'libxml-2.0'           : '2.6.0',
451         'samplerate'           : '0.1.0',
452         'raptor'               : '1.4.2',
453         'lrdf'                 : '0.4.0',
454         'jack'                 : '0.109.0',
455         'libgnomecanvas-2.0'   : '2.0',
456         'aubio'                : '0.3.2'
457 }
458
459 def DependenciesRequiredMessage():
460         print 'You do not have the necessary dependencies required to build ardour'
461         print 'Please consult http://ardour.org/building for more information'
462
463 def CheckPKGConfig(context, version):
464     context.Message( 'Checking for pkg-config version >= %s... ' %version )
465     ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
466     context.Result( ret )
467     return ret
468
469 def CheckPKGVersion(context, name, version):
470     context.Message( 'Checking for %s... ' % name )
471     ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
472     context.Result( ret )
473     return ret
474
475 def CheckPKGExists(context, name):
476     context.Message ('Checking for %s...' % name)
477     ret = context.TryAction('pkg-config --exists %s' % name)[0]
478     context.Result (ret)
479     return ret
480
481 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
482                                        'CheckPKGVersion' : CheckPKGVersion })
483
484 # I think a more recent version is needed on win32
485 min_pkg_config_version = '0.8.0'
486
487 if not conf.CheckPKGConfig(min_pkg_config_version):
488      print 'pkg-config >= %s not found.' % min_pkg_config_version
489      Exit(1)
490
491 for pkg, version in deps.iteritems():
492         if not conf.CheckPKGVersion( pkg, version ):
493                 print '%s >= %s not found.' %(pkg, version)
494                 DependenciesRequiredMessage()
495                 Exit(1)
496
497 env = conf.Finish()
498
499 # ----------------------------------------------------------------------
500 # Construction environment setup
501 # ----------------------------------------------------------------------
502
503 libraries = { }
504
505 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
506
507 #libraries['sndfile'] = LibraryInfo()
508 #libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
509
510 libraries['lrdf'] = LibraryInfo()
511 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
512
513 libraries['raptor'] = LibraryInfo()
514 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
515
516 libraries['samplerate'] = LibraryInfo()
517 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
518
519 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
520
521 if conf.CheckPKGExists ('fftw3f'):
522     libraries['fftw3f'] = LibraryInfo()
523     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
524
525 if conf.CheckPKGExists ('fftw3'):
526     libraries['fftw3'] = LibraryInfo()
527     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
528
529 if conf.CheckPKGExists ('aubio'):
530     libraries['aubio'] = LibraryInfo()
531     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
532     env['AUBIO'] = 1
533 else:
534     env['AUBIO'] = 0
535
536 env = conf.Finish ()
537
538 if env['FFT_ANALYSIS']:
539         #
540         # Check for fftw3 header as well as the library
541         #
542
543         conf = Configure(libraries['fftw3'])
544
545         if conf.CheckHeader ('fftw3.h') == False:
546             print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
547             sys.exit (1)            
548         conf.Finish()
549
550 if env['FREESOUND']:
551         #
552         # Check for curl header as well as the library
553         #
554
555         libraries['curl'] = LibraryInfo()
556
557         conf = Configure(libraries['curl'])
558
559         if conf.CheckHeader ('curl/curl.h') == False:
560                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
561                 sys.exit (1)            
562         else:
563                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
564         conf.Finish()
565 else:
566         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
567
568 if env['LV2']:
569         conf = env.Configure(custom_tests = { 'CheckPKGExists' : CheckPKGExists })
570         
571         if conf.CheckPKGExists ('\"slv2 >= 0.6.0\"'):
572                 libraries['slv2'] = LibraryInfo()
573                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
574                 env.Append (CCFLAGS="-DHAVE_LV2")
575         else:
576                 print 'Building Ardour with LV2 support requires SLV2 >= 0.6.0'
577                 print 'WARNING: SLV2 not found, or too old.  Ardour will be built without LV2 support.'
578                 print 'Until the 2.4 release, Ardour requires SLV2 out of SVN.'
579                 print 'Testing would be very much appreciated!  svn co http://svn.drobilla.net/lad/slv2'
580                 env['LV2'] = 0
581         conf.Finish()
582 else:
583         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
584
585 libraries['jack'] = LibraryInfo()
586 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
587
588 libraries['xml'] = LibraryInfo()
589 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
590
591 libraries['xslt'] = LibraryInfo()
592 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
593
594 libraries['glib2'] = LibraryInfo()
595 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
596 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
597 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
598 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
599
600 libraries['freetype2'] = LibraryInfo()
601 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
602
603 libraries['gtk2'] = LibraryInfo()
604 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
605
606 libraries['pango'] = LibraryInfo()
607 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
608
609 libraries['libgnomecanvas2'] = LibraryInfo()
610 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
611
612 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
613
614 # The Ardour Control Protocol Library
615
616 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
617                                       CPPPATH='#libs/surfaces/control_protocol')
618
619 # The Ardour backend/engine
620
621 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
622 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
623 libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
624 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
625
626
627 # SCons should really do this for us
628
629 conf = env.Configure ()
630
631 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
632 if have_cxx[0] != 1:
633     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
634     sys.exit (1)
635 else:
636     print "Congratulations, you have a functioning C++ compiler."
637
638 env = conf.Finish()
639
640
641 #
642 # Compiler flags and other system-dependent stuff
643 #
644
645 opt_flags = []
646 if env['GPROFILE'] == 1:
647     debug_flags = [ '-g', '-pg' ]
648 else:
649     debug_flags = [ '-g' ]
650
651 # guess at the platform, used to define compiler flags
652
653 config_guess = os.popen("tools/config.guess").read()[:-1]
654
655 config_cpu = 0
656 config_arch = 1
657 config_kernel = 2
658 config_os = 3
659 config = config_guess.split ("-")
660
661 print "system triple: " + config_guess
662
663 # Autodetect
664 if env['DIST_TARGET'] == 'auto':
665     if config[config_arch] == 'apple':
666         # The [.] matches to the dot after the major version, "." would match any character
667         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
668             env['DIST_TARGET'] = 'panther'
669         if re.search ("darwin8[.]", config[config_kernel]) != None:
670             env['DIST_TARGET'] = 'tiger'
671         else:
672             env['DIST_TARGET'] = 'leopard'
673     else:
674         if re.search ("x86_64", config[config_cpu]) != None:
675             env['DIST_TARGET'] = 'x86_64'
676         elif re.search("i[0-5]86", config[config_cpu]) != None:
677             env['DIST_TARGET'] = 'i386'
678         elif re.search("powerpc", config[config_cpu]) != None:
679             env['DIST_TARGET'] = 'powerpc'
680         else:
681             env['DIST_TARGET'] = 'i686'
682     print "\n*******************************"
683     print "detected DIST_TARGET = " + env['DIST_TARGET']
684     print "*******************************\n"
685
686
687 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
688     #
689     # Apple/PowerPC optimization options
690     #
691     # -mcpu=7450 does not reliably work with gcc 3.*
692     #
693     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
694         if config[config_arch] == 'apple':
695             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
696             # to support g3s but still have some optimization for above
697             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
698         else:
699             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
700     else:
701         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
702     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
703     opt_flags.extend (["-Os"])
704
705 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':
706     
707     build_host_supports_sse = 0
708     
709     debug_flags.append ("-DARCH_X86")
710     opt_flags.append ("-DARCH_X86")
711     
712     if config[config_kernel] == 'linux' :
713         
714         if env['DIST_TARGET'] != 'i386':
715             
716             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
717             x86_flags = flag_line.split (": ")[1:][0].split ()
718             
719             if "mmx" in x86_flags:
720                 opt_flags.append ("-mmmx")
721             if "sse" in x86_flags:
722                 build_host_supports_sse = 1
723             if "3dnow" in x86_flags:
724                 opt_flags.append ("-m3dnow")
725             
726             if config[config_cpu] == "i586":
727                 opt_flags.append ("-march=i586")
728             elif config[config_cpu] == "i686":
729                 opt_flags.append ("-march=i686")
730     
731     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
732         opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
733         debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
734 # end of processor-specific section
735
736 # optimization section
737 if env['FPU_OPTIMIZATION']:
738     if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
739         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
740         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
741         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
742     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
743         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
744         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
745         if env['DIST_TARGET'] == 'x86_64':
746             opt_flags.append ("-DUSE_X86_64_ASM")
747             debug_flags.append ("-DUSE_X86_64_ASM")
748         if build_host_supports_sse != 1:
749             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)"
750 # end optimization section
751
752 # handle x86/x86_64 libdir properly
753
754 if env['DIST_TARGET'] == 'x86_64':
755     env['LIBDIR']='lib64'
756 else:
757     env['LIBDIR']='lib'
758
759 #
760 # a single way to test if we're on OS X
761 #
762
763 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
764     env['IS_OSX'] = 1
765     # force tiger or later, to avoid issues on PPC which defaults
766     # back to 10.1 if we don't tell it otherwise.
767     env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
768
769     if env['DIST_TARGET'] == 'leopard':
770         # need this to really build against the 10.4 SDK when building on leopard
771         # ideally this would be configurable, but lets just do that later when we need it
772         env.Append(CCFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
773         env.Append(LINKFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
774
775 else:
776     env['IS_OSX'] = 0
777
778 #
779 # save off guessed arch element in an env
780 #
781 env.Append(CONFIG_ARCH=config[config_arch])
782
783
784 #
785 # ARCH="..." overrides all
786 #
787
788 if env['ARCH'] != '':
789     opt_flags = env['ARCH'].split()
790
791 #
792 # prepend boiler plate optimization flags
793 #
794
795 opt_flags[:0] = [
796     "-O3",
797     "-fomit-frame-pointer",
798     "-ffast-math",
799     "-fstrength-reduce",
800     "-pipe"
801     ]
802
803 if env['DEBUG'] == 1:
804     env.Append(CCFLAGS=" ".join (debug_flags))
805     env.Append(LINKFLAGS=" ".join (debug_flags))
806 else:
807     env.Append(CCFLAGS=" ".join (opt_flags))
808     env.Append(LINKFLAGS=" ".join (opt_flags))
809
810 if env['STL_DEBUG'] == 1:
811     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
812
813 if env['UNIVERSAL'] == 1:
814     env.Append(CCFLAGS="-arch i386 -arch ppc")
815     env.Append(LINKFLAGS="-arch i386 -arch ppc")
816
817
818 #
819 # warnings flags
820 #
821
822 env.Append(CCFLAGS="-Wall")
823 env.Append(CXXFLAGS="-Woverloaded-virtual")
824
825 if env['EXTRA_WARN']:
826     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
827     env.Append(CXXFLAGS="-ansi")
828 #    env.Append(CFLAGS="-iso")
829
830 if env['LIBLO']:
831     env.Append(CCFLAGS="-DHAVE_LIBLO")
832
833
834 #
835 # fix scons nitpickiness on APPLE
836 #
837
838
839 def prep_libcheck(topenv, libinfo):
840     if topenv['IS_OSX']:
841         #
842         # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default.
843         #            All libraries needed should be built against this location
844         if topenv['GTKOSX']:
845                 gtkroot = os.path.expanduser ("~");
846                 libinfo.Append(CPPPATH="$GTKROOT/include", LIBPATH="$GTKROOT/lib")
847                 libinfo.Append(CXXFLAGS="-I$GTKROOT/include", LINKFLAGS="-L$GTKROOT/lib")
848         libinfo.Append(CPPPATH="/opt/local/include", LIBPATH="/opt/local/lib")
849         libinfo.Append(CXXFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
850
851 prep_libcheck(env, env)
852
853
854 #
855 # these are part of the Ardour source tree because they are C++
856
857
858 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
859                                  LIBPATH='#libs/vamp-sdk',
860                                  CPPPATH='#libs/vamp-sdk')
861 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
862                                  LIBPATH='#libs/vamp-sdk',
863                                  CPPPATH='#libs/vamp-sdk')
864
865 env['RUBBERBAND'] = False
866
867 conf = Configure (env)
868
869 if conf.CheckHeader ('fftw3.h'):
870     env['RUBBERBAND'] = True
871     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
872                                            LIBPATH='#libs/rubberband',
873                                            CPPPATH='#libs/rubberband',
874                                            CCFLAGS='-DUSE_RUBBERBAND')
875 else:
876     print ""
877     print "-------------------------------------------------------------------------"
878     print "You do not have the FFTW single-precision development package installed."
879     print "This prevents Ardour from using the Rubberband library for timestretching"
880     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
881     print "pitchshifting will not be available."
882     print "-------------------------------------------------------------------------"
883     print ""
884
885 conf.Finish()
886
887 #
888 # Check for libusb
889
890 libraries['usb'] = LibraryInfo ()
891 prep_libcheck(env, libraries['usb'])
892
893 conf = Configure (libraries['usb'])
894 if conf.CheckLib ('usb', 'usb_interrupt_write'):
895     have_libusb = True
896 else:
897     have_libusb = False
898
899 # check for linux/input.h while we're at it for powermate
900 if conf.CheckHeader('linux/input.h'):
901     have_linux_input = True
902 else:
903     have_linux_input = False
904
905 libraries['usb'] = conf.Finish ()
906
907 #
908 # Check for FLAC
909
910 libraries['flac'] = LibraryInfo ()
911 prep_libcheck(env, libraries['flac'])
912 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
913
914 #
915 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
916 #                since the version of libsndfile we have internally does not support
917 #                the new API that libFLAC has adopted
918 #
919
920 conf = Configure (libraries['flac'])
921 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
922     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
923     use_flac = True
924 else:
925     use_flac = False
926     
927 libraries['flac'] = conf.Finish ()
928
929 # or if that fails...
930 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
931
932 # boost (we don't link against boost, just use some header files)
933
934 libraries['boost'] = LibraryInfo ()
935 prep_libcheck(env, libraries['boost'])
936 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
937 conf = Configure (libraries['boost'])
938 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
939         print "Boost header files do not appear to be installed. You also might be running a buggy version of scons. Try scons 0.97 if you can."
940         sys.exit (1)
941     
942 libraries['boost'] = conf.Finish ()
943
944 #
945 # Check for liblo
946
947 if env['LIBLO']:
948     libraries['lo'] = LibraryInfo ()
949     prep_libcheck(env, libraries['lo'])
950
951     conf = Configure (libraries['lo'])
952     if conf.CheckLib ('lo', 'lo_server_new') == False:
953         print "liblo does not appear to be installed."
954         sys.exit (1)
955     
956     libraries['lo'] = conf.Finish ()
957
958 #
959 # Check for dmalloc
960
961 libraries['dmalloc'] = LibraryInfo ()
962 prep_libcheck(env, libraries['dmalloc'])
963
964 #
965 # look for the threaded version
966 #
967
968 conf = Configure (libraries['dmalloc'])
969 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
970     have_libdmalloc = True
971 else:
972     have_libdmalloc = False
973
974 libraries['dmalloc'] = conf.Finish ()
975
976 #
977 # ensure FREEDESKTOP target is doable..
978 #
979
980 conf = env.Configure ()
981 if env['FREEDESKTOP']:
982         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
983         if have_update_mime_database[0] != 1:
984                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
985                 env['FREEDESKTOP'] = 0
986         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
987         if have_gtk_update_icon_cache[0] != 1:
988                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
989                 env['FREEDESKTOP'] = 0
990         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
991         if have_update_desktop_database[0] != 1:
992                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
993                 env['FREEDESKTOP'] = 0
994 env = conf.Finish()
995
996 #
997 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
998 #
999
1000 conf = Configure(env)
1001
1002 if conf.CheckCHeader('alsa/asoundlib.h'):
1003     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
1004     env['SYSMIDI'] = 'ALSA Sequencer'
1005     subst_dict['%MIDITAG%'] = "seq"
1006     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1007 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1008     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1009     if env['GTKOSX']:
1010         # We need Carbon as well as the rest
1011         libraries['sysmidi'] = LibraryInfo (
1012                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1013     else:
1014         libraries['sysmidi'] = LibraryInfo (
1015                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1016     env['SYSMIDI'] = 'CoreMIDI'
1017     subst_dict['%MIDITAG%'] = "ardour"
1018     subst_dict['%MIDITYPE%'] = "coremidi"
1019 else:
1020     print "It appears you don't have the required MIDI libraries installed. For Linux this means you are missing the development package for ALSA libraries."
1021     sys.exit (1)
1022
1023 env = conf.Finish()
1024
1025 if env['SYSLIBS']:
1026
1027     syslibdeps = \
1028     {
1029         'sigc++-2.0'           : '2.0',
1030         'gtkmm-2.4'            : '2.8',
1031         'libgnomecanvasmm-2.6' : '2.12.0'
1032     }
1033
1034     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1035                     'CheckPKGVersion' : CheckPKGVersion })
1036
1037     for pkg, version in syslibdeps.iteritems():
1038         if not conf.CheckPKGVersion( pkg, version ):
1039             print '%s >= %s not found.' %(pkg, version)
1040             DependenciesRequiredMessage()
1041             Exit(1)
1042     
1043     env = conf.Finish()
1044     
1045     libraries['sigc2'] = LibraryInfo()
1046     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1047     libraries['glibmm2'] = LibraryInfo()
1048     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1049     libraries['cairomm'] = LibraryInfo()
1050     libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1051     libraries['gdkmm2'] = LibraryInfo()
1052     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1053     libraries['gtkmm2'] = LibraryInfo()
1054     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1055     libraries['atkmm'] = LibraryInfo()
1056     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1057     libraries['pangomm'] = LibraryInfo()
1058     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1059     libraries['libgnomecanvasmm'] = LibraryInfo()
1060     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1061
1062 #
1063 # cannot use system one for the time being
1064 #
1065     
1066     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1067                                     LIBPATH='#libs/libsndfile',
1068                                     CPPPATH=['#libs/libsndfile/src'])
1069
1070 #    libraries['libglademm'] = LibraryInfo()
1071 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1072
1073 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1074     libraries['soundtouch'] = LibraryInfo()
1075     #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1076     # Comment the previous line and uncomment this for Debian:
1077     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1078
1079     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1080                                             LIBPATH='#libs/appleutility',
1081                                             CPPPATH='#libs/appleutility')
1082     
1083     coredirs = [
1084         'templates',
1085         'manual'
1086     ]
1087     
1088     subdirs = [
1089         'libs/libsndfile',
1090         'libs/pbd',
1091         'libs/midi++2',
1092         'libs/ardour',
1093         'libs/vamp-sdk',
1094         'libs/vamp-plugins/',
1095     # these are unconditionally included but have
1096     # tests internally to avoid compilation etc
1097     # if VST is not set
1098         'libs/fst',
1099         'vst',
1100     # this is unconditionally included but has
1101     # tests internally to avoid compilation etc
1102     # if COREAUDIO is not set
1103         'libs/appleutility'
1104         ]
1105     
1106     gtk_subdirs = [
1107 #        'libs/flowcanvas',
1108         'libs/gtkmm2ext',
1109         'gtk2_ardour',
1110         'libs/clearlooks'
1111         ]
1112
1113 else:
1114     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
1115                                     LIBPATH='#libs/sigc++2',
1116                                     CPPPATH='#libs/sigc++2')
1117     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
1118                                     LIBPATH='#libs/glibmm2',
1119                                     CPPPATH='#libs/glibmm2')
1120     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
1121                                     LIBPATH='#libs/gtkmm2/pango',
1122                                     CPPPATH='#libs/gtkmm2/pango')
1123     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
1124                                      LIBPATH='#libs/gtkmm2/atk',
1125                                      CPPPATH='#libs/gtkmm2/atk')
1126     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
1127                                       LIBPATH='#libs/gtkmm2/gdk',
1128                                       CPPPATH='#libs/gtkmm2/gdk')
1129     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
1130                                      LIBPATH="#libs/gtkmm2/gtk",
1131                                      CPPPATH='#libs/gtkmm2/gtk/')
1132     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
1133                                                 LIBPATH='#libs/libgnomecanvasmm',
1134                                                 CPPPATH='#libs/libgnomecanvasmm')
1135     
1136     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
1137                                           LIBPATH='#libs/soundtouch',
1138                                           CPPPATH=['#libs', '#libs/soundtouch'])
1139     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1140                                     LIBPATH='#libs/libsndfile',
1141                                     CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
1142 #    libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
1143 #                                          LIBPATH='#libs/libglademm',
1144 #                                          CPPPATH='#libs/libglademm')
1145     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1146                                             LIBPATH='#libs/appleutility',
1147                                             CPPPATH='#libs/appleutility')
1148
1149     coredirs = [
1150         'templates',
1151         'manual'
1152     ]
1153     
1154     subdirs = [
1155         'libs/sigc++2',
1156         'libs/libsndfile',
1157         'libs/pbd',
1158         'libs/midi++2',
1159         'libs/ardour',
1160         'libs/vamp-sdk',
1161         'libs/vamp-plugins/',
1162     # these are unconditionally included but have
1163     # tests internally to avoid compilation etc
1164     # if VST is not set
1165         'libs/fst',
1166         'vst',
1167     # this is unconditionally included but has
1168     # tests internally to avoid compilation etc
1169     # if COREAUDIO is not set
1170         'libs/appleutility'
1171         ]
1172     
1173     gtk_subdirs = [
1174         'libs/glibmm2',
1175         'libs/gtkmm2/pango',
1176         'libs/gtkmm2/atk',
1177         'libs/gtkmm2/gdk',
1178         'libs/gtkmm2/gtk',
1179         'libs/libgnomecanvasmm',
1180         'libs/gtkmm2ext',
1181         'gtk2_ardour',
1182         'libs/clearlooks'
1183         ]
1184
1185 #
1186 # * always build the LGPL control protocol lib, since we link against it from libardour
1187 # * ditto for generic MIDI
1188 # * tranzport checks whether it should build internally, but we need here so that
1189 #   its included in the tarball
1190 #
1191
1192 surface_subdirs = [ 'libs/surfaces/control_protocol',
1193                     'libs/surfaces/generic_midi',
1194                     'libs/surfaces/tranzport',
1195                     'libs/surfaces/mackie',
1196                     'libs/surfaces/powermate'
1197                     ]
1198
1199 if env['SURFACES']:
1200     if have_libusb:
1201         env['TRANZPORT'] = 1
1202     else:
1203         env['TRANZPORT'] = 0
1204         print 'Disabled building Tranzport code because libusb could not be found'
1205
1206     if have_linux_input:
1207         env['POWERMATE'] = 1
1208     else:
1209         env['POWERMATE'] = 0
1210         print 'Disabled building Powermate code because linux/input.h could not be found'
1211
1212     if os.access ('libs/surfaces/sony9pin', os.F_OK):
1213         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1214 else:
1215     env['POWERMATE'] = 0
1216     env['TRANZPORT'] = 0
1217
1218 #
1219 # timestretch libraries
1220 #
1221
1222 timefx_subdirs = ['libs/soundtouch']
1223 if env['RUBBERBAND']:
1224     timefx_subdirs += ['libs/rubberband']
1225
1226 opts.Save('scache.conf', env)
1227 Help(opts.GenerateHelpText(env))
1228
1229 final_prefix = '$PREFIX'
1230
1231 if env['DESTDIR'] :
1232     install_prefix = '$DESTDIR/$PREFIX'
1233 else:
1234     install_prefix = env['PREFIX']
1235
1236 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1237 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1238 subst_dict['%PREFIX%'] = final_prefix;
1239
1240 if env['PREFIX'] == '/usr':
1241     final_config_prefix = '/etc'
1242 else:
1243     final_config_prefix = env['PREFIX'] + '/etc'
1244
1245 config_prefix = '$DESTDIR' + final_config_prefix
1246
1247 #
1248 # everybody needs this
1249 #
1250
1251 env.Merge ([ libraries['core'] ])
1252
1253
1254 #
1255 # i18n support
1256 #
1257
1258 conf = Configure (env)
1259 if env['NLS']:
1260     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1261     print 'Checking for internationalization support ...'
1262     have_gettext = conf.TryAction(Action('xgettext --version'))
1263     if have_gettext[0] != 1:
1264         nls_error += ' No xgettext command.'
1265         env['NLS'] = 0
1266     else:
1267         print "Found xgettext"
1268     
1269     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1270     if have_msgmerge[0] != 1:
1271         nls_error += ' No msgmerge command.'
1272         env['NLS'] = 0
1273     else:
1274         print "Found msgmerge"
1275     
1276     if not conf.CheckCHeader('libintl.h'):
1277         nls_error += ' No libintl.h.'
1278         env['NLS'] = 0
1279         
1280     if env['NLS'] == 0:
1281         print nls_error
1282     else:
1283         print "International version will be built."
1284 env = conf.Finish()
1285
1286 if env['NLS'] == 1:
1287     env.Append(CCFLAGS="-DENABLE_NLS")
1288
1289 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict use_flac')
1290
1291 #
1292 # the configuration file may be system dependent
1293 #
1294
1295 conf = env.Configure ()
1296
1297 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1298     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1299     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1300 else:
1301     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1302     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1303
1304 # posix_memalign available
1305 if not conf.CheckFunc('posix_memalign'):
1306     print 'Did not find posix_memalign(), using malloc'
1307     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1308
1309
1310 env = conf.Finish()
1311
1312 # generate the per-user and system rc files from the same source
1313
1314 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1315
1316 # add to the substitution dictionary
1317
1318 subst_dict['%VERSION%'] = ardour_version[0:3]
1319 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1320 subst_dict['%REVISION_STRING%'] = ''
1321 if os.path.exists('.svn'):
1322     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1323
1324 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1325
1326 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1327 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1328                              [ Delete ('$PREFIX/etc/ardour2'),
1329                                Delete ('$PREFIX/lib/ardour2'),
1330                                Delete ('$PREFIX/bin/ardour2'),
1331                                Delete ('$PREFIX/share/ardour2')])
1332
1333 env.Alias('revision', the_revision)
1334 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
1335 env.Alias('uninstall', remove_ardour)
1336
1337 Default (sysrcbuild)
1338
1339 # source tarball
1340
1341 Precious (env['DISTTREE'])
1342
1343 env.Distribute (env['DISTTREE'],
1344                [ 'SConstruct', 'svn_revision.h',
1345                   'COPYING', 'PACKAGER_README', 'README',
1346                   'ardour.rc.in',
1347                   'tools/config.guess',
1348                   'icons/icon/ardour_icon_mac_mask.png',
1349                   'icons/icon/ardour_icon_mac.png',
1350                   'icons/icon/ardour_icon_tango_16px_blue.png',
1351                   'icons/icon/ardour_icon_tango_16px_red.png',
1352                   'icons/icon/ardour_icon_tango_22px_blue.png',
1353                   'icons/icon/ardour_icon_tango_22px_red.png',
1354                   'icons/icon/ardour_icon_tango_32px_blue.png',
1355                   'icons/icon/ardour_icon_tango_32px_red.png',
1356                   'icons/icon/ardour_icon_tango_48px_blue.png',
1357                   'icons/icon/ardour_icon_tango_48px_red.png'
1358                   ] +
1359                 glob.glob ('DOCUMENTATION/AUTHORS*') +
1360                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
1361                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
1362                 glob.glob ('DOCUMENTATION/BUILD*') +
1363                 glob.glob ('DOCUMENTATION/FAQ*') +
1364                 glob.glob ('DOCUMENTATION/README*')
1365                 )
1366
1367 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1368 env.Alias ('srctar', srcdist)
1369
1370 #
1371 # don't leave the distree around
1372 #
1373
1374 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1375 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1376
1377 #
1378 # the subdirs
1379 #
1380
1381 for subdir in coredirs:
1382     SConscript (subdir + '/SConscript')
1383
1384 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1385     for subdir in sublistdir:
1386         SConscript (subdir + '/SConscript')
1387
1388 # cleanup
1389 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1390