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