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