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