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