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