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