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