add note onset detection to the ferret, c/o the aubio-based Onset VAMP plugin (REQUIR...
[ardour.git] / SConstruct
1 # -*- python -*-
2
3 #
4 # and there we have it, or do we?
5 #
6
7 import os
8 import sys
9 import re
10 import shutil
11 import glob
12 import errno
13 import time
14 import platform
15 import string
16 import commands
17 from sets import Set
18 import SCons.Node.FS
19
20 SConsignFile()
21 EnsureSConsVersion(0, 96)
22
23 ardour_version = '2.4.1'
24
25 subst_dict = { }
26
27 #
28 # Command-line options
29 #
30
31 opts = Options('scache.conf')
32 opts.AddOptions(
33     ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
34     ('WINDOWS_KEY', 'Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key', 'Mod4'),
35     BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
36     BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
37     BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
38     BoolOption('NATIVE_OSX_KEYS', 'Build key bindings file that matches OS X conventions', 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.101.1',
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
533 env = conf.Finish ()
534
535 if env['FFT_ANALYSIS']:
536         #
537         # Check for fftw3 header as well as the library
538         #
539
540         conf = Configure(libraries['fftw3'])
541
542         if conf.CheckHeader ('fftw3.h') == False:
543             print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
544             sys.exit (1)            
545         conf.Finish()
546
547 if env['AUBIO']:
548         #
549         # Check for aubio header as well as the library
550         #
551
552         conf = Configure(libraries['aubio'])
553
554         if conf.CheckHeader ('aubio/aubio.h') == False:
555             print ('AUBIO-related features be compiled without the aubio headers, which do not seem to be installed')
556             env['AUBIO'] = 0
557         conf.Finish()
558
559 if env['FREESOUND']:
560         #
561         # Check for curl header as well as the library
562         #
563
564         libraries['curl'] = LibraryInfo()
565
566         conf = Configure(libraries['curl'])
567
568         if conf.CheckHeader ('curl/curl.h') == False:
569                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
570                 sys.exit (1)            
571         else:
572                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
573         conf.Finish()
574 else:
575         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
576
577 if env['LV2']:
578         conf = env.Configure(custom_tests = { 'CheckPKGExists' : CheckPKGExists })
579         
580         if conf.CheckPKGExists ('\"slv2 >= 0.6.0\"'):
581                 libraries['slv2'] = LibraryInfo()
582                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
583                 env.Append (CCFLAGS="-DHAVE_LV2")
584         else:
585                 print 'Building Ardour with LV2 support requires SLV2 >= 0.6.0'
586                 print 'WARNING: SLV2 not found, or too old.  Ardour will be built without LV2 support.'
587                 print 'Until the 2.4 release, Ardour requires SLV2 out of SVN.'
588                 print 'Testing would be very much appreciated!  svn co http://svn.drobilla.net/lad/slv2'
589                 env['LV2'] = 0
590         conf.Finish()
591 else:
592         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
593
594 libraries['jack'] = LibraryInfo()
595 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
596
597 libraries['xml'] = LibraryInfo()
598 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
599
600 libraries['xslt'] = LibraryInfo()
601 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
602
603 libraries['glib2'] = LibraryInfo()
604 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
605 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
606 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
607 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
608
609 libraries['freetype2'] = LibraryInfo()
610 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
611
612 libraries['gtk2'] = LibraryInfo()
613 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
614
615 libraries['pango'] = LibraryInfo()
616 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
617
618 libraries['libgnomecanvas2'] = LibraryInfo()
619 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
620
621 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
622
623 # The Ardour Control Protocol Library
624
625 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
626                                       CPPPATH='#libs/surfaces/control_protocol')
627
628 # The Ardour backend/engine
629
630 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
631 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
632 libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
633 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
634
635
636 # SCons should really do this for us
637
638 conf = env.Configure ()
639
640 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
641 if have_cxx[0] != 1:
642     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
643     sys.exit (1)
644 else:
645     print "Congratulations, you have a functioning C++ compiler."
646
647 env = conf.Finish()
648
649
650 #
651 # Compiler flags and other system-dependent stuff
652 #
653
654 opt_flags = []
655 if env['GPROFILE'] == 1:
656     debug_flags = [ '-g', '-pg' ]
657 else:
658     debug_flags = [ '-g' ]
659
660 # guess at the platform, used to define compiler flags
661
662 config_guess = os.popen("tools/config.guess").read()[:-1]
663
664 config_cpu = 0
665 config_arch = 1
666 config_kernel = 2
667 config_os = 3
668 config = config_guess.split ("-")
669
670 print "system triple: " + config_guess
671
672 # Autodetect
673 if env['DIST_TARGET'] == 'auto':
674     if config[config_arch] == 'apple':
675         # The [.] matches to the dot after the major version, "." would match any character
676         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
677             env['DIST_TARGET'] = 'panther'
678         if re.search ("darwin8[.]", config[config_kernel]) != None:
679             env['DIST_TARGET'] = 'tiger'
680         else:
681             env['DIST_TARGET'] = 'leopard'
682     else:
683         if re.search ("x86_64", config[config_cpu]) != None:
684             env['DIST_TARGET'] = 'x86_64'
685         elif re.search("i[0-5]86", config[config_cpu]) != None:
686             env['DIST_TARGET'] = 'i386'
687         elif re.search("powerpc", config[config_cpu]) != None:
688             env['DIST_TARGET'] = 'powerpc'
689         else:
690             env['DIST_TARGET'] = 'i686'
691     print "\n*******************************"
692     print "detected DIST_TARGET = " + env['DIST_TARGET']
693     print "*******************************\n"
694
695
696 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
697     #
698     # Apple/PowerPC optimization options
699     #
700     # -mcpu=7450 does not reliably work with gcc 3.*
701     #
702     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
703         if config[config_arch] == 'apple':
704             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
705             # to support g3s but still have some optimization for above
706             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
707         else:
708             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
709     else:
710         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
711     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
712     opt_flags.extend (["-Os"])
713
714 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':
715     
716     build_host_supports_sse = 0
717     
718     debug_flags.append ("-DARCH_X86")
719     opt_flags.append ("-DARCH_X86")
720     
721     if config[config_kernel] == 'linux' :
722         
723         if env['DIST_TARGET'] != 'i386':
724             
725             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
726             x86_flags = flag_line.split (": ")[1:][0].split ()
727             
728             if "mmx" in x86_flags:
729                 opt_flags.append ("-mmmx")
730             if "sse" in x86_flags:
731                 build_host_supports_sse = 1
732             if "3dnow" in x86_flags:
733                 opt_flags.append ("-m3dnow")
734             
735             if config[config_cpu] == "i586":
736                 opt_flags.append ("-march=i586")
737             elif config[config_cpu] == "i686":
738                 opt_flags.append ("-march=i686")
739     
740     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
741         opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
742         debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
743 # end of processor-specific section
744
745 # optimization section
746 if env['FPU_OPTIMIZATION']:
747     if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
748         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
749         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
750         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
751     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
752         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
753         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
754         if env['DIST_TARGET'] == 'x86_64':
755             opt_flags.append ("-DUSE_X86_64_ASM")
756             debug_flags.append ("-DUSE_X86_64_ASM")
757         if build_host_supports_sse != 1:
758             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)"
759 # end optimization section
760
761 # handle x86/x86_64 libdir properly
762
763 if env['DIST_TARGET'] == 'x86_64':
764     env['LIBDIR']='lib64'
765 else:
766     env['LIBDIR']='lib'
767
768 #
769 # a single way to test if we're on OS X
770 #
771
772 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
773     env['IS_OSX'] = 1
774     # force tiger or later, to avoid issues on PPC which defaults
775     # back to 10.1 if we don't tell it otherwise.
776     env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
777 else:
778     env['IS_OSX'] = 0
779
780 #
781 # save off guessed arch element in an env
782 #
783 env.Append(CONFIG_ARCH=config[config_arch])
784
785
786 #
787 # ARCH="..." overrides all
788 #
789
790 if env['ARCH'] != '':
791     opt_flags = env['ARCH'].split()
792
793 #
794 # prepend boiler plate optimization flags
795 #
796
797 opt_flags[:0] = [
798     "-O3",
799     "-fomit-frame-pointer",
800     "-ffast-math",
801     "-fstrength-reduce",
802     "-pipe"
803     ]
804
805 if env['DEBUG'] == 1:
806     env.Append(CCFLAGS=" ".join (debug_flags))
807     env.Append(LINKFLAGS=" ".join (debug_flags))
808 else:
809     env.Append(CCFLAGS=" ".join (opt_flags))
810     env.Append(LINKFLAGS=" ".join (opt_flags))
811
812 if env['STL_DEBUG'] == 1:
813     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
814
815 if env['UNIVERSAL'] == 1:
816     env.Append(CCFLAGS="-arch i386 -arch ppc")
817     env.Append(LINKFLAGS="-arch i386 -arch ppc")
818
819
820 #
821 # warnings flags
822 #
823
824 env.Append(CCFLAGS="-Wall")
825 env.Append(CXXFLAGS="-Woverloaded-virtual")
826
827 if env['EXTRA_WARN']:
828     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
829     env.Append(CXXFLAGS="-ansi")
830 #    env.Append(CFLAGS="-iso")
831
832 if env['LIBLO']:
833     env.Append(CCFLAGS="-DHAVE_LIBLO")
834
835
836 #
837 # fix scons nitpickiness on APPLE
838 #
839
840
841 def prep_libcheck(topenv, libinfo):
842     if topenv['IS_OSX']:
843         #
844         # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default.
845         #            All libraries needed should be built against this location
846         if topenv['GTKOSX']:
847                 libinfo.Append(CPPPATH="/opt/gtk/include", LIBPATH="/opt/gtk/lib")
848                 libinfo.Append(CXXFLAGS="-I/opt/gtk/include", LINKFLAGS="-L/opt/gtk/lib")
849         libinfo.Append(CPPPATH="/opt/local/include", LIBPATH="/opt/local/lib")
850         libinfo.Append(CXXFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
851
852 prep_libcheck(env, env)
853
854
855 #
856 # these are part of the Ardour source tree because they are C++
857
858
859 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
860                                  LIBPATH='#libs/vamp-sdk',
861                                  CPPPATH='#libs/vamp-sdk')
862 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
863                                  LIBPATH='#libs/vamp-sdk',
864                                  CPPPATH='#libs/vamp-sdk')
865
866 env['RUBBERBAND'] = False
867
868 conf = Configure (env)
869
870 if conf.CheckHeader ('fftw3.h'):
871     env['RUBBERBAND'] = True
872     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
873                                            LIBPATH='#libs/rubberband',
874                                            CPPPATH='#libs/rubberband',
875                                            CCFLAGS='-DUSE_RUBBERBAND')
876 else:
877     print ""
878     print "-------------------------------------------------------------------------"
879     print "You do not have the FFTW single-precision development package installed."
880     print "This prevents Ardour from using the Rubberband library for timestretching"
881     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
882     print "pitchshifting will not be available."
883     print "-------------------------------------------------------------------------"
884     print ""
885
886 conf.Finish()
887
888 #
889 # Check for libusb
890
891 libraries['usb'] = LibraryInfo ()
892 prep_libcheck(env, libraries['usb'])
893
894 conf = Configure (libraries['usb'])
895 if conf.CheckLib ('usb', 'usb_interrupt_write'):
896     have_libusb = True
897 else:
898     have_libusb = False
899
900 # check for linux/input.h while we're at it for powermate
901 if conf.CheckHeader('linux/input.h'):
902     have_linux_input = True
903 else:
904     have_linux_input = False
905
906 libraries['usb'] = conf.Finish ()
907
908 #
909 # Check for FLAC
910
911 libraries['flac'] = LibraryInfo ()
912 prep_libcheck(env, libraries['flac'])
913 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
914
915 #
916 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
917 #                since the version of libsndfile we have internally does not support
918 #                the new API that libFLAC has adopted
919 #
920
921 conf = Configure (libraries['flac'])
922 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
923     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
924     use_flac = True
925 else:
926     use_flac = False
927     
928 libraries['flac'] = conf.Finish ()
929
930 # or if that fails...
931 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
932
933 # boost (we don't link against boost, just use some header files)
934
935 libraries['boost'] = LibraryInfo ()
936 prep_libcheck(env, libraries['boost'])
937 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
938 conf = Configure (libraries['boost'])
939 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
940         print "Boost header files do not appear to be installed."
941         sys.exit (1)
942     
943 libraries['boost'] = conf.Finish ()
944
945 #
946 # Check for liblo
947
948 if env['LIBLO']:
949     libraries['lo'] = LibraryInfo ()
950     prep_libcheck(env, libraries['lo'])
951
952     conf = Configure (libraries['lo'])
953     if conf.CheckLib ('lo', 'lo_server_new') == False:
954         print "liblo does not appear to be installed."
955         sys.exit (1)
956     
957     libraries['lo'] = conf.Finish ()
958
959 #
960 # Check for dmalloc
961
962 libraries['dmalloc'] = LibraryInfo ()
963 prep_libcheck(env, libraries['dmalloc'])
964
965 #
966 # look for the threaded version
967 #
968
969 conf = Configure (libraries['dmalloc'])
970 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
971     have_libdmalloc = True
972 else:
973     have_libdmalloc = False
974
975 libraries['dmalloc'] = conf.Finish ()
976
977 #
978 # ensure FREEDESKTOP target is doable..
979 #
980
981 conf = env.Configure ()
982 if env['FREEDESKTOP']:
983         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
984         if have_update_mime_database[0] != 1:
985                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
986                 env['FREEDESKTOP'] = 0
987         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
988         if have_gtk_update_icon_cache[0] != 1:
989                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
990                 env['FREEDESKTOP'] = 0
991         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
992         if have_update_desktop_database[0] != 1:
993                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
994                 env['FREEDESKTOP'] = 0
995 env = conf.Finish()
996
997 #
998 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
999 #
1000
1001 conf = Configure(env)
1002
1003 if conf.CheckCHeader('alsa/asoundlib.h'):
1004     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
1005     env['SYSMIDI'] = 'ALSA Sequencer'
1006     subst_dict['%MIDITAG%'] = "seq"
1007     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1008 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1009     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1010     if env['GTKOSX']:
1011         # We need Carbon as well as the rest
1012         libraries['sysmidi'] = LibraryInfo (
1013                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1014     else:
1015         libraries['sysmidi'] = LibraryInfo (
1016                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1017     env['SYSMIDI'] = 'CoreMIDI'
1018     subst_dict['%MIDITAG%'] = "ardour"
1019     subst_dict['%MIDITYPE%'] = "coremidi"
1020 else:
1021     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."
1022     sys.exit (1)
1023
1024 env = conf.Finish()
1025
1026 if env['SYSLIBS']:
1027
1028     syslibdeps = \
1029     {
1030         'sigc++-2.0'           : '2.0',
1031         'gtkmm-2.4'            : '2.8',
1032         'libgnomecanvasmm-2.6' : '2.12.0'
1033     }
1034
1035     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1036                     'CheckPKGVersion' : CheckPKGVersion })
1037
1038     for pkg, version in syslibdeps.iteritems():
1039         if not conf.CheckPKGVersion( pkg, version ):
1040             print '%s >= %s not found.' %(pkg, version)
1041             DependenciesRequiredMessage()
1042             Exit(1)
1043     
1044     env = conf.Finish()
1045     
1046     libraries['sigc2'] = LibraryInfo()
1047     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1048     libraries['glibmm2'] = LibraryInfo()
1049     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1050     libraries['cairomm'] = LibraryInfo()
1051     libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1052     libraries['gdkmm2'] = LibraryInfo()
1053     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1054     libraries['gtkmm2'] = LibraryInfo()
1055     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1056     libraries['atkmm'] = LibraryInfo()
1057     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1058     libraries['pangomm'] = LibraryInfo()
1059     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1060     libraries['libgnomecanvasmm'] = LibraryInfo()
1061     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1062
1063 #
1064 # cannot use system one for the time being
1065 #
1066     
1067     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1068                                     LIBPATH='#libs/libsndfile',
1069                                     CPPPATH=['#libs/libsndfile/src'])
1070
1071 #    libraries['libglademm'] = LibraryInfo()
1072 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1073
1074 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1075     libraries['soundtouch'] = LibraryInfo()
1076     #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1077     # Comment the previous line and uncomment this for Debian:
1078     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1079
1080     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1081                                             LIBPATH='#libs/appleutility',
1082                                             CPPPATH='#libs/appleutility')
1083     
1084     coredirs = [
1085         'templates'
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     ]
1152     
1153     subdirs = [
1154         'libs/sigc++2',
1155         'libs/libsndfile',
1156         'libs/pbd',
1157         'libs/midi++2',
1158         'libs/ardour',
1159         'libs/vamp-sdk',
1160         'libs/vamp-plugins/',
1161     # these are unconditionally included but have
1162     # tests internally to avoid compilation etc
1163     # if VST is not set
1164         'libs/fst',
1165         'vst',
1166     # this is unconditionally included but has
1167     # tests internally to avoid compilation etc
1168     # if COREAUDIO is not set
1169         'libs/appleutility'
1170         ]
1171     
1172     gtk_subdirs = [
1173         'libs/glibmm2',
1174         'libs/gtkmm2/pango',
1175         'libs/gtkmm2/atk',
1176         'libs/gtkmm2/gdk',
1177         'libs/gtkmm2/gtk',
1178         'libs/libgnomecanvasmm',
1179         'libs/gtkmm2ext',
1180         'gtk2_ardour',
1181         'libs/clearlooks'
1182         ]
1183
1184 #
1185 # * always build the LGPL control protocol lib, since we link against it from libardour
1186 # * ditto for generic MIDI
1187 # * tranzport checks whether it should build internally, but we need here so that
1188 #   its included in the tarball
1189 #
1190
1191 surface_subdirs = [ 'libs/surfaces/control_protocol',
1192                     'libs/surfaces/generic_midi',
1193                     'libs/surfaces/tranzport',
1194                     'libs/surfaces/mackie',
1195                     'libs/surfaces/powermate'
1196                     ]
1197
1198 if env['SURFACES']:
1199     if have_libusb:
1200         env['TRANZPORT'] = 1
1201     else:
1202         env['TRANZPORT'] = 0
1203         print 'Disabled building Tranzport code because libusb could not be found'
1204
1205     if have_linux_input:
1206         env['POWERMATE'] = 1
1207     else:
1208         env['POWERMATE'] = 0
1209         print 'Disabled building Powermate code because linux/input.h could not be found'
1210
1211     if os.access ('libs/surfaces/sony9pin', os.F_OK):
1212         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1213 else:
1214     env['POWERMATE'] = 0
1215     env['TRANZPORT'] = 0
1216
1217 #
1218 # timestretch libraries
1219 #
1220
1221 timefx_subdirs = ['libs/soundtouch']
1222 if env['RUBBERBAND']:
1223     timefx_subdirs += ['libs/rubberband']
1224
1225 opts.Save('scache.conf', env)
1226 Help(opts.GenerateHelpText(env))
1227
1228 final_prefix = '$PREFIX'
1229
1230 if env['DESTDIR'] :
1231     install_prefix = '$DESTDIR/$PREFIX'
1232 else:
1233     install_prefix = env['PREFIX']
1234
1235 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1236 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1237 subst_dict['%PREFIX%'] = final_prefix;
1238
1239 if env['PREFIX'] == '/usr':
1240     final_config_prefix = '/etc'
1241 else:
1242     final_config_prefix = env['PREFIX'] + '/etc'
1243
1244 config_prefix = '$DESTDIR' + final_config_prefix
1245
1246 #
1247 # everybody needs this
1248 #
1249
1250 env.Merge ([ libraries['core'] ])
1251
1252
1253 #
1254 # i18n support
1255 #
1256
1257 conf = Configure (env)
1258 if env['NLS']:
1259     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1260     print 'Checking for internationalization support ...'
1261     have_gettext = conf.TryAction(Action('xgettext --version'))
1262     if have_gettext[0] != 1:
1263         nls_error += ' No xgettext command.'
1264         env['NLS'] = 0
1265     else:
1266         print "Found xgettext"
1267     
1268     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1269     if have_msgmerge[0] != 1:
1270         nls_error += ' No msgmerge command.'
1271         env['NLS'] = 0
1272     else:
1273         print "Found msgmerge"
1274     
1275     if not conf.CheckCHeader('libintl.h'):
1276         nls_error += ' No libintl.h.'
1277         env['NLS'] = 0
1278         
1279     if env['NLS'] == 0:
1280         print nls_error
1281     else:
1282         print "International version will be built."
1283 env = conf.Finish()
1284
1285 if env['NLS'] == 1:
1286     env.Append(CCFLAGS="-DENABLE_NLS")
1287
1288 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict use_flac')
1289
1290 #
1291 # the configuration file may be system dependent
1292 #
1293
1294 conf = env.Configure ()
1295
1296 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1297     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1298     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1299 else:
1300     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1301     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1302
1303 # posix_memalign available
1304 if not conf.CheckFunc('posix_memalign'):
1305     print 'Did not find posix_memalign(), using malloc'
1306     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1307
1308
1309 env = conf.Finish()
1310
1311 # generate the per-user and system rc files from the same source
1312
1313 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1314
1315 # add to the substitution dictionary
1316
1317 subst_dict['%VERSION%'] = ardour_version[0:3]
1318 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1319 subst_dict['%REVISION_STRING%'] = ''
1320 if os.path.exists('.svn'):
1321     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1322
1323 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1324
1325 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1326 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1327                              [ Delete ('$PREFIX/etc/ardour2'),
1328                                Delete ('$PREFIX/lib/ardour2'),
1329                                Delete ('$PREFIX/bin/ardour2'),
1330                                Delete ('$PREFIX/share/ardour2')])
1331
1332 env.Alias('revision', the_revision)
1333 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
1334 env.Alias('uninstall', remove_ardour)
1335
1336 Default (sysrcbuild)
1337
1338 # source tarball
1339
1340 Precious (env['DISTTREE'])
1341
1342 env.Distribute (env['DISTTREE'],
1343                [ 'SConstruct', 'svn_revision.h',
1344                   'COPYING', 'PACKAGER_README', 'README',
1345                   'ardour.rc.in',
1346                   'tools/config.guess',
1347                   'icons/icon/ardour_icon_mac_mask.png',
1348                   'icons/icon/ardour_icon_mac.png',
1349                   'icons/icon/ardour_icon_tango_16px_blue.png',
1350                   'icons/icon/ardour_icon_tango_16px_red.png',
1351                   'icons/icon/ardour_icon_tango_22px_blue.png',
1352                   'icons/icon/ardour_icon_tango_22px_red.png',
1353                   'icons/icon/ardour_icon_tango_32px_blue.png',
1354                   'icons/icon/ardour_icon_tango_32px_red.png',
1355                   'icons/icon/ardour_icon_tango_48px_blue.png',
1356                   'icons/icon/ardour_icon_tango_48px_red.png'
1357                   ] +
1358                 glob.glob ('DOCUMENTATION/AUTHORS*') +
1359                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
1360                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
1361                 glob.glob ('DOCUMENTATION/BUILD*') +
1362                 glob.glob ('DOCUMENTATION/FAQ*') +
1363                 glob.glob ('DOCUMENTATION/README*')
1364                 )
1365
1366 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1367 env.Alias ('srctar', srcdist)
1368
1369 #
1370 # don't leave the distree around
1371 #
1372
1373 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1374 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1375
1376 #
1377 # the subdirs
1378 #
1379
1380 for subdir in coredirs:
1381     SConscript (subdir + '/SConscript')
1382
1383 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1384     for subdir in sublistdir:
1385         SConscript (subdir + '/SConscript')
1386
1387 # cleanup
1388 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1389