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