prevent VST build on DIST_TARGET=x86_64
[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."
760     print "Recompile with the DIST_TARGET=i386 or DIST_TARGET=i686."
761     print "\nPlease be aware that this will only work if your system"
762     print "    is setup with 32 bit versions of all the required libraries."
763     sys.exit (-1)
764
765 #
766 # a single way to test if we're on OS X
767 #
768
769 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
770     env['IS_OSX'] = 1
771     # force tiger or later, to avoid issues on PPC which defaults
772     # back to 10.1 if we don't tell it otherwise.
773     env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
774
775     if env['DIST_TARGET'] == 'leopard':
776         # need this to really build against the 10.4 SDK when building on leopard
777         # ideally this would be configurable, but lets just do that later when we need it
778         env.Append(CCFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
779         env.Append(LINKFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
780
781 else:
782     env['IS_OSX'] = 0
783
784 #
785 # save off guessed arch element in an env
786 #
787 env.Append(CONFIG_ARCH=config[config_arch])
788
789
790 #
791 # ARCH="..." overrides all
792 #
793
794 if env['ARCH'] != '':
795     opt_flags = env['ARCH'].split()
796
797 #
798 # prepend boiler plate optimization flags
799 #
800
801 opt_flags[:0] = [
802     "-O3",
803     "-fomit-frame-pointer",
804     "-ffast-math",
805     "-fstrength-reduce",
806     "-pipe"
807     ]
808
809 if env['DEBUG'] == 1:
810     env.Append(CCFLAGS=" ".join (debug_flags))
811     env.Append(LINKFLAGS=" ".join (debug_flags))
812 else:
813     env.Append(CCFLAGS=" ".join (opt_flags))
814     env.Append(LINKFLAGS=" ".join (opt_flags))
815
816 if env['STL_DEBUG'] == 1:
817     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
818
819 if env['UNIVERSAL'] == 1:
820     env.Append(CCFLAGS="-arch i386 -arch ppc")
821     env.Append(LINKFLAGS="-arch i386 -arch ppc")
822
823
824 #
825 # warnings flags
826 #
827
828 env.Append(CCFLAGS="-Wall")
829 env.Append(CXXFLAGS="-Woverloaded-virtual")
830
831 if env['EXTRA_WARN']:
832     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
833     env.Append(CXXFLAGS="-ansi")
834 #    env.Append(CFLAGS="-iso")
835
836 if env['LIBLO']:
837     env.Append(CCFLAGS="-DHAVE_LIBLO")
838
839
840 #
841 # fix scons nitpickiness on APPLE
842 #
843
844
845 def prep_libcheck(topenv, libinfo):
846     if topenv['IS_OSX']:
847         #
848         # rationale: GTK-Quartz uses jhbuild and installs to ~/gtk/inst by default.
849         # All libraries needed should be built against this location
850         if topenv['GTKOSX']:
851             GTKROOT = os.path.expanduser ('~/gtk/inst')
852             libinfo.Append(CPPPATH= GTKROOT + "/include", LIBPATH= GTKROOT + "/lib")
853             libinfo.Append(CXXFLAGS="-I" + GTKROOT + "/include", LINKFLAGS="-L" + GTKROOT + "/lib")
854             
855 prep_libcheck(env, env)
856
857
858 #
859 # these are part of the Ardour source tree because they are C++
860
861
862 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
863                                  LIBPATH='#libs/vamp-sdk',
864                                  CPPPATH='#libs/vamp-sdk')
865 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
866                                  LIBPATH='#libs/vamp-sdk',
867                                  CPPPATH='#libs/vamp-sdk')
868
869 env['RUBBERBAND'] = False
870
871 conf = Configure (env)
872
873 if conf.CheckHeader ('fftw3.h'):
874     env['RUBBERBAND'] = True
875     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
876                                            LIBPATH='#libs/rubberband',
877                                            CPPPATH='#libs/rubberband',
878                                            CCFLAGS='-DUSE_RUBBERBAND')
879 else:
880     print ""
881     print "-------------------------------------------------------------------------"
882     print "You do not have the FFTW single-precision development package installed."
883     print "This prevents Ardour from using the Rubberband library for timestretching"
884     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
885     print "pitchshifting will not be available."
886     print "-------------------------------------------------------------------------"
887     print ""
888
889 conf.Finish()
890
891 #
892 # Check for libusb
893
894 libraries['usb'] = LibraryInfo ()
895 prep_libcheck(env, libraries['usb'])
896
897 conf = Configure (libraries['usb'])
898 if conf.CheckLib ('usb', 'usb_interrupt_write'):
899     have_libusb = True
900 else:
901     have_libusb = False
902
903 # check for linux/input.h while we're at it for powermate
904 if conf.CheckHeader('linux/input.h'):
905     have_linux_input = True
906 else:
907     have_linux_input = False
908
909 libraries['usb'] = conf.Finish ()
910
911 #
912 # Check for wiimote dependencies
913
914 if env['WIIMOTE']:
915     wiimoteConf = env.Configure ( )
916     if not wiimoteConf.CheckHeader('cwiid.h'):
917         print 'WIIMOTE configured but you are missing libcwiid!'
918         sys.exit(1)
919     if not wiimoteConf.CheckHeader('bluetooth/bluetooth.h'):
920         print 'WIIMOTE configured but you are missing the libbluetooth headers which you need to compile wiimote support!'
921         sys.exit(1)
922     wiimoteConf.Finish()
923
924
925 #
926 # Check for FLAC
927
928 libraries['flac'] = LibraryInfo ()
929 prep_libcheck(env, libraries['flac'])
930 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
931
932 #
933 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
934 #                since the version of libsndfile we have internally does not support
935 #                the new API that libFLAC has adopted
936 #
937
938 conf = Configure (libraries['flac'])
939 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
940     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
941     use_flac = True
942 else:
943     use_flac = False
944     
945 libraries['flac'] = conf.Finish ()
946
947 # or if that fails...
948 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
949
950 # boost (we don't link against boost, just use some header files)
951
952 libraries['boost'] = LibraryInfo ()
953 prep_libcheck(env, libraries['boost'])
954 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
955 conf = Configure (libraries['boost'])
956 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
957         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."
958         sys.exit (1)
959     
960 libraries['boost'] = conf.Finish ()
961
962 #
963 # Check for liblo
964
965 if env['LIBLO']:
966     libraries['lo'] = LibraryInfo ()
967     prep_libcheck(env, libraries['lo'])
968
969     conf = Configure (libraries['lo'])
970     if conf.CheckLib ('lo', 'lo_server_new') == False:
971         print "liblo does not appear to be installed."
972         sys.exit (1)
973     
974     libraries['lo'] = conf.Finish ()
975
976 #
977 # Check for dmalloc
978
979 libraries['dmalloc'] = LibraryInfo ()
980 prep_libcheck(env, libraries['dmalloc'])
981
982 #
983 # look for the threaded version
984 #
985
986 conf = Configure (libraries['dmalloc'])
987 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
988     have_libdmalloc = True
989 else:
990     have_libdmalloc = False
991
992 libraries['dmalloc'] = conf.Finish ()
993
994 #
995 # ensure FREEDESKTOP target is doable..
996 #
997
998 conf = env.Configure ()
999 if env['FREEDESKTOP']:
1000         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
1001         if have_update_mime_database[0] != 1:
1002                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
1003                 env['FREEDESKTOP'] = 0
1004         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
1005         if have_gtk_update_icon_cache[0] != 1:
1006                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
1007                 env['FREEDESKTOP'] = 0
1008         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
1009         if have_update_desktop_database[0] != 1:
1010                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
1011                 env['FREEDESKTOP'] = 0
1012 env = conf.Finish()
1013
1014 #
1015 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
1016 #
1017
1018 conf = Configure(env)
1019
1020 if conf.CheckCHeader('alsa/asoundlib.h'):
1021     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
1022     env['SYSMIDI'] = 'ALSA Sequencer'
1023     subst_dict['%MIDITAG%'] = "seq"
1024     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1025 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1026     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1027     if env['GTKOSX']:
1028         # We need Carbon as well as the rest
1029         libraries['sysmidi'] = LibraryInfo (
1030                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1031     else:
1032         libraries['sysmidi'] = LibraryInfo (
1033                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1034     env['SYSMIDI'] = 'CoreMIDI'
1035     subst_dict['%MIDITAG%'] = "ardour"
1036     subst_dict['%MIDITYPE%'] = "coremidi"
1037 else:
1038     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."
1039     sys.exit (1)
1040
1041 env = conf.Finish()
1042
1043 if env['GTKOSX']:
1044     clearlooks_version = 'libs/clearlooks-newer'
1045 else:
1046     clearlooks_version = 'libs/clearlooks-older'
1047
1048 if env['SYSLIBS']:
1049
1050     syslibdeps = \
1051     {
1052         'sigc++-2.0'           : '2.0',
1053         'gtkmm-2.4'            : '2.8',
1054         'libgnomecanvasmm-2.6' : '2.12.0'
1055     }
1056
1057     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1058                     'CheckPKGVersion' : CheckPKGVersion })
1059
1060     for pkg, version in syslibdeps.iteritems():
1061         if not conf.CheckPKGVersion( pkg, version ):
1062             print '%s >= %s not found.' %(pkg, version)
1063             DependenciesRequiredMessage()
1064             Exit(1)
1065     
1066     env = conf.Finish()
1067     
1068     libraries['sigc2'] = LibraryInfo()
1069     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1070     libraries['glibmm2'] = LibraryInfo()
1071     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1072     libraries['cairomm'] = LibraryInfo()
1073     libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1074     libraries['gdkmm2'] = LibraryInfo()
1075     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1076     libraries['gtkmm2'] = LibraryInfo()
1077     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1078     libraries['atkmm'] = LibraryInfo()
1079     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1080     libraries['pangomm'] = LibraryInfo()
1081     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1082     libraries['libgnomecanvasmm'] = LibraryInfo()
1083     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1084
1085 #
1086 # cannot use system one for the time being
1087 #
1088     
1089     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1090                                     LIBPATH='#libs/libsndfile',
1091                                     CPPPATH=['#libs/libsndfile/src'])
1092
1093 #    libraries['libglademm'] = LibraryInfo()
1094 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1095
1096 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1097     libraries['soundtouch'] = LibraryInfo()
1098     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1099     # Comment the previous line and uncomment this for old versions of Debian:
1100     #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1101
1102     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1103                                             LIBPATH='#libs/appleutility',
1104                                             CPPPATH='#libs/appleutility')
1105     
1106     coredirs = [
1107         'templates',
1108         'manual'
1109     ]
1110     
1111     subdirs = [
1112         'libs/libsndfile',
1113         'libs/pbd',
1114         'libs/midi++2',
1115         'libs/ardour',
1116         'libs/vamp-sdk',
1117         'libs/vamp-plugins/',
1118     # these are unconditionally included but have
1119     # tests internally to avoid compilation etc
1120     # if VST is not set
1121         'libs/fst',
1122         'vst',
1123     # this is unconditionally included but has
1124     # tests internally to avoid compilation etc
1125     # if COREAUDIO is not set
1126         'libs/appleutility'
1127         ]
1128     
1129     gtk_subdirs = [
1130 #        'libs/flowcanvas',
1131         'libs/gtkmm2ext',
1132         'gtk2_ardour',
1133         clearlooks_version
1134         ]
1135
1136 else:
1137     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
1138                                     LIBPATH='#libs/sigc++2',
1139                                     CPPPATH='#libs/sigc++2')
1140     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
1141                                     LIBPATH='#libs/glibmm2',
1142                                     CPPPATH='#libs/glibmm2')
1143     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
1144                                     LIBPATH='#libs/gtkmm2/pango',
1145                                     CPPPATH='#libs/gtkmm2/pango')
1146     libraries['cairomm'] = LibraryInfo(LIBS='cairomm',
1147                                     LIBPATH='#libs/cairomm',
1148                                     CPPPATH='#libs/cairomm')
1149     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
1150                                      LIBPATH='#libs/gtkmm2/atk',
1151                                      CPPPATH='#libs/gtkmm2/atk')
1152     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
1153                                       LIBPATH='#libs/gtkmm2/gdk',
1154                                       CPPPATH='#libs/gtkmm2/gdk')
1155     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
1156                                      LIBPATH="#libs/gtkmm2/gtk",
1157                                      CPPPATH='#libs/gtkmm2/gtk/')
1158     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
1159                                                 LIBPATH='#libs/libgnomecanvasmm',
1160                                                 CPPPATH='#libs/libgnomecanvasmm')
1161     
1162     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
1163                                           LIBPATH='#libs/soundtouch',
1164                                           CPPPATH=['#libs', '#libs/soundtouch'])
1165     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1166                                     LIBPATH='#libs/libsndfile',
1167                                     CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
1168 #    libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
1169 #                                          LIBPATH='#libs/libglademm',
1170 #                                          CPPPATH='#libs/libglademm')
1171     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1172                                             LIBPATH='#libs/appleutility',
1173                                             CPPPATH='#libs/appleutility')
1174
1175     coredirs = [
1176         'templates',
1177         'manual'
1178     ]
1179     
1180     subdirs = [
1181         'libs/sigc++2',
1182         'libs/libsndfile',
1183         'libs/pbd',
1184         'libs/midi++2',
1185         'libs/ardour',
1186         'libs/vamp-sdk',
1187         'libs/vamp-plugins/',
1188     # these are unconditionally included but have
1189     # tests internally to avoid compilation etc
1190     # if VST is not set
1191         'libs/fst',
1192         'vst',
1193     # this is unconditionally included but has
1194     # tests internally to avoid compilation etc
1195     # if COREAUDIO is not set
1196         'libs/appleutility'
1197         ]
1198     
1199     gtk_subdirs = [
1200         'libs/glibmm2',
1201         'libs/gtkmm2/pango',
1202         'libs/gtkmm2/atk',
1203         'libs/gtkmm2/gdk',
1204         'libs/gtkmm2/gtk',
1205         'libs/libgnomecanvasmm',
1206         'libs/gtkmm2ext',
1207         'gtk2_ardour',
1208         clearlooks_version
1209         ]
1210
1211 #
1212 # * always build the LGPL control protocol lib, since we link against it from libardour
1213 # * ditto for generic MIDI
1214 # * tranzport & wiimote check whether they should build internally, but we need them here
1215 #   so that they are included in the tarball
1216 #
1217
1218 surface_subdirs = [ 'libs/surfaces/control_protocol',
1219                     'libs/surfaces/generic_midi',
1220                     'libs/surfaces/tranzport',
1221                     'libs/surfaces/mackie',
1222                     'libs/surfaces/powermate',
1223                     'libs/surfaces/wiimote'
1224                     ]
1225
1226 if env['SURFACES']:
1227     if have_libusb:
1228         env['TRANZPORT'] = 1
1229     else:
1230         env['TRANZPORT'] = 0
1231         print 'Disabled building Tranzport code because libusb could not be found'
1232
1233     if have_linux_input:
1234         env['POWERMATE'] = 1
1235     else:
1236         env['POWERMATE'] = 0
1237         print 'Disabled building Powermate code because linux/input.h could not be found'
1238
1239     if os.access ('libs/surfaces/sony9pin', os.F_OK):
1240         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1241 else:
1242     env['POWERMATE'] = 0
1243     env['TRANZPORT'] = 0
1244
1245 #
1246 # timestretch libraries
1247 #
1248
1249 timefx_subdirs = ['libs/soundtouch']
1250 if env['RUBBERBAND']:
1251     timefx_subdirs += ['libs/rubberband']
1252
1253 opts.Save('scache.conf', env)
1254 Help(opts.GenerateHelpText(env))
1255
1256 final_prefix = '$PREFIX'
1257
1258 if env['DESTDIR'] :
1259     install_prefix = '$DESTDIR/$PREFIX'
1260 else:
1261     install_prefix = env['PREFIX']
1262
1263 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1264 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1265 subst_dict['%PREFIX%'] = final_prefix;
1266
1267 if env['PREFIX'] == '/usr':
1268     final_config_prefix = '/etc'
1269 else:
1270     final_config_prefix = env['PREFIX'] + '/etc'
1271
1272 config_prefix = '$DESTDIR' + final_config_prefix
1273
1274 #
1275 # everybody needs this
1276 #
1277
1278 env.Merge ([ libraries['core'] ])
1279
1280
1281 #
1282 # i18n support
1283 #
1284
1285 conf = Configure (env)
1286 if env['NLS']:
1287     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1288     print 'Checking for internationalization support ...'
1289     have_gettext = conf.TryAction(Action('xgettext --version'))
1290     if have_gettext[0] != 1:
1291         nls_error += ' No xgettext command.'
1292         env['NLS'] = 0
1293     else:
1294         print "Found xgettext"
1295     
1296     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1297     if have_msgmerge[0] != 1:
1298         nls_error += ' No msgmerge command.'
1299         env['NLS'] = 0
1300     else:
1301         print "Found msgmerge"
1302     
1303     if not conf.CheckCHeader('libintl.h'):
1304         nls_error += ' No libintl.h.'
1305         env['NLS'] = 0
1306         
1307     if env['NLS'] == 0:
1308         print nls_error
1309     else:
1310         print "International version will be built."
1311 env = conf.Finish()
1312
1313 if env['NLS'] == 1:
1314     env.Append(CCFLAGS="-DENABLE_NLS")
1315
1316 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict use_flac')
1317
1318 #
1319 # the configuration file may be system dependent
1320 #
1321
1322 conf = env.Configure ()
1323
1324 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1325     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1326     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1327 else:
1328     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1329     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1330
1331 # posix_memalign available
1332 if not conf.CheckFunc('posix_memalign'):
1333     print 'Did not find posix_memalign(), using malloc'
1334     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1335
1336
1337 env = conf.Finish()
1338
1339 # Which GTK tooltips API
1340
1341 gtktestenv = env.Clone ()
1342 gtktestenv.Merge ([
1343         libraries['gtk2']
1344         ])
1345
1346 conf = gtktestenv.Configure ()
1347
1348 if conf.CheckFunc('gtk_widget_set_tooltip_text'):
1349     env.Append (CXXFLAGS='-DGTK_NEW_TOOLTIP_API')
1350
1351 conf.Finish ()
1352
1353
1354 # generate the per-user and system rc files from the same source
1355
1356 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1357
1358 # add to the substitution dictionary
1359
1360 subst_dict['%VERSION%'] = ardour_version[0:3]
1361 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1362 subst_dict['%REVISION_STRING%'] = ''
1363 if os.path.exists('.svn'):
1364     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1365
1366 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1367
1368 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1369 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1370                              [ Delete ('$PREFIX/etc/ardour2'),
1371                                Delete ('$PREFIX/lib/ardour2'),
1372                                Delete ('$PREFIX/bin/ardour2'),
1373                                Delete ('$PREFIX/share/ardour2')])
1374
1375 env.Alias('revision', the_revision)
1376 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
1377 env.Alias('uninstall', remove_ardour)
1378
1379 Default (sysrcbuild)
1380
1381 # source tarball
1382
1383 Precious (env['DISTTREE'])
1384
1385 env.Distribute (env['DISTTREE'],
1386                [ 'SConstruct', 
1387                   'COPYING', 'PACKAGER_README', 'README',
1388                   'ardour.rc.in',
1389                   'tools/config.guess',
1390                   'icons/icon/ardour_icon_mac_mask.png',
1391                   'icons/icon/ardour_icon_mac.png',
1392                   'icons/icon/ardour_icon_tango_16px_blue.png',
1393                   'icons/icon/ardour_icon_tango_16px_red.png',
1394                   'icons/icon/ardour_icon_tango_22px_blue.png',
1395                   'icons/icon/ardour_icon_tango_22px_red.png',
1396                   'icons/icon/ardour_icon_tango_32px_blue.png',
1397                   'icons/icon/ardour_icon_tango_32px_red.png',
1398                   'icons/icon/ardour_icon_tango_48px_blue.png',
1399                   'icons/icon/ardour_icon_tango_48px_red.png'
1400                   ] +
1401                 glob.glob ('ardour.1*') +
1402                 glob.glob ('libs/clearlooks-newer/*.c') +
1403                 glob.glob ('libs/clearlooks-newer/*.h') +
1404                 glob.glob ('libs/clearlooks-newer/SConscript')
1405                 )
1406
1407 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1408 env.Alias ('srctar', srcdist)
1409
1410 #
1411 # don't leave the distree around
1412 #
1413
1414 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1415 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1416
1417 #
1418 # Update revision info before going into subdirs
1419 #
1420
1421 create_stored_revision()
1422
1423 #
1424 # the subdirs
1425 #
1426
1427 for subdir in coredirs:
1428     SConscript (subdir + '/SConscript')
1429
1430 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1431     for subdir in sublistdir:
1432         SConscript (subdir + '/SConscript')
1433
1434 # cleanup
1435 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1436