b41b609820c0e081d5fc1b36eeb9241b6895ae5f
[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['flac'] = LibraryInfo ()
510 libraries['flac'].ParseConfig ('pkg-config --cflags --libs flac')
511
512 libraries['ogg'] = LibraryInfo ()
513 libraries['ogg'].ParseConfig ('pkg-config --cflags --libs ogg')
514
515 libraries['sndfile'] = LibraryInfo()
516 libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
517
518 libraries['lrdf'] = LibraryInfo()
519 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
520
521 libraries['raptor'] = LibraryInfo()
522 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
523
524 libraries['samplerate'] = LibraryInfo()
525 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
526
527 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
528
529 if conf.CheckPKGExists ('fftw3f'):
530     libraries['fftw3f'] = LibraryInfo()
531     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
532
533 if conf.CheckPKGExists ('fftw3'):
534     libraries['fftw3'] = LibraryInfo()
535     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
536
537 if conf.CheckPKGExists ('aubio'):
538     libraries['aubio'] = LibraryInfo()
539     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
540     env['AUBIO'] = 1
541 else:
542     env['AUBIO'] = 0
543
544 env = conf.Finish ()
545
546 if env['FFT_ANALYSIS']:
547         #
548         # Check for fftw3 header as well as the library
549         #
550
551         conf = Configure(libraries['fftw3'])
552
553         if conf.CheckHeader ('fftw3.h') == False:
554             print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
555             sys.exit (1)            
556         conf.Finish()
557
558 if env['FREESOUND']:
559         #
560         # Check for curl header as well as the library
561         #
562
563         libraries['curl'] = LibraryInfo()
564
565         conf = Configure(libraries['curl'])
566
567         if conf.CheckHeader ('curl/curl.h') == False:
568                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
569                 sys.exit (1)            
570         else:
571                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
572         conf.Finish()
573 else:
574         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
575
576 if env['LV2']:
577         conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion})
578         
579         if conf.CheckPKGVersion('slv2', '0.6.0'):
580                 libraries['slv2'] = LibraryInfo()
581                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
582                 env.Append (CCFLAGS="-DHAVE_LV2")
583         else:
584                 print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
585                 env['LV2'] = 0
586         conf.Finish()
587 else:
588         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
589
590 libraries['jack'] = LibraryInfo()
591 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
592
593 libraries['xml'] = LibraryInfo()
594 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
595
596 libraries['xslt'] = LibraryInfo()
597 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
598
599 libraries['glib2'] = LibraryInfo()
600 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
601 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
602 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
603 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
604
605 libraries['freetype2'] = LibraryInfo()
606 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
607
608 libraries['gtk2'] = LibraryInfo()
609 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
610
611 libraries['pango'] = LibraryInfo()
612 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
613
614 libraries['pangocairo'] = LibraryInfo()
615 libraries['pangocairo'].ParseConfig ('pkg-config --cflags --libs pangocairo')
616
617 libraries['libgnomecanvas2'] = LibraryInfo()
618 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
619
620 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
621
622 # The Ardour Control Protocol Library
623
624 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
625                                       CPPPATH='#libs/surfaces/control_protocol')
626
627 # The Ardour backend/engine
628
629 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
630 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
631 libraries['evoral'] = LibraryInfo (LIBS='evoral', LIBPATH='#libs/evoral', CPPPATH='#libs/evoral')
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
778     if env['DIST_TARGET'] == 'leopard':
779         # need this to really build against the 10.4 SDK when building on leopard
780         # ideally this would be configurable, but lets just do that later when we need it
781         env.Append(CCFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
782         env.Append(LINKFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
783
784 else:
785     env['IS_OSX'] = 0
786
787 #
788 # save off guessed arch element in an env
789 #
790 env.Append(CONFIG_ARCH=config[config_arch])
791
792
793 #
794 # ARCH="..." overrides all
795 #
796
797 if env['ARCH'] != '':
798     opt_flags = env['ARCH'].split()
799
800 #
801 # prepend boiler plate optimization flags
802 #
803
804 opt_flags[:0] = [
805     "-O3",
806     "-fomit-frame-pointer",
807     "-ffast-math",
808     "-fstrength-reduce",
809     "-pipe"
810     ]
811
812 if env['DEBUG'] == 1:
813     env.Append(CCFLAGS=" ".join (debug_flags))
814     env.Append(LINKFLAGS=" ".join (debug_flags))
815 else:
816     env.Append(CCFLAGS=" ".join (opt_flags))
817     env.Append(LINKFLAGS=" ".join (opt_flags))
818
819 if env['STL_DEBUG'] == 1:
820     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
821
822 if env['UNIVERSAL'] == 1:
823     env.Append(CCFLAGS="-arch i386 -arch ppc")
824     env.Append(LINKFLAGS="-arch i386 -arch ppc")
825
826
827 #
828 # warnings flags
829 #
830
831 env.Append(CCFLAGS="-Wall")
832 env.Append(CXXFLAGS="-Woverloaded-virtual")
833
834 if env['EXTRA_WARN']:
835     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
836     env.Append(CXXFLAGS="-ansi")
837 #    env.Append(CFLAGS="-iso")
838
839 if env['LIBLO']:
840     env.Append(CCFLAGS="-DHAVE_LIBLO")
841
842
843 #
844 # fix scons nitpickiness on APPLE
845 #
846
847
848 def prep_libcheck(topenv, libinfo):
849     if topenv['IS_OSX']:
850         #
851         # rationale: GTK-Quartz uses jhbuild and installs to $HOME/gtk/inst by default.
852         #            All libraries needed should be built against this location
853
854         if topenv['GTKOSX']:
855                 GTKROOT = os.path.expanduser ('~/gtk/inst')
856                 libinfo.Append(CPPPATH= GTKROOT + "/include", LIBPATH= GTKROOT + "/lib")
857                 libinfo.Append(CXXFLAGS="-I" + GTKROOT + "/include", LINKFLAGS="-L" + GTKROOT + "/lib")
858                 #libinfo.Append(CPPPATH="/opt/local/include", LIBPATH="/opt/local/lib")
859                 #libinfo.Append(CXXFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
860
861 prep_libcheck(env, env)
862
863 #
864 # these are part of the Ardour source tree because they are C++
865
866
867 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
868                                  LIBPATH='#libs/vamp-sdk',
869                                  CPPPATH='#libs/vamp-sdk')
870 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
871                                  LIBPATH='#libs/vamp-sdk',
872                                  CPPPATH='#libs/vamp-sdk')
873
874 env['RUBBERBAND'] = False
875
876 conf = Configure (env)
877
878 if conf.CheckHeader ('fftw3.h'):
879     env['RUBBERBAND'] = True
880     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
881                                            LIBPATH='#libs/rubberband',
882                                            CPPPATH='#libs/rubberband',
883                                            CCFLAGS='-DUSE_RUBBERBAND')
884 else:
885     print ""
886     print "-------------------------------------------------------------------------"
887     print "You do not have the FFTW single-precision development package installed."
888     print "This prevents Ardour from using the Rubberband library for timestretching"
889     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
890     print "pitchshifting will not be available."
891     print "-------------------------------------------------------------------------"
892     print ""
893
894 conf.Finish()
895
896 #
897 # Check for libusb
898
899 libraries['usb'] = LibraryInfo ()
900 prep_libcheck(env, libraries['usb'])
901
902 conf = Configure (libraries['usb'])
903 if conf.CheckLib ('usb', 'usb_interrupt_write'):
904     have_libusb = True
905 else:
906     have_libusb = False
907
908 # check for linux/input.h while we're at it for powermate
909 if conf.CheckHeader('linux/input.h'):
910     have_linux_input = True
911 else:
912     have_linux_input = False
913
914 libraries['usb'] = conf.Finish ()
915
916 # boost (we don't link against boost, just use some header files)
917
918 libraries['boost'] = LibraryInfo ()
919 prep_libcheck(env, libraries['boost'])
920 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
921 conf = Configure (libraries['boost'])
922 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
923         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."
924         sys.exit (1)
925     
926 libraries['boost'] = conf.Finish ()
927
928 #
929 # Check for liblo
930
931 if env['LIBLO']:
932     libraries['lo'] = LibraryInfo ()
933     prep_libcheck(env, libraries['lo'])
934
935     conf = Configure (libraries['lo'])
936     if conf.CheckLib ('lo', 'lo_server_new') == False:
937         print "liblo does not appear to be installed."
938         sys.exit (1)
939     
940     libraries['lo'] = conf.Finish ()
941
942 #
943 # Check for dmalloc
944
945 libraries['dmalloc'] = LibraryInfo ()
946 prep_libcheck(env, libraries['dmalloc'])
947
948 #
949 # look for the threaded version
950 #
951
952 conf = Configure (libraries['dmalloc'])
953 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
954     have_libdmalloc = True
955 else:
956     have_libdmalloc = False
957
958 libraries['dmalloc'] = conf.Finish ()
959
960 #
961 # ensure FREEDESKTOP target is doable..
962 #
963
964 conf = env.Configure ()
965 if env['FREEDESKTOP']:
966         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
967         if have_update_mime_database[0] != 1:
968                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
969                 env['FREEDESKTOP'] = 0
970         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
971         if have_gtk_update_icon_cache[0] != 1:
972                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
973                 env['FREEDESKTOP'] = 0
974         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
975         if have_update_desktop_database[0] != 1:
976                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
977                 env['FREEDESKTOP'] = 0
978 env = conf.Finish()
979
980 #
981 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
982 #
983
984 conf = Configure(env)
985     
986 # ALSA, for engine dialog
987 libraries['asound'] = LibraryInfo ()
988
989 if conf.CheckCHeader('alsa/asoundlib.h'):
990     libraries['asound'] = LibraryInfo (LIBS='asound')
991
992 if conf.CheckCHeader('jack/midiport.h'):
993     libraries['sysmidi'] = LibraryInfo (LIBS='jack')
994     env['SYSMIDI'] = 'JACK MIDI'
995     subst_dict['%MIDITAG%'] = "control"
996     subst_dict['%MIDITYPE%'] = "jack"
997     print "Using JACK MIDI"
998 elif conf.CheckCHeader('alsa/asoundlib.h'):
999     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
1000     env['SYSMIDI'] = 'ALSA Sequencer'
1001     subst_dict['%MIDITAG%'] = "seq"
1002     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1003     print "Using ALSA MIDI"
1004 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1005     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1006     if env['GTKOSX']:
1007         # We need Carbon as well as the rest
1008         libraries['sysmidi'] = LibraryInfo (
1009                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1010     else:
1011         libraries['sysmidi'] = LibraryInfo (
1012                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1013     env['SYSMIDI'] = 'CoreMIDI'
1014     subst_dict['%MIDITAG%'] = "ardour"
1015     subst_dict['%MIDITYPE%'] = "coremidi"
1016 else:
1017     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."
1018     sys.exit (1)
1019
1020 env = conf.Finish()
1021
1022 if env['SYSLIBS']:
1023
1024     syslibdeps = \
1025     {
1026         'sigc++-2.0'           : '2.0',
1027         'gtkmm-2.4'            : '2.8',
1028         'libgnomecanvasmm-2.6' : '2.12.0'
1029     }
1030
1031     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1032                     'CheckPKGVersion' : CheckPKGVersion })
1033
1034     for pkg, version in syslibdeps.iteritems():
1035         if not conf.CheckPKGVersion( pkg, version ):
1036             print '%s >= %s not found.' %(pkg, version)
1037             DependenciesRequiredMessage()
1038             Exit(1)
1039     
1040     env = conf.Finish()
1041     
1042     libraries['sigc2'] = LibraryInfo()
1043     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1044     libraries['glibmm2'] = LibraryInfo()
1045     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1046     libraries['cairo'] = LibraryInfo()
1047     libraries['cairo'].ParseConfig('pkg-config --cflags --libs cairo')
1048     libraries['cairomm'] = LibraryInfo()
1049     libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1050     libraries['gdkmm2'] = LibraryInfo()
1051     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1052     libraries['gtkmm2'] = LibraryInfo()
1053     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1054     libraries['atkmm'] = LibraryInfo()
1055     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1056     libraries['pangomm'] = LibraryInfo()
1057     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1058     libraries['libgnomecanvasmm'] = LibraryInfo()
1059     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1060     libraries['taglib'] = LibraryInfo()
1061     libraries['taglib'].ParseConfig ('pkg-config --cflags --libs taglib')
1062
1063 #    libraries['libglademm'] = LibraryInfo()
1064 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1065
1066 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1067     libraries['soundtouch'] = LibraryInfo()
1068     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1069     # Comment the previous line and uncomment this for some versions of Debian:
1070     #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1071
1072     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1073                                             LIBPATH='#libs/appleutility',
1074                                             CPPPATH='#libs/appleutility')
1075     
1076     libraries['sndfile'] = LibraryInfo()
1077     libraries['sndfile'].ParseConfig ('pkg-config --cflags --libs sndfile')
1078     
1079     coredirs = [
1080         'templates',
1081         'manual'
1082     ]
1083     
1084     subdirs = [
1085         'libs/pbd',
1086         'libs/midi++2',
1087         'libs/evoral',
1088         'libs/ardour',
1089         'libs/vamp-sdk',
1090         'libs/vamp-plugins/',
1091     # these are unconditionally included but have
1092     # tests internally to avoid compilation etc
1093     # if VST is not set
1094         'libs/fst',
1095         'vst',
1096     # this is unconditionally included but has
1097     # tests internally to avoid compilation etc
1098     # if COREAUDIO is not set
1099         'libs/appleutility'
1100         ]
1101     
1102     gtk_subdirs = [
1103 #        'libs/flowcanvas',
1104         'libs/gtkmm2ext',
1105         'gtk2_ardour',
1106         'libs/clearlooks'
1107         ]
1108
1109 else:
1110     libraries['cairo'] = LibraryInfo()
1111     libraries['cairo'].ParseConfig('pkg-config --cflags --libs cairo')
1112     
1113     libraries['gtk2-unix-print'] = LibraryInfo()
1114     libraries['gtk2-unix-print'].ParseConfig('pkg-config --cflags --libs gtk+-unix-print-2.0')
1115     
1116     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
1117                                     LIBPATH='#libs/sigc++2',
1118                                     CPPPATH='#libs/sigc++2')
1119     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
1120                                     LIBPATH='#libs/glibmm2',
1121                                     CPPPATH='#libs/glibmm2/glib')
1122     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
1123                                     LIBPATH='#libs/gtkmm2/pango',
1124                                     CPPPATH='#libs/gtkmm2/pango')
1125     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
1126                                      LIBPATH='#libs/gtkmm2/atk',
1127                                      CPPPATH='#libs/gtkmm2/atk')
1128     libraries['cairomm'] = LibraryInfo(LIBS='cairomm',
1129                                       LIBPATH='#libs/cairomm',
1130                                       CPPPATH='#libs/cairomm')
1131     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
1132                                       LIBPATH='#libs/gtkmm2/gdk',
1133                                       CPPPATH='#libs/gtkmm2/gdk')
1134     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
1135                                      LIBPATH="#libs/gtkmm2/gtk",
1136                                      CPPPATH='#libs/gtkmm2/gtk/')
1137     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
1138                                                 LIBPATH='#libs/libgnomecanvasmm',
1139                                                 CPPPATH='#libs/libgnomecanvasmm')
1140     
1141     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
1142                                           LIBPATH='#libs/soundtouch',
1143                                           CPPPATH=['#libs', '#libs/soundtouch'])
1144     libraries['taglib'] = LibraryInfo(LIBS='libtaglib',
1145                                       LIBPATH='#libs/taglib',
1146                                       CPPPATH=['#libs/taglib/headers','#libs/taglib/headers/taglib'])
1147 #    libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
1148 #                                          LIBPATH='#libs/libglademm',
1149 #                                          CPPPATH='#libs/libglademm')
1150     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1151                                             LIBPATH='#libs/appleutility',
1152                                             CPPPATH='#libs/appleutility')
1153
1154     coredirs = [
1155         'templates',
1156         'manual'
1157     ]
1158     
1159     subdirs = [
1160         'libs/sigc++2',
1161         'libs/taglib',
1162         'libs/pbd',
1163         'libs/midi++2',
1164         'libs/evoral',
1165         'libs/ardour',
1166         'libs/vamp-sdk',
1167         'libs/vamp-plugins/',
1168     # these are unconditionally included but have
1169     # tests internally to avoid compilation etc
1170     # if VST is not set
1171         'libs/fst',
1172         'vst',
1173     # this is unconditionally included but has
1174     # tests internally to avoid compilation etc
1175     # if COREAUDIO is not set
1176         'libs/appleutility'
1177         ]
1178     
1179     gtk_subdirs = [
1180         'libs/glibmm2',
1181         'libs/gtkmm2/pango',
1182         'libs/gtkmm2/atk',
1183         'libs/gtkmm2/gdk',
1184         'libs/gtkmm2/gtk',
1185         'libs/libgnomecanvasmm',
1186         'libs/gtkmm2ext',
1187         'gtk2_ardour',
1188         'libs/clearlooks',
1189         'libs/cairomm'
1190         ]
1191
1192 #
1193 # * always build the LGPL control protocol lib, since we link against it from libardour
1194 # * ditto for generic MIDI
1195 # * tranzport checks whether it should build internally, but we need here so that
1196 #   its included in the tarball
1197 #
1198
1199 surface_subdirs = [ 'libs/surfaces/control_protocol',
1200                     'libs/surfaces/generic_midi',
1201                     'libs/surfaces/tranzport',
1202                     'libs/surfaces/mackie',
1203                     'libs/surfaces/powermate'
1204                     ]
1205
1206 if env['SURFACES']:
1207     if have_libusb:
1208         env['TRANZPORT'] = 1
1209     else:
1210         env['TRANZPORT'] = 0
1211         print 'Disabled building Tranzport code because libusb could not be found'
1212
1213     if have_linux_input:
1214         env['POWERMATE'] = 1
1215     else:
1216         env['POWERMATE'] = 0
1217         print 'Disabled building Powermate code because linux/input.h could not be found'
1218
1219     if os.access ('libs/surfaces/sony9pin', os.F_OK):
1220         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1221 else:
1222     env['POWERMATE'] = 0
1223     env['TRANZPORT'] = 0
1224
1225 #
1226 # timestretch libraries
1227 #
1228
1229 timefx_subdirs = ['libs/soundtouch']
1230 if env['RUBBERBAND']:
1231     timefx_subdirs += ['libs/rubberband']
1232
1233 opts.Save('scache.conf', env)
1234 Help(opts.GenerateHelpText(env))
1235
1236 final_prefix = '$PREFIX'
1237
1238 if env['DESTDIR'] :
1239     install_prefix = '$DESTDIR/$PREFIX'
1240 else:
1241     install_prefix = env['PREFIX']
1242
1243 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1244 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1245 subst_dict['%PREFIX%'] = final_prefix;
1246
1247 if env['PREFIX'] == '/usr':
1248     final_config_prefix = '/etc'
1249 else:
1250     final_config_prefix = env['PREFIX'] + '/etc'
1251
1252 config_prefix = '$DESTDIR' + final_config_prefix
1253
1254 #
1255 # everybody needs this
1256 #
1257
1258 env.Merge ([ libraries['core'] ])
1259
1260
1261 #
1262 # i18n support
1263 #
1264
1265 conf = Configure (env)
1266 if env['NLS']:
1267     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1268     print 'Checking for internationalization support ...'
1269     have_gettext = conf.TryAction(Action('xgettext --version'))
1270     if have_gettext[0] != 1:
1271         nls_error += ' No xgettext command.'
1272         env['NLS'] = 0
1273     else:
1274         print "Found xgettext"
1275     
1276     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1277     if have_msgmerge[0] != 1:
1278         nls_error += ' No msgmerge command.'
1279         env['NLS'] = 0
1280     else:
1281         print "Found msgmerge"
1282     
1283     if not conf.CheckCHeader('libintl.h'):
1284         nls_error += ' No libintl.h.'
1285         env['NLS'] = 0
1286         
1287     if env['NLS'] == 0:
1288         print nls_error
1289     else:
1290         print "International version will be built."
1291 env = conf.Finish()
1292
1293 if env['NLS'] == 1:
1294     env.Append(CCFLAGS="-DENABLE_NLS")
1295
1296 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict')
1297
1298 #
1299 # the configuration file may be system dependent
1300 #
1301
1302 conf = env.Configure ()
1303
1304 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1305     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1306     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1307 else:
1308     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1309     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1310
1311 # posix_memalign available
1312 if not conf.CheckFunc('posix_memalign'):
1313     print 'Did not find posix_memalign(), using malloc'
1314     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1315
1316
1317 env = conf.Finish()
1318
1319 # generate the per-user and system rc files from the same source
1320
1321 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1322
1323 # add to the substitution dictionary
1324
1325 subst_dict['%VERSION%'] = ardour_version[0:3]
1326 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1327 subst_dict['%REVISION_STRING%'] = ''
1328 if os.path.exists('.svn'):
1329     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1330
1331 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1332
1333 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1334 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1335                              [ Delete ('$PREFIX/etc/ardour3'),
1336                                Delete ('$PREFIX/lib/ardour3'),
1337                                Delete ('$PREFIX/bin/ardour3'),
1338                                Delete ('$PREFIX/share/ardour3')])
1339
1340 env.Alias('revision', the_revision)
1341 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour3'), 'ardour_system.rc'))
1342 env.Alias('uninstall', remove_ardour)
1343
1344 Default (sysrcbuild)
1345
1346 # source tarball
1347
1348 Precious (env['DISTTREE'])
1349
1350 env.Distribute (env['DISTTREE'],
1351                [ 'SConstruct', 'svn_revision.h',
1352                   'COPYING', 'PACKAGER_README', 'README',
1353                   'ardour.rc.in',
1354                   'tools/config.guess',
1355                   'icons/icon/ardour_icon_mac_mask.png',
1356                   'icons/icon/ardour_icon_mac.png',
1357                   'icons/icon/ardour_icon_tango_16px_blue.png',
1358                   'icons/icon/ardour_icon_tango_16px_red.png',
1359                   'icons/icon/ardour_icon_tango_22px_blue.png',
1360                   'icons/icon/ardour_icon_tango_22px_red.png',
1361                   'icons/icon/ardour_icon_tango_32px_blue.png',
1362                   'icons/icon/ardour_icon_tango_32px_red.png',
1363                   'icons/icon/ardour_icon_tango_48px_blue.png',
1364                   'icons/icon/ardour_icon_tango_48px_red.png'
1365                   ] +
1366                 glob.glob ('DOCUMENTATION/AUTHORS*') +
1367                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
1368                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
1369                 glob.glob ('DOCUMENTATION/BUILD*') +
1370                 glob.glob ('DOCUMENTATION/FAQ*') +
1371                 glob.glob ('DOCUMENTATION/README*')
1372                 )
1373
1374 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1375 env.Alias ('srctar', srcdist)
1376
1377 #
1378 # don't leave the distree around
1379 #
1380
1381 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1382 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1383
1384 #
1385 # Update revision info before going into subdirs
1386 #
1387
1388 create_stored_revision()
1389
1390 #
1391 # the subdirs
1392 #
1393
1394 for subdir in coredirs:
1395     SConscript (subdir + '/SConscript')
1396
1397 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1398     for subdir in sublistdir:
1399         SConscript (subdir + '/SConscript')
1400
1401 # cleanup
1402 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1403