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