2d4651994d86c25a445ad6726042794243f4acd6
[ardour.git] / SConstruct
1 # -*- python -*-
2
3 #
4 # and there we have it, or do we?
5 #
6
7 import os
8 import os.path
9 import sys
10 import re
11 import shutil
12 import glob
13 import errno
14 import time
15 import platform
16 import string
17 import commands
18 from sets import Set
19 import SCons.Node.FS
20
21 SConsignFile()
22 EnsureSConsVersion(0, 96)
23
24 ardour_version = '3.0'
25
26 subst_dict = { }
27
28 #
29 # Command-line options
30 #
31
32 opts = Options('scache.conf')
33 opts.AddOptions(
34     ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
35     ('WINDOWS_KEY', 'Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key', 'Mod4'),
36     BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
37     BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
38     BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
39     BoolOption('OLDFONTS', 'Old school font sizes', 0),
40     BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
41     BoolOption('STL_DEBUG', 'Set to build with Standard Template Library Debugging', 0),
42     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
43     EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'leopard', 'none' ), ignorecase=2),
44     BoolOption('DMALLOC', 'Compile and link using the dmalloc library', 0),
45     BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic.  Might break compilation.  For pedants', 0),
46     BoolOption('FREESOUND', 'Include Freesound database lookup', 0),
47     BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
48     BoolOption('NLS', 'Set to turn on i18n support', 1),
49     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
50     BoolOption('SURFACES', 'Build support for control surfaces', 1),
51     BoolOption('WIIMOTE', 'Build the wiimote control surface', 0),
52     BoolOption('SYSLIBS', 'USE AT YOUR OWN RISK: CANCELS ALL SUPPORT FROM ARDOUR AUTHORS: Use existing system versions of various libraries instead of internal ones', 0),
53     BoolOption('UNIVERSAL', 'Compile as universal binary.  Requires that external libraries are already universal.', 0),
54     BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
55     BoolOption('VST', 'Compile with support for VST', 0),
56     BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 1),
57     BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
58     BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
59     BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
60     BoolOption('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1)
61 )
62
63 #----------------------------------------------------------------------
64 # a handy helper that provides a way to merge compile/link information
65 # from multiple different "environments"
66 #----------------------------------------------------------------------
67 #
68 class LibraryInfo(Environment):
69     def __init__(self,*args,**kw):
70         Environment.__init__ (self,*args,**kw)
71     
72     def Merge (self,others):
73         for other in others:
74             self.Append (LIBS = other.get ('LIBS',[]))
75             self.Append (LIBPATH = other.get ('LIBPATH', []))
76             self.Append (CPPPATH = other.get('CPPPATH', []))
77             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
78             self.Append (CCFLAGS = other.get('CCFLAGS', []))
79         self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
80         self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
81         #doing LINKFLAGS breaks -framework
82         #doing LIBS break link order dependency
83     
84     def ENV_update(self, src_ENV):
85         for k in src_ENV.keys():
86             if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
87                                                   'LIB', 'INCLUDE' ]:
88                 self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
89             else:
90                 self['ENV'][k]=src_ENV[k]
91
92 env = LibraryInfo (options = opts,
93                    CPPPATH = [ '.' ],
94                    VERSION = ardour_version,
95                    TARBALL='ardour-' + ardour_version + '.tar.bz2',
96                    DISTFILES = [ ],
97                    DISTTREE  = '#ardour-' + ardour_version,
98                    DISTCHECKDIR = '#ardour-' + ardour_version + '/check'
99                    )
100
101 env.ENV_update(os.environ)
102
103 #----------------------------------------------------------------------
104 # Builders
105 #----------------------------------------------------------------------
106
107 # Handy subst-in-file builder
108 #
109
110 def do_subst_in_file(targetfile, sourcefile, dict):
111     """Replace all instances of the keys of dict with their values.
112     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
113     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
114     """
115     try:
116         f = open(sourcefile, 'rb')
117         contents = f.read()
118         f.close()
119     except:
120         raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
121     for (k,v) in dict.items():
122         contents = re.sub(k, v, contents)
123     try:
124         f = open(targetfile, 'wb')
125         f.write(contents)
126         f.close()
127     except:
128         raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
129     return 0 # success
130
131 def subst_in_file(target, source, env):
132     if not env.has_key('SUBST_DICT'):
133         raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
134     d = dict(env['SUBST_DICT']) # copy it
135     for (k,v) in d.items():
136         if callable(v):
137             d[k] = env.subst(v())
138         elif SCons.Util.is_String(v):
139             d[k]=env.subst(v)
140         else:
141             raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
142     for (t,s) in zip(target, source):
143         return do_subst_in_file(str(t), str(s), d)
144
145 def subst_in_file_string(target, source, env):
146     """This is what gets printed on the console."""
147     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
148                       for (t,s) in zip(target, source)])
149
150 def subst_emitter(target, source, env):
151     """Add dependency from substituted SUBST_DICT to target.
152     Returns original target, source tuple unchanged.
153     """
154     d = env['SUBST_DICT'].copy() # copy it
155     for (k,v) in d.items():
156         if callable(v):
157             d[k] = env.subst(v())
158         elif SCons.Util.is_String(v):
159             d[k]=env.subst(v)
160     Depends(target, SCons.Node.Python.Value(d))
161     # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
162     return target, source
163
164 subst_action = Action (subst_in_file, subst_in_file_string)
165 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
166
167 #
168 # internationalization
169 #
170
171 # po_builder: builder function to copy po files to the parent directory while updating them
172 #
173 # first source:  .po file
174 # second source: .pot file
175 #
176
177 def po_builder(target,source,env):
178     os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
179     args = [ 'msgmerge',
180              '--update',
181              str(target[0]),
182              str(source[1])
183              ]
184     print 'Updating ' + str(target[0])
185     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
186
187 po_bld = Builder (action = po_builder)
188 env.Append(BUILDERS = {'PoBuild' : po_bld})
189
190 # mo_builder: builder function for (binary) message catalogs (.mo)
191 #
192 # first source:  .po file
193 #
194
195 def mo_builder(target,source,env):
196     args = [ 'msgfmt',
197              '-c',
198              '-o',
199              target[0].get_path(),
200              source[0].get_path()
201              ]
202     return os.spawnvp (os.P_WAIT, 'msgfmt', args)
203
204 mo_bld = Builder (action = mo_builder)
205 env.Append(BUILDERS = {'MoBuild' : mo_bld})
206
207 # pot_builder: builder function for message templates (.pot)
208 #
209 # source: list of C/C++ etc. files to extract messages from
210 #
211
212 def pot_builder(target,source,env):
213     args = [ 'xgettext',
214              '--keyword=_',
215              '--keyword=N_',
216              '--from-code=UTF-8',
217              '-o', target[0].get_path(),
218              "--default-domain=" + env['PACKAGE'],
219              '--copyright-holder="Paul Davis"' ]
220     args += [ src.get_path() for src in source ]
221     
222     return os.spawnvp (os.P_WAIT, 'xgettext', args)
223
224 pot_bld = Builder (action = pot_builder)
225 env.Append(BUILDERS = {'PotBuild' : pot_bld})
226
227 #
228 # utility function, not a builder
229 #
230
231 def i18n (buildenv, sources, installenv):
232     domain = buildenv['PACKAGE']
233     potfile = buildenv['POTFILE']
234     
235     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
236     
237     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
238     languages = [ po.replace ('.po', '') for po in p_oze ]
239     
240     for po_file in p_oze:
241         buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
242         mo_file = po_file.replace (".po", ".mo")
243         installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
244         installenv.Alias ('msgupdate', buildenv.MoBuild (mo_file, po_file))
245     
246     for lang in languages:
247         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
248         moname = domain + '.mo'
249         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
250
251
252 def fetch_svn_revision (path):
253     cmd = "LANG= "
254     cmd += "svn info "
255     cmd += path
256     cmd += " | awk '/^Revision:/ { print $2}'"
257     return commands.getoutput (cmd)
258
259 def fetch_git_revision (path):
260     cmd = "LANG= "
261     cmd += "git log --abbrev HEAD^..HEAD "
262     cmd += path
263     output = commands.getoutput (cmd)
264     output = output.splitlines ()
265
266     rev = output[0].replace ("commit", "git")[0:10]
267     for line in output:
268         try:
269             if "git-svn-id" in line:
270                 line = line.split('@')
271                 line = line[1].split(' ')
272                 rev = line[0]
273         except:
274             pass
275
276     return rev
277
278 def create_stored_revision (target = None, source = None, env = None):
279     rev = ""
280     if os.path.exists('.svn'):    
281         rev = fetch_svn_revision ('.');
282     elif os.path.exists('.git'):
283         rev = fetch_git_revision ('.');
284     elif os.path.exists('libs/ardour/svn_revision.cc'):
285         print "Using packaged svn revision"
286         return
287     else:
288         if not os.path.exists('libs/ardour/ardour/svn_revision.h'):    
289             print "This release of ardour is missing libs/ardour/ardour/svn_revision.h. Blame the packager."
290             sys.exit (-1)
291
292     try:
293         text  = "#include <ardour/svn_revision.h>\n"
294         text += "namespace ARDOUR {\n";
295         text += "extern const char* svn_revision = \"" + rev + "\";\n";
296         text += "}\n";
297         print '============> writing svn revision info to libs/ardour/svn_revision.cc\n'
298         o = file ('libs/ardour/svn_revision.cc', 'w')
299         o.write (text)
300         o.close ()
301     except IOError:
302         print "Could not open libs/ardour/svn_revision.cc for writing\n"
303         sys.exit (-1)
304
305 #
306 # A generic builder for version.cc files
307 #
308 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
309 # note: assumes one source files, the header that declares the version variables
310 #
311
312 def version_builder (target, source, env):
313
314     text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
315     text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
316     text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
317     
318     try:
319         o = file (target[0].get_path(), 'w')
320         o.write (text)
321         o.close ()
322     except IOError:
323         print "Could not open", target[0].get_path(), " for writing\n"
324         sys.exit (-1)
325
326     text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
327     text += "#define __" + env['DOMAIN'] + "_version_h__\n"
328     text += "extern const char* " + env['DOMAIN'] + "_revision;\n"
329     text += "extern int " + env['DOMAIN'] + "_major_version;\n"
330     text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
331     text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
332     text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
333     
334     try:
335         o = file (target[1].get_path(), 'w')
336         o.write (text)
337         o.close ()
338     except IOError:
339         print "Could not open", target[1].get_path(), " for writing\n"
340         sys.exit (-1)
341         
342     return None
343
344 version_bld = Builder (action = version_builder)
345 env.Append (BUILDERS = {'VersionBuild' : version_bld})
346
347 #
348 # a builder that makes a hard link from the 'source' executable to a name with
349 # a "build ID" based on the most recent CVS activity that might be reasonably
350 # related to version activity. this relies on the idea that the SConscript
351 # file that builds the executable is updated with new version info and committed
352 # to the source code repository whenever things change.
353 #
354
355 def versioned_builder(target,source,env):
356     w, r = os.popen2( "LANG= svn info | awk '/^Revision:/ { print $2}'")
357     
358     last_revision = r.readline().strip()
359     w.close()
360     r.close()
361     if last_revision == "":
362         print "No SVN info found - versioned executable cannot be built"
363         return -1
364     
365     print "The current build ID is " + last_revision
366     
367     tagged_executable = source[0].get_path() + '-' + last_revision
368     
369     if os.path.exists (tagged_executable):
370         print "Replacing existing executable with the same build tag."
371         os.unlink (tagged_executable)
372     
373     return os.link (source[0].get_path(), tagged_executable)
374
375 verbuild = Builder (action = versioned_builder)
376 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
377
378 #
379 # source tar file builder
380 #
381
382 def distcopy (target, source, env):
383     treedir = str (target[0])
384     
385     try:
386         os.mkdir (treedir)
387     except OSError, (errnum, strerror):
388         if errnum != errno.EEXIST:
389             print 'mkdir ', treedir, ':', strerror
390     
391     cmd = 'tar cf - '
392     #
393     # we don't know what characters might be in the file names
394     # so quote them all before passing them to the shell
395     #
396     all_files = ([ str(s) for s in source ])
397     cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
398     cmd += ' | (cd ' + treedir + ' && tar xf -)'
399     p = os.popen (cmd)
400     return p.close ()
401
402 def tarballer (target, source, env):
403     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'" + " --exclude .svn --exclude '.svn/*'"
404     print 'running ', cmd, ' ... '
405     p = os.popen (cmd)
406     return p.close ()
407
408 dist_bld = Builder (action = distcopy,
409                     target_factory = SCons.Node.FS.default_fs.Entry,
410                     source_factory = SCons.Node.FS.default_fs.Entry,
411                     multi = 1)
412
413 tarball_bld = Builder (action = tarballer,
414                        target_factory = SCons.Node.FS.default_fs.Entry,
415                        source_factory = SCons.Node.FS.default_fs.Entry)
416
417 env.Append (BUILDERS = {'Distribute' : dist_bld})
418 env.Append (BUILDERS = {'Tarball' : tarball_bld})
419
420 #
421 # Make sure they know what they are doing
422 #
423
424 if env['VST']:
425     if os.path.isfile('.personal_use_only'):
426         print "Enabling VST support. Note that distributing a VST-enabled ardour\nis a violation of several different licences.\nBuild with VST=false if you intend to distribute ardour to others."
427     else:
428         sys.stdout.write ("Are you building Ardour for personal use (rather than distribution to others)? [no]: ")
429         answer = sys.stdin.readline ()
430         answer = answer.rstrip().strip()
431         if answer == "yes" or answer == "y":
432             fh = open('.personal_use_only', 'w')
433             fh.close()
434             print "OK, VST support will be enabled"
435         else:
436             print 'You cannot build Ardour with VST support for distribution to others.\nIt is a violation of several different licenses. Build with VST=false.'
437             sys.exit (-1);
438 else:
439     if os.path.isfile('.personal_use_only'):
440         os.remove('.personal_use_only')
441
442 ####################
443 # push environment
444 ####################
445
446 def pushEnvironment(context):
447     if os.environ.has_key('PATH'):
448         context.Append(PATH = os.environ['PATH'])
449         
450     if os.environ.has_key('PKG_CONFIG_PATH'):
451         context.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
452             
453     if os.environ.has_key('CC'):
454         context['CC'] = os.environ['CC']
455                 
456     if os.environ.has_key('CXX'):
457         context['CXX'] = os.environ['CXX']
458
459     if os.environ.has_key('DISTCC_HOSTS'):
460         context['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
461         context['ENV']['HOME'] = os.environ['HOME']
462
463 pushEnvironment (env)
464
465 #######################
466 # Dependency Checking #
467 #######################
468
469 deps = \
470 {
471         'glib-2.0'             : '2.10.1',
472         'gthread-2.0'          : '2.10.1',
473         'gtk+-2.0'             : '2.12.1',
474         'libxml-2.0'           : '2.6.0',
475         'samplerate'           : '0.1.0',
476         'raptor'               : '1.4.2',
477         'lrdf'                 : '0.4.0',
478         'jack'                 : '0.109.0',
479         'libgnomecanvas-2.0'   : '2.0',
480         'aubio'                : '0.3.2',
481         'ogg'                  : '1.1.2',
482         'flac'                 : '1.2.1',
483         'sndfile'              : '1.0.18'
484 }
485
486 def DependenciesRequiredMessage():
487         print 'You do not have the necessary dependencies required to build ardour'
488         print 'Please consult http://ardour.org/building for more information'
489
490 def CheckPKGConfig(context, version):
491     context.Message( 'Checking for pkg-config version >= %s... ' %version )
492     ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
493     context.Result( ret )
494     return ret
495
496 def CheckPKGVersion(context, name, version):
497     context.Message( 'Checking for %s... ' % name )
498     ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
499     context.Result( ret )
500     return ret
501
502 def CheckPKGExists(context, name):
503     context.Message ('Checking for %s...' % name)
504     ret = context.TryAction('pkg-config --exists %s' % name)[0]
505     context.Result (ret)
506     return ret
507
508 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
509                                        'CheckPKGVersion' : CheckPKGVersion })
510
511 # I think a more recent version is needed on win32
512 min_pkg_config_version = '0.8.0'
513
514 if not conf.CheckPKGConfig(min_pkg_config_version):
515      print 'pkg-config >= %s not found.' % min_pkg_config_version
516      Exit(1)
517
518 for pkg, version in deps.iteritems():
519         if not conf.CheckPKGVersion( pkg, version ):
520                 print '%s >= %s not found.' %(pkg, version)
521                 DependenciesRequiredMessage()
522                 Exit(1)
523
524 env = conf.Finish()
525
526 # ----------------------------------------------------------------------
527 # Construction environment setup
528 # ----------------------------------------------------------------------
529
530 libraries = { }
531
532 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
533
534 libraries['sndfile'] = LibraryInfo()
535 libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
536
537 libraries['lrdf'] = LibraryInfo()
538 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
539
540 libraries['raptor'] = LibraryInfo()
541 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
542
543 libraries['samplerate'] = LibraryInfo()
544 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
545
546 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
547
548 if conf.CheckPKGExists ('fftw3f'):
549     libraries['fftw3f'] = LibraryInfo()
550     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
551
552 if conf.CheckPKGExists ('fftw3'):
553     libraries['fftw3'] = LibraryInfo()
554     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
555
556 if conf.CheckPKGExists ('aubio'):
557     libraries['aubio'] = LibraryInfo()
558     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
559     env['AUBIO'] = 1
560 else:
561     env['AUBIO'] = 0
562
563 env = conf.Finish ()
564
565 #
566 # Check for fftw3 header as well as the library
567 #
568
569 conf = Configure(libraries['fftw3'])
570
571 if conf.CheckHeader ('fftw3.h') == False:
572     print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
573     sys.exit (1)            
574 conf.Finish()
575
576 if env['FREESOUND']:
577         #
578         # Check for curl header as well as the library
579         #
580
581         libraries['curl'] = LibraryInfo()
582
583         conf = Configure(libraries['curl'])
584
585         if conf.CheckHeader ('curl/curl.h') == False:
586                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
587                 sys.exit (1)            
588         else:
589                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
590         conf.Finish()
591 else:
592         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
593
594 if env['LV2']:
595         conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion})
596         
597         if conf.CheckPKGVersion('slv2', '0.6.4'):
598                 libraries['slv2'] = LibraryInfo()
599                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
600                 env.Append (CCFLAGS="-DHAVE_LV2")
601         else:
602                 print 'LV2 support is not enabled (SLV2 not found or older than 0.6.4 (svn))'
603                 env['LV2'] = 0
604         conf.Finish()
605 else:
606         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
607
608 if not env['WIIMOTE']:
609         print 'WIIMOTE not enabled. Build with \'scons WIIMOTE=1\' to enable support.'
610
611 libraries['jack'] = LibraryInfo()
612 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
613
614 libraries['xml'] = LibraryInfo()
615 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
616
617 libraries['xslt'] = LibraryInfo()
618 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
619
620 libraries['uuid'] = LibraryInfo()
621 libraries['uuid'].ParseConfig('pkg-config --cflags --libs uuid')
622
623 libraries['glib2'] = LibraryInfo()
624 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
625 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
626 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
627 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
628
629 libraries['freetype2'] = LibraryInfo()
630 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
631
632 libraries['gtk2'] = LibraryInfo()
633 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
634
635 libraries['pango'] = LibraryInfo()
636 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
637
638 libraries['pangocairo'] = LibraryInfo()
639 libraries['pangocairo'].ParseConfig ('pkg-config --cflags --libs pangocairo')
640
641 libraries['libgnomecanvas2'] = LibraryInfo()
642 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
643
644 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
645
646 # The Ardour Control Protocol Library
647
648 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
649                                       CPPPATH='#libs/surfaces/control_protocol')
650
651 # The Ardour backend/engine
652
653 libraries['ardour']    = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
654 libraries['midi++2']   = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
655 libraries['smf']       = LibraryInfo (LIBS='smf', LIBPATH='#libs/evoral/src/libsmf', CPPPATH='#libs/evoral/src/libsmf/')
656 libraries['evoral']    = LibraryInfo (LIBS='evoral', LIBPATH='#libs/evoral', CPPPATH='#libs/evoral')
657 libraries['pbd']       = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
658 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
659
660
661 # SCons should really do this for us
662
663 conf = env.Configure ()
664
665 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
666 if have_cxx[0] != 1:
667     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
668     sys.exit (1)
669 else:
670     print "Congratulations, you have a functioning C++ compiler."
671
672 env = conf.Finish()
673
674
675 #
676 # Compiler flags and other system-dependent stuff
677 #
678
679 opt_flags = []
680 if env['GPROFILE'] == 1:
681     debug_flags = [ '-O0', '-g', '-pg' ]
682 else:
683     debug_flags = [ '-O0', '-g' ]
684
685 # guess at the platform, used to define compiler flags
686
687 config_guess = os.popen("tools/config.guess").read()[:-1]
688
689 config_cpu = 0
690 config_arch = 1
691 config_kernel = 2
692 config_os = 3
693 config = config_guess.split ("-")
694
695 print "system triple: " + config_guess
696
697 # Autodetect
698 if env['DIST_TARGET'] == 'auto':
699     if config[config_arch] == 'apple':
700         # The [.] matches to the dot after the major version, "." would match any character
701         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
702             env['DIST_TARGET'] = 'panther'
703         if re.search ("darwin8[.]", config[config_kernel]) != None:
704             env['DIST_TARGET'] = 'tiger'
705         else:
706             env['DIST_TARGET'] = 'leopard'
707     else:
708         if re.search ("x86_64", config[config_cpu]) != None:
709             env['DIST_TARGET'] = 'x86_64'
710         elif re.search("i[0-5]86", config[config_cpu]) != None:
711             env['DIST_TARGET'] = 'i386'
712         elif re.search("powerpc", config[config_cpu]) != None:
713             env['DIST_TARGET'] = 'powerpc'
714         else:
715             env['DIST_TARGET'] = 'i686'
716     print "\n*******************************"
717     print "detected DIST_TARGET = " + env['DIST_TARGET']
718     print "*******************************\n"
719
720
721 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
722     #
723     # Apple/PowerPC optimization options
724     #
725     # -mcpu=7450 does not reliably work with gcc 3.*
726     #
727     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
728         if config[config_arch] == 'apple':
729             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
730             # to support g3s but still have some optimization for above
731             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
732         else:
733             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
734     else:
735         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
736     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
737     opt_flags.extend (["-Os"])
738
739 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':
740     
741     build_host_supports_sse = 0
742     
743     #
744     # ARCH_X86 means anything in the x86 family from i386 to x86_64
745     # USE_X86_64_ASM is used to distingush 32 and 64 bit assembler
746     #
747
748     if (re.search ("(i[0-9]86|x86_64)", config[config_cpu]) != None):
749         debug_flags.append ("-DARCH_X86")
750         opt_flags.append ("-DARCH_X86")
751     
752     if config[config_kernel] == 'linux' :
753         
754         if env['DIST_TARGET'] != 'i386':
755             
756             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
757             x86_flags = flag_line.split (": ")[1:][0].split ()
758             
759             if "mmx" in x86_flags:
760                 opt_flags.append ("-mmmx")
761             if "sse" in x86_flags:
762                 build_host_supports_sse = 1
763             if "3dnow" in x86_flags:
764                 opt_flags.append ("-m3dnow")
765             
766             if config[config_cpu] == "i586":
767                 opt_flags.append ("-march=i586")
768             elif config[config_cpu] == "i686":
769                 opt_flags.append ("-march=i686")
770     
771     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
772         opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
773         debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
774 # end of processor-specific section
775
776 # optimization section
777 if env['FPU_OPTIMIZATION']:
778     if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
779         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
780         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
781         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
782     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
783         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
784         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
785         if env['DIST_TARGET'] == 'x86_64':
786             opt_flags.append ("-DUSE_X86_64_ASM")
787             debug_flags.append ("-DUSE_X86_64_ASM")
788         if build_host_supports_sse != 1:
789             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)"
790 # end optimization section
791
792 # handle x86/x86_64 libdir properly
793
794 if env['DIST_TARGET'] == 'x86_64':
795     env['LIBDIR']='lib64'
796 else:
797     env['LIBDIR']='lib'
798
799 #
800 # a single way to test if we're on OS X
801 #
802
803 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
804     env['IS_OSX'] = 1
805     # force tiger or later, to avoid issues on PPC which defaults
806     # back to 10.1 if we don't tell it otherwise.
807     env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
808
809     if env['DIST_TARGET'] == 'leopard':
810         # need this to really build against the 10.4 SDK when building on leopard
811         # ideally this would be configurable, but lets just do that later when we need it
812         env.Append(CCFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
813         env.Append(LINKFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
814
815 else:
816     env['IS_OSX'] = 0
817
818 #
819 # save off guessed arch element in an env
820 #
821 env.Append(CONFIG_ARCH=config[config_arch])
822
823
824 #
825 # ARCH="..." overrides all
826 #
827
828 if env['ARCH'] != '':
829     opt_flags = env['ARCH'].split()
830
831 #
832 # prepend boiler plate optimization flags
833 #
834
835 opt_flags[:0] = [
836     "-O3",
837     "-fomit-frame-pointer",
838     "-ffast-math",
839     "-fstrength-reduce",
840     "-pipe"
841     ]
842
843 if env['DEBUG'] == 1:
844     env.Append(CCFLAGS=" ".join (debug_flags))
845     env.Append(LINKFLAGS=" ".join (debug_flags))
846 else:
847     env.Append(CCFLAGS=" ".join (opt_flags))
848     env.Append(LINKFLAGS=" ".join (opt_flags))
849
850 if env['STL_DEBUG'] == 1:
851     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
852
853 if env['UNIVERSAL'] == 1:
854     env.Append(CCFLAGS="-arch i386 -arch ppc")
855     env.Append(LINKFLAGS="-arch i386 -arch ppc")
856
857
858 #
859 # warnings flags
860 #
861
862 env.Append(CCFLAGS="-Wall")
863 env.Append(CXXFLAGS="-Woverloaded-virtual")
864
865 if env['EXTRA_WARN']:
866     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
867     env.Append(CXXFLAGS="-ansi")
868 #    env.Append(CFLAGS="-iso")
869
870 #
871 # fix scons nitpickiness on APPLE
872 #
873
874
875 def prep_libcheck(topenv, libinfo):
876     if topenv['IS_OSX']:
877         #
878         # rationale: GTK-Quartz uses jhbuild and installs to ~/gtk/inst by default.
879         # All libraries needed should be built against this location
880
881         if topenv['GTKOSX']:
882             GTKROOT = os.path.expanduser ('~/gtk/inst')
883             libinfo.Append(CPPPATH= GTKROOT + "/include", LIBPATH= GTKROOT + "/lib")
884             libinfo.Append(CXXFLAGS="-I" + GTKROOT + "/include", LINKFLAGS="-L" + GTKROOT + "/lib")
885
886                 
887
888 prep_libcheck(env, env)
889
890 #
891 # these are part of the Ardour source tree because they are C++
892
893
894 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
895                                  LIBPATH='#libs/vamp-sdk',
896                                  CPPPATH='#libs/vamp-sdk')
897 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
898                                  LIBPATH='#libs/vamp-sdk',
899                                  CPPPATH='#libs/vamp-sdk')
900
901 env['RUBBERBAND'] = False
902
903 conf = Configure (env)
904
905 if conf.CheckHeader ('fftw3.h'):
906     env['RUBBERBAND'] = True
907     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
908                                            LIBPATH='#libs/rubberband',
909                                            CPPPATH='#libs/rubberband',
910                                            CCFLAGS='-DUSE_RUBBERBAND')
911 else:
912     print ""
913     print "-------------------------------------------------------------------------"
914     print "You do not have the FFTW single-precision development package installed."
915     print "This prevents Ardour from using the Rubberband library for timestretching"
916     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
917     print "pitchshifting will not be available."
918     print "-------------------------------------------------------------------------"
919     print ""
920
921 conf.Finish()
922
923 #
924 # Check for libusb
925
926 libraries['usb'] = LibraryInfo ()
927 prep_libcheck(env, libraries['usb'])
928
929 conf = Configure (libraries['usb'])
930 if conf.CheckLib ('usb', 'usb_interrupt_write'):
931     have_libusb = True
932 else:
933     have_libusb = False
934
935 # check for linux/input.h while we're at it for powermate
936 if conf.CheckHeader('linux/input.h'):
937     have_linux_input = True
938 else:
939     have_linux_input = False
940
941 libraries['usb'] = conf.Finish ()
942
943 #
944 # Check for wiimote dependencies
945
946 if env['WIIMOTE']:
947     wiimoteConf = env.Configure ( )
948     if not wiimoteConf.CheckHeader('cwiid.h'):
949         print 'WIIMOTE configured but you are missing libcwiid!'
950         sys.exit(1)
951     if not wiimoteConf.CheckHeader('bluetooth/bluetooth.h'):
952         print 'WIIMOTE configured but you are missing the libbluetooth headers which you need to compile wiimote support!'
953         sys.exit(1)
954     wiimoteConf.Finish()
955
956
957 #
958 # Check for FLAC
959
960 libraries['flac'] = LibraryInfo ()
961 prep_libcheck(env, libraries['flac'])
962 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
963
964 #
965 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
966 #                since the version of libsndfile we have internally does not support
967 #                the new API that libFLAC has adopted
968 #
969
970 conf = Configure (libraries['flac'])
971 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
972     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
973     use_flac = True
974 else:
975     use_flac = False
976     
977 libraries['flac'] = conf.Finish ()
978
979 # or if that fails...
980 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
981
982 # boost (we don't link against boost, just use some header files)
983
984 libraries['boost'] = LibraryInfo ()
985 prep_libcheck(env, libraries['boost'])
986 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
987 conf = Configure (libraries['boost'])
988 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
989         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."
990         sys.exit (1)
991     
992 libraries['boost'] = conf.Finish ()
993
994 #
995 # Check for liblo
996
997 libraries['lo'] = LibraryInfo ()
998 prep_libcheck(env, libraries['lo'])
999
1000 conf = Configure (libraries['lo'])
1001 if conf.CheckLib ('lo', 'lo_server_new') == False:
1002     print "liblo does not appear to be installed."
1003     env['HAVE_LIBLO'] = False
1004 else:
1005     env['HAVE_LIBLO'] = True
1006
1007 libraries['lo'] = conf.Finish ()
1008
1009 #
1010 # Check for dmalloc
1011
1012 libraries['dmalloc'] = LibraryInfo ()
1013 prep_libcheck(env, libraries['dmalloc'])
1014
1015 #
1016 # look for the threaded version
1017 #
1018
1019 conf = Configure (libraries['dmalloc'])
1020 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
1021     have_libdmalloc = True
1022 else:
1023     have_libdmalloc = False
1024
1025 libraries['dmalloc'] = conf.Finish ()
1026
1027 #
1028 # ensure FREEDESKTOP target is doable..
1029 #
1030
1031 conf = env.Configure ()
1032 if env['FREEDESKTOP']:
1033         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
1034         if have_update_mime_database[0] != 1:
1035                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
1036                 env['FREEDESKTOP'] = 0
1037         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
1038         if have_gtk_update_icon_cache[0] != 1:
1039                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
1040                 env['FREEDESKTOP'] = 0
1041         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
1042         if have_update_desktop_database[0] != 1:
1043                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
1044                 env['FREEDESKTOP'] = 0
1045 env = conf.Finish()
1046
1047 #
1048 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
1049 #
1050
1051 conf = Configure(env)
1052     
1053 # ALSA, for engine dialog
1054 libraries['asound'] = LibraryInfo ()
1055
1056 if conf.CheckCHeader('alsa/asoundlib.h'):
1057     libraries['asound'].ParseConfig('pkg-config --cflags --libs alsa')
1058
1059 if conf.CheckCHeader('jack/midiport.h'):
1060     libraries['sysmidi'] = LibraryInfo (LIBS='jack')
1061     env['SYSMIDI'] = 'JACK MIDI'
1062     subst_dict['%MIDITAG%'] = "control"
1063     subst_dict['%MIDITYPE%'] = "jack"
1064     env.Append(CCFLAGS=" -DWITH_JACK_MIDI")
1065     print "Using JACK MIDI"
1066 elif conf.CheckCHeader('alsa/asoundlib.h'):
1067     libraries['sysmidi'] = LibraryInfo ()
1068     libraries['sysmidi'].ParseConfig('pkg-config --cflags --libs alsa')
1069     env['SYSMIDI'] = 'ALSA Sequencer'
1070     subst_dict['%MIDITAG%'] = "seq"
1071     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1072     print "Using ALSA MIDI"
1073 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1074     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1075     if env['GTKOSX']:
1076         # We need Carbon as well as the rest
1077         libraries['sysmidi'] = LibraryInfo (
1078                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1079     else:
1080         libraries['sysmidi'] = LibraryInfo (
1081                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1082     env['SYSMIDI'] = 'CoreMIDI'
1083     subst_dict['%MIDITAG%'] = "ardour"
1084     subst_dict['%MIDITYPE%'] = "coremidi"
1085 else:
1086     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."
1087     sys.exit (1)
1088
1089 env = conf.Finish()
1090
1091 if env['GTKOSX']:
1092     clearlooks_version = 'libs/clearlooks-newer'
1093 else:
1094     clearlooks_version = 'libs/clearlooks-older'
1095
1096 if env['SYSLIBS']:
1097
1098     syslibdeps = \
1099     {
1100         'sigc++-2.0'           : '2.0',
1101         'gtkmm-2.4'            : '2.8',
1102         'libgnomecanvasmm-2.6' : '2.12.0'
1103     }
1104
1105     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1106                     'CheckPKGVersion' : CheckPKGVersion })
1107
1108     for pkg, version in syslibdeps.iteritems():
1109         if not conf.CheckPKGVersion( pkg, version ):
1110             print '%s >= %s not found.' %(pkg, version)
1111             DependenciesRequiredMessage()
1112             Exit(1)
1113     
1114     env = conf.Finish()
1115     
1116     libraries['sigc2'] = LibraryInfo()
1117     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1118     libraries['glibmm2'] = LibraryInfo()
1119     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-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['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