Unify the canvases by moving groups around rather than using set_scrolling_region...
[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.5'
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  = "#ifndef __ardour_svn_revision_h__\n"
266             text += "#define __ardour_svn_revision_h__\n"
267             text += "static const char* ardour_svn_revision = \"" + rev + "\";\n";
268             text += "#endif\n"
269             print '============> writing svn revision info to svn_revision.h\n'
270             o = file ('svn_revision.h', 'w')
271             o.write (text)
272             o.close ()
273         except IOError:
274             print "Could not open svn_revision.h for writing\n"
275             sys.exit (-1)
276     else:
277         print "You cannot use \"scons revision\" on without using a checked out"
278         print "copy of the Ardour source code repository"
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         'aubio'                : '0.3.2'
457 }
458
459 def DependenciesRequiredMessage():
460         print 'You do not have the necessary dependencies required to build ardour'
461         print 'Please consult http://ardour.org/building for more information'
462
463 def CheckPKGConfig(context, version):
464     context.Message( 'Checking for pkg-config version >= %s... ' %version )
465     ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
466     context.Result( ret )
467     return ret
468
469 def CheckPKGVersion(context, name, version):
470     context.Message( 'Checking for %s... ' % name )
471     ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
472     context.Result( ret )
473     return ret
474
475 def CheckPKGExists(context, name):
476     context.Message ('Checking for %s...' % name)
477     ret = context.TryAction('pkg-config --exists %s' % name)[0]
478     context.Result (ret)
479     return ret
480
481 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
482                                        'CheckPKGVersion' : CheckPKGVersion })
483
484 # I think a more recent version is needed on win32
485 min_pkg_config_version = '0.8.0'
486
487 if not conf.CheckPKGConfig(min_pkg_config_version):
488      print 'pkg-config >= %s not found.' % min_pkg_config_version
489      Exit(1)
490
491 for pkg, version in deps.iteritems():
492         if not conf.CheckPKGVersion( pkg, version ):
493                 print '%s >= %s not found.' %(pkg, version)
494                 DependenciesRequiredMessage()
495                 Exit(1)
496
497 env = conf.Finish()
498
499 # ----------------------------------------------------------------------
500 # Construction environment setup
501 # ----------------------------------------------------------------------
502
503 libraries = { }
504
505 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
506
507 #libraries['sndfile'] = LibraryInfo()
508 #libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
509
510 libraries['lrdf'] = LibraryInfo()
511 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
512
513 libraries['raptor'] = LibraryInfo()
514 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
515
516 libraries['samplerate'] = LibraryInfo()
517 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
518
519 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
520
521 if conf.CheckPKGExists ('fftw3f'):
522     libraries['fftw3f'] = LibraryInfo()
523     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
524
525 if conf.CheckPKGExists ('fftw3'):
526     libraries['fftw3'] = LibraryInfo()
527     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
528
529 if conf.CheckPKGExists ('aubio'):
530     libraries['aubio'] = LibraryInfo()
531     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
532     env['AUBIO'] = 1
533 else:
534     env['AUBIO'] = 0
535
536 env = conf.Finish ()
537
538 if env['FFT_ANALYSIS']:
539         #
540         # Check for fftw3 header as well as the library
541         #
542
543         conf = Configure(libraries['fftw3'])
544
545         if conf.CheckHeader ('fftw3.h') == False:
546             print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
547             sys.exit (1)            
548         conf.Finish()
549
550 if env['FREESOUND']:
551         #
552         # Check for curl header as well as the library
553         #
554
555         libraries['curl'] = LibraryInfo()
556
557         conf = Configure(libraries['curl'])
558
559         if conf.CheckHeader ('curl/curl.h') == False:
560                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
561                 sys.exit (1)            
562         else:
563                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
564         conf.Finish()
565 else:
566         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
567
568 if env['LV2']:
569         conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion})
570         
571         if conf.CheckPKGVersion('slv2', '0.6.0'):
572                 libraries['slv2'] = LibraryInfo()
573                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
574                 env.Append (CCFLAGS="-DHAVE_LV2")
575         else:
576                 print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
577                 env['LV2'] = 0
578         conf.Finish()
579 else:
580         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
581
582 libraries['jack'] = LibraryInfo()
583 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
584
585 libraries['xml'] = LibraryInfo()
586 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
587
588 libraries['xslt'] = LibraryInfo()
589 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
590
591 libraries['glib2'] = LibraryInfo()
592 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
593 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
594 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
595 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
596
597 libraries['freetype2'] = LibraryInfo()
598 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
599
600 libraries['gtk2'] = LibraryInfo()
601 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
602
603 libraries['pango'] = LibraryInfo()
604 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
605
606 libraries['libgnomecanvas2'] = LibraryInfo()
607 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
608
609 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
610
611 # The Ardour Control Protocol Library
612
613 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
614                                       CPPPATH='#libs/surfaces/control_protocol')
615
616 # The Ardour backend/engine
617
618 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
619 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
620 libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
621 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
622
623
624 # SCons should really do this for us
625
626 conf = env.Configure ()
627
628 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
629 if have_cxx[0] != 1:
630     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
631     sys.exit (1)
632 else:
633     print "Congratulations, you have a functioning C++ compiler."
634
635 env = conf.Finish()
636
637
638 #
639 # Compiler flags and other system-dependent stuff
640 #
641
642 opt_flags = []
643 if env['GPROFILE'] == 1:
644     debug_flags = [ '-g', '-pg' ]
645 else:
646     debug_flags = [ '-g' ]
647
648 # guess at the platform, used to define compiler flags
649
650 config_guess = os.popen("tools/config.guess").read()[:-1]
651
652 config_cpu = 0
653 config_arch = 1
654 config_kernel = 2
655 config_os = 3
656 config = config_guess.split ("-")
657
658 print "system triple: " + config_guess
659
660 # Autodetect
661 if env['DIST_TARGET'] == 'auto':
662     if config[config_arch] == 'apple':
663         # The [.] matches to the dot after the major version, "." would match any character
664         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
665             env['DIST_TARGET'] = 'panther'
666         if re.search ("darwin8[.]", config[config_kernel]) != None:
667             env['DIST_TARGET'] = 'tiger'
668         else:
669             env['DIST_TARGET'] = 'leopard'
670     else:
671         if re.search ("x86_64", config[config_cpu]) != None:
672             env['DIST_TARGET'] = 'x86_64'
673         elif re.search("i[0-5]86", config[config_cpu]) != None:
674             env['DIST_TARGET'] = 'i386'
675         elif re.search("powerpc", config[config_cpu]) != None:
676             env['DIST_TARGET'] = 'powerpc'
677         else:
678             env['DIST_TARGET'] = 'i686'
679     print "\n*******************************"
680     print "detected DIST_TARGET = " + env['DIST_TARGET']
681     print "*******************************\n"
682
683
684 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
685     #
686     # Apple/PowerPC optimization options
687     #
688     # -mcpu=7450 does not reliably work with gcc 3.*
689     #
690     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
691         if config[config_arch] == 'apple':
692             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
693             # to support g3s but still have some optimization for above
694             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
695         else:
696             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
697     else:
698         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
699     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
700     opt_flags.extend (["-Os"])
701
702 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':
703     
704     build_host_supports_sse = 0
705     
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', 'svn_revision.h',
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 # the subdirs
1377 #
1378
1379 for subdir in coredirs:
1380     SConscript (subdir + '/SConscript')
1381
1382 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1383     for subdir in sublistdir:
1384         SConscript (subdir + '/SConscript')
1385
1386 # cleanup
1387 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1388