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