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