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