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