do not look for (and potentially exit) jack servers if jack is already running
[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'
25
26 subst_dict = { }
27
28 #
29 # Command-line options
30 #
31
32 opts = Options('scache.conf')
33 opts.AddOptions(
34     ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
35     ('WINDOWS_KEY', 'Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key', 'Mod4><Super'),
36     BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
37     BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
38     BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
39     BoolOption('OLDFONTS', 'Old school font sizes', 0),
40     BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
41     BoolOption('STL_DEBUG', 'Set to build with Standard Template Library Debugging', 0),
42     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
43     EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'leopard', 'none' ), ignorecase=2),
44     BoolOption('DMALLOC', 'Compile and link using the dmalloc library', 0),
45     BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic.  Might break compilation.  For pedants', 0),
46     BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 1),
47     BoolOption('FREESOUND', 'Include Freesound database lookup', 0),
48     BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
49     BoolOption('LIBLO', 'Compile with support for liblo library', 1),
50     BoolOption('NLS', 'Set to turn on i18n support', 1),
51     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
52     BoolOption('SURFACES', 'Build support for control surfaces', 1),
53     BoolOption('WIIMOTE', 'Build the wiimote control surface', 0),
54     BoolOption('SYSLIBS', 'USE AT YOUR OWN RISK: CANCELS ALL SUPPORT FROM ARDOUR AUTHORS: Use existing system versions of various libraries instead of internal ones', 0),
55     BoolOption('UNIVERSAL', 'Compile as universal binary.  Requires that external libraries are already universal.', 0),
56     BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
57     BoolOption('VST', 'Compile with support for VST', 0),
58     BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 1),
59     BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
60     BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
61     BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
62     BoolOption('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1),
63     BoolOption('AUSTATE', "Build with support for AU settings & presets saving/loading", 0)
64 )
65
66 #----------------------------------------------------------------------
67 # a handy helper that provides a way to merge compile/link information
68 # from multiple different "environments"
69 #----------------------------------------------------------------------
70 #
71 class LibraryInfo(Environment):
72     def __init__(self,*args,**kw):
73         Environment.__init__ (self,*args,**kw)
74     
75     def Merge (self,others):
76         for other in others:
77             self.Append (LIBS = other.get ('LIBS',[]))
78             self.Append (LIBPATH = other.get ('LIBPATH', []))
79             self.Append (CPPPATH = other.get('CPPPATH', []))
80             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
81             self.Append (CCFLAGS = other.get('CCFLAGS', []))
82         self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
83         self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
84         #doing LINKFLAGS breaks -framework
85         #doing LIBS break link order dependency
86     
87     def ENV_update(self, src_ENV):
88         for k in src_ENV.keys():
89             if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
90                                                   'LIB', 'INCLUDE' ]:
91                 self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
92             else:
93                 self['ENV'][k]=src_ENV[k]
94
95 env = LibraryInfo (options = opts,
96                    CPPPATH = [ '.' ],
97                    VERSION = ardour_version,
98                    TARBALL='ardour-' + ardour_version + '.tar.bz2',
99                    DISTFILES = [ ],
100                    DISTTREE  = '#ardour-' + ardour_version,
101                    DISTCHECKDIR = '#ardour-' + ardour_version + '/check'
102                    )
103
104 env.ENV_update(os.environ)
105
106 #----------------------------------------------------------------------
107 # Builders
108 #----------------------------------------------------------------------
109
110 # Handy subst-in-file builder
111 #
112
113 def do_subst_in_file(targetfile, sourcefile, dict):
114     """Replace all instances of the keys of dict with their values.
115     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
116     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
117     """
118     try:
119         f = open(sourcefile, 'rb')
120         contents = f.read()
121         f.close()
122     except:
123         raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
124     for (k,v) in dict.items():
125         contents = re.sub(k, v, contents)
126     try:
127         f = open(targetfile, 'wb')
128         f.write(contents)
129         f.close()
130     except:
131         raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
132     return 0 # success
133
134 def subst_in_file(target, source, env):
135     if not env.has_key('SUBST_DICT'):
136         raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
137     d = dict(env['SUBST_DICT']) # copy it
138     for (k,v) in d.items():
139         if callable(v):
140             d[k] = env.subst(v())
141         elif SCons.Util.is_String(v):
142             d[k]=env.subst(v)
143         else:
144             raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
145     for (t,s) in zip(target, source):
146         return do_subst_in_file(str(t), str(s), d)
147
148 def subst_in_file_string(target, source, env):
149     """This is what gets printed on the console."""
150     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
151                       for (t,s) in zip(target, source)])
152
153 def subst_emitter(target, source, env):
154     """Add dependency from substituted SUBST_DICT to target.
155     Returns original target, source tuple unchanged.
156     """
157     d = env['SUBST_DICT'].copy() # copy it
158     for (k,v) in d.items():
159         if callable(v):
160             d[k] = env.subst(v())
161         elif SCons.Util.is_String(v):
162             d[k]=env.subst(v)
163     Depends(target, SCons.Node.Python.Value(d))
164     # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
165     return target, source
166
167 subst_action = Action (subst_in_file, subst_in_file_string)
168 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
169
170 #
171 # internationalization
172 #
173
174 # po_builder: builder function to copy po files to the parent directory while updating them
175 #
176 # first source:  .po file
177 # second source: .pot file
178 #
179
180 def po_builder(target,source,env):
181     os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
182     args = [ 'msgmerge',
183              '--update',
184              str(target[0]),
185              str(source[1])
186              ]
187     print 'Updating ' + str(target[0])
188     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
189
190 po_bld = Builder (action = po_builder)
191 env.Append(BUILDERS = {'PoBuild' : po_bld})
192
193 # mo_builder: builder function for (binary) message catalogs (.mo)
194 #
195 # first source:  .po file
196 #
197
198 def mo_builder(target,source,env):
199     args = [ 'msgfmt',
200              '-c',
201              '-o',
202              target[0].get_path(),
203              source[0].get_path()
204              ]
205     return os.spawnvp (os.P_WAIT, 'msgfmt', args)
206
207 mo_bld = Builder (action = mo_builder)
208 env.Append(BUILDERS = {'MoBuild' : mo_bld})
209
210 # pot_builder: builder function for message templates (.pot)
211 #
212 # source: list of C/C++ etc. files to extract messages from
213 #
214
215 def pot_builder(target,source,env):
216     args = [ 'xgettext',
217              '--keyword=_',
218              '--keyword=N_',
219              '--from-code=UTF-8',
220              '-o', target[0].get_path(),
221              "--default-domain=" + env['PACKAGE'],
222              '--copyright-holder="Paul Davis"' ]
223     args += [ src.get_path() for src in source ]
224     
225     return os.spawnvp (os.P_WAIT, 'xgettext', args)
226
227 pot_bld = Builder (action = pot_builder)
228 env.Append(BUILDERS = {'PotBuild' : pot_bld})
229
230 #
231 # utility function, not a builder
232 #
233
234 def i18n (buildenv, sources, installenv):
235     domain = buildenv['PACKAGE']
236     potfile = buildenv['POTFILE']
237     
238     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
239     
240     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
241     languages = [ po.replace ('.po', '') for po in p_oze ]
242     
243     for po_file in p_oze:
244         buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
245         mo_file = po_file.replace (".po", ".mo")
246         installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
247         installenv.Alias ('msgupdate', buildenv.MoBuild (mo_file, po_file))
248     
249     for lang in languages:
250         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
251         moname = domain + '.mo'
252         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
253
254
255 def fetch_svn_revision (path):
256     cmd = "LANG= "
257     cmd += "svn info "
258     cmd += path
259     cmd += " | awk '/^Revision:/ { print $2}'"
260     return commands.getoutput (cmd)
261
262 def create_stored_revision (target = None, source = None, env = None):
263     if os.path.exists('.svn'):    
264         rev = fetch_svn_revision ('.');
265         try:
266             text  = "#include <ardour/svn_revision.h>\n"
267             text += "namespace ARDOUR {\n";
268             text += "extern const char* svn_revision = \"" + rev + "\";\n";
269             text += "}\n";
270             print '============> writing svn revision info to libs/ardour/svn_revision.cc\n'
271             o = file ('libs/ardour/svn_revision.cc', 'w')
272             o.write (text)
273             o.close ()
274         except IOError:
275             print "Could not open libs/ardour/svn_revision.cc for writing\n"
276             sys.exit (-1)
277     else:
278         if not os.path.exists('libs/ardour/ardour/svn_revision.h'):    
279             print "This release of ardour is missing libs/ardour/ardour/svn_revision.h. Blame the packager."
280             sys.exit (-1)
281
282 #
283 # A generic builder for version.cc files
284 #
285 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
286 # note: assumes one source files, the header that declares the version variables
287 #
288
289 def version_builder (target, source, env):
290
291     text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
292     text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
293     text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
294     
295     try:
296         o = file (target[0].get_path(), 'w')
297         o.write (text)
298         o.close ()
299     except IOError:
300         print "Could not open", target[0].get_path(), " for writing\n"
301         sys.exit (-1)
302
303     text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
304     text += "#define __" + env['DOMAIN'] + "_version_h__\n"
305     text += "extern const char* " + env['DOMAIN'] + "_revision;\n"
306     text += "extern int " + env['DOMAIN'] + "_major_version;\n"
307     text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
308     text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
309     text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
310     
311     try:
312         o = file (target[1].get_path(), 'w')
313         o.write (text)
314         o.close ()
315     except IOError:
316         print "Could not open", target[1].get_path(), " for writing\n"
317         sys.exit (-1)
318         
319     return None
320
321 version_bld = Builder (action = version_builder)
322 env.Append (BUILDERS = {'VersionBuild' : version_bld})
323
324 #
325 # a builder that makes a hard link from the 'source' executable to a name with
326 # a "build ID" based on the most recent CVS activity that might be reasonably
327 # related to version activity. this relies on the idea that the SConscript
328 # file that builds the executable is updated with new version info and committed
329 # to the source code repository whenever things change.
330 #
331
332 def versioned_builder(target,source,env):
333     w, r = os.popen2( "LANG= svn info | awk '/^Revision:/ { print $2}'")
334     
335     last_revision = r.readline().strip()
336     w.close()
337     r.close()
338     if last_revision == "":
339         print "No SVN info found - versioned executable cannot be built"
340         return -1
341     
342     print "The current build ID is " + last_revision
343     
344     tagged_executable = source[0].get_path() + '-' + last_revision
345     
346     if os.path.exists (tagged_executable):
347         print "Replacing existing executable with the same build tag."
348         os.unlink (tagged_executable)
349     
350     return os.link (source[0].get_path(), tagged_executable)
351
352 verbuild = Builder (action = versioned_builder)
353 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
354
355 #
356 # source tar file builder
357 #
358
359 def distcopy (target, source, env):
360     treedir = str (target[0])
361     
362     try:
363         os.mkdir (treedir)
364     except OSError, (errnum, strerror):
365         if errnum != errno.EEXIST:
366             print 'mkdir ', treedir, ':', strerror
367     
368     cmd = 'tar cf - '
369     #
370     # we don't know what characters might be in the file names
371     # so quote them all before passing them to the shell
372     #
373     all_files = ([ str(s) for s in source ])
374     cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
375     cmd += ' | (cd ' + treedir + ' && tar xf -)'
376     p = os.popen (cmd)
377     return p.close ()
378
379 def tarballer (target, source, env):
380     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'" + " --exclude .svn --exclude '.svn/*'"
381     print 'running ', cmd, ' ... '
382     p = os.popen (cmd)
383     return p.close ()
384
385 dist_bld = Builder (action = distcopy,
386                     target_factory = SCons.Node.FS.default_fs.Entry,
387                     source_factory = SCons.Node.FS.default_fs.Entry,
388                     multi = 1)
389
390 tarball_bld = Builder (action = tarballer,
391                        target_factory = SCons.Node.FS.default_fs.Entry,
392                        source_factory = SCons.Node.FS.default_fs.Entry)
393
394 env.Append (BUILDERS = {'Distribute' : dist_bld})
395 env.Append (BUILDERS = {'Tarball' : tarball_bld})
396
397 ####################
398 # push environment
399 ####################
400
401 def pushEnvironment(context):
402     if os.environ.has_key('PATH'):
403         context.Append(PATH = os.environ['PATH'])
404         context['ENV']['PATH'] = os.environ['PATH']
405         
406     if os.environ.has_key('PKG_CONFIG_PATH'):
407         context.Append(PKG_CONFIG_PATH = os.environ['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 #libraries['sndfile'] = LibraryInfo()
488 #libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
489
490 libraries['lrdf'] = LibraryInfo()
491 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
492
493 libraries['raptor'] = LibraryInfo()
494 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
495
496 libraries['samplerate'] = LibraryInfo()
497 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
498
499 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
500
501 if conf.CheckPKGExists ('fftw3f'):
502     libraries['fftw3f'] = LibraryInfo()
503     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
504
505 if conf.CheckPKGExists ('fftw3'):
506     libraries['fftw3'] = LibraryInfo()
507     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
508
509 if conf.CheckPKGExists ('aubio'):
510     libraries['aubio'] = LibraryInfo()
511     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
512     env['AUBIO'] = 1
513 else:
514     env['AUBIO'] = 0
515
516 env = conf.Finish ()
517
518 if env['FFT_ANALYSIS']:
519         #
520         # Check for fftw3 header as well as the library
521         #
522
523         conf = Configure(libraries['fftw3'])
524
525         if conf.CheckHeader ('fftw3.h') == False:
526             print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
527             sys.exit (1)            
528         conf.Finish()
529
530 if env['FREESOUND']:
531         #
532         # Check for curl header as well as the library
533         #
534
535         libraries['curl'] = LibraryInfo()
536
537         conf = Configure(libraries['curl'])
538
539         if conf.CheckHeader ('curl/curl.h') == False:
540                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
541                 sys.exit (1)            
542         else:
543                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
544         conf.Finish()
545 else:
546         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
547
548 if env['LV2']:
549         conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion})
550         
551         if conf.CheckPKGVersion('slv2', '0.6.1'):
552                 libraries['slv2'] = LibraryInfo()
553                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
554                 env.Append (CCFLAGS="-DHAVE_LV2")
555         else:
556                 print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
557                 env['LV2'] = 0
558         conf.Finish()
559 else:
560         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
561
562 if not env['WIIMOTE']:
563         print 'WIIMOTE not enabled. Build with \'scons WIIMOTE=1\' to enable support.'
564
565 libraries['jack'] = LibraryInfo()
566 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
567
568 libraries['xml'] = LibraryInfo()
569 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
570
571 libraries['xslt'] = LibraryInfo()
572 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
573
574 libraries['glib2'] = LibraryInfo()
575 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
576 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
577 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
578 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
579
580 libraries['freetype2'] = LibraryInfo()
581 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
582
583 libraries['gtk2'] = LibraryInfo()
584 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
585
586 libraries['pango'] = LibraryInfo()
587 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
588
589 libraries['libgnomecanvas2'] = LibraryInfo()
590 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
591
592 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
593
594 # The Ardour Control Protocol Library
595
596 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
597                                       CPPPATH='#libs/surfaces/control_protocol')
598
599 # The Ardour backend/engine
600
601 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
602 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
603 libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
604 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
605
606
607 # SCons should really do this for us
608
609 conf = env.Configure ()
610
611 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
612 if have_cxx[0] != 1:
613     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
614     sys.exit (1)
615 else:
616     print "Congratulations, you have a functioning C++ compiler."
617
618 env = conf.Finish()
619
620
621 #
622 # Compiler flags and other system-dependent stuff
623 #
624
625 opt_flags = []
626 if env['GPROFILE'] == 1:
627     debug_flags = [ '-g', '-pg' ]
628 else:
629     debug_flags = [ '-g' ]
630
631 # guess at the platform, used to define compiler flags
632
633 config_guess = os.popen("tools/config.guess").read()[:-1]
634
635 config_cpu = 0
636 config_arch = 1
637 config_kernel = 2
638 config_os = 3
639 config = config_guess.split ("-")
640
641 print "system triple: " + config_guess
642
643 # Autodetect
644 if env['DIST_TARGET'] == 'auto':
645     if config[config_arch] == 'apple':
646         # The [.] matches to the dot after the major version, "." would match any character
647         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
648             env['DIST_TARGET'] = 'panther'
649         if re.search ("darwin8[.]", config[config_kernel]) != None:
650             env['DIST_TARGET'] = 'tiger'
651         else:
652             env['DIST_TARGET'] = 'leopard'
653     else:
654         if re.search ("x86_64", config[config_cpu]) != None:
655             env['DIST_TARGET'] = 'x86_64'
656         elif re.search("i[0-5]86", config[config_cpu]) != None:
657             env['DIST_TARGET'] = 'i386'
658         elif re.search("powerpc", config[config_cpu]) != None:
659             env['DIST_TARGET'] = 'powerpc'
660         else:
661             env['DIST_TARGET'] = 'i686'
662     print "\n*******************************"
663     print "detected DIST_TARGET = " + env['DIST_TARGET']
664     print "*******************************\n"
665
666
667 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
668     #
669     # Apple/PowerPC optimization options
670     #
671     # -mcpu=7450 does not reliably work with gcc 3.*
672     #
673     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
674         if config[config_arch] == 'apple':
675             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
676             # to support g3s but still have some optimization for above
677             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
678         else:
679             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
680     else:
681         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
682     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
683     opt_flags.extend (["-Os"])
684
685 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':
686     
687     build_host_supports_sse = 0
688     
689     #
690     # ARCH_X86 means anything in the x86 family from i386 to x86_64
691     # USE_X86_64_ASM is used to distingush 32 and 64 bit assembler
692     #
693
694     if (re.search ("(i[0-9]86|x86_64)", config[config_cpu]) != None):
695         debug_flags.append ("-DARCH_X86")
696         opt_flags.append ("-DARCH_X86")
697     
698     if config[config_kernel] == 'linux' :
699         
700         if env['DIST_TARGET'] != 'i386':
701             
702             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
703             x86_flags = flag_line.split (": ")[1:][0].split ()
704             
705             if "mmx" in x86_flags:
706                 opt_flags.append ("-mmmx")
707             if "sse" in x86_flags:
708                 build_host_supports_sse = 1
709             if "3dnow" in x86_flags:
710                 opt_flags.append ("-m3dnow")
711             
712             if config[config_cpu] == "i586":
713                 opt_flags.append ("-march=i586")
714             elif config[config_cpu] == "i686":
715                 opt_flags.append ("-march=i686")
716     
717     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
718         opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
719         debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
720
721     if (env['VST']):
722         #
723         # everything must be 32 bit for VST (we're not replicating Cakewalk's hack, yet ...)
724         # 
725         opt_flags.extend(["-m32"])
726         debug_flags.extend(["-m32"])
727
728 # end of processor-specific section
729
730 # optimization section
731 if env['FPU_OPTIMIZATION']:
732     if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
733         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
734         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
735         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
736     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
737         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
738         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
739         if env['DIST_TARGET'] == 'x86_64' and not env['VST']:
740             opt_flags.append ("-DUSE_X86_64_ASM")
741             debug_flags.append ("-DUSE_X86_64_ASM")
742         if build_host_supports_sse != 1:
743             print "\nWarning: you are building Ardour with SSE support even though your system does not support these instructions. (This may not be an error, especially if you are a package maintainer)"
744 # end optimization section
745
746 # handle x86/x86_64 libdir properly
747
748 if env['DIST_TARGET'] == 'x86_64':
749     env['LIBDIR']='lib64'
750 else:
751     env['LIBDIR']='lib'
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