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