Fix some confusion about relative / non-relative port names. Add some asserts to...
[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.2'):
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.0)'
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['evoral'] = LibraryInfo (LIBS='evoral', LIBPATH='#libs/evoral', CPPPATH='#libs/evoral')
656 libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
657 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
658
659
660 # SCons should really do this for us
661
662 conf = env.Configure ()
663
664 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
665 if have_cxx[0] != 1:
666     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
667     sys.exit (1)
668 else:
669     print "Congratulations, you have a functioning C++ compiler."
670
671 env = conf.Finish()
672
673
674 #
675 # Compiler flags and other system-dependent stuff
676 #
677
678 opt_flags = []
679 if env['GPROFILE'] == 1:
680     debug_flags = [ '-g', '-pg' ]
681 else:
682     debug_flags = [ '-g' ]
683
684 # guess at the platform, used to define compiler flags
685
686 config_guess = os.popen("tools/config.guess").read()[:-1]
687
688 config_cpu = 0
689 config_arch = 1
690 config_kernel = 2
691 config_os = 3
692 config = config_guess.split ("-")
693
694 print "system triple: " + config_guess
695
696 # Autodetect
697 if env['DIST_TARGET'] == 'auto':
698     if config[config_arch] == 'apple':
699         # The [.] matches to the dot after the major version, "." would match any character
700         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
701             env['DIST_TARGET'] = 'panther'
702         if re.search ("darwin8[.]", config[config_kernel]) != None:
703             env['DIST_TARGET'] = 'tiger'
704         else:
705             env['DIST_TARGET'] = 'leopard'
706     else:
707         if re.search ("x86_64", config[config_cpu]) != None:
708             env['DIST_TARGET'] = 'x86_64'
709         elif re.search("i[0-5]86", config[config_cpu]) != None:
710             env['DIST_TARGET'] = 'i386'
711         elif re.search("powerpc", config[config_cpu]) != None:
712             env['DIST_TARGET'] = 'powerpc'
713         else:
714             env['DIST_TARGET'] = 'i686'
715     print "\n*******************************"
716     print "detected DIST_TARGET = " + env['DIST_TARGET']
717     print "*******************************\n"
718
719
720 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
721     #
722     # Apple/PowerPC optimization options
723     #
724     # -mcpu=7450 does not reliably work with gcc 3.*
725     #
726     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
727         if config[config_arch] == 'apple':
728             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
729             # to support g3s but still have some optimization for above
730             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
731         else:
732             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
733     else:
734         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
735     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
736     opt_flags.extend (["-Os"])
737
738 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':
739     
740     build_host_supports_sse = 0
741     
742     #
743     # ARCH_X86 means anything in the x86 family from i386 to x86_64
744     # USE_X86_64_ASM is used to distingush 32 and 64 bit assembler
745     #
746
747     if (re.search ("(i[0-9]86|x86_64)", config[config_cpu]) != None):
748         debug_flags.append ("-DARCH_X86")
749         opt_flags.append ("-DARCH_X86")
750     
751     if config[config_kernel] == 'linux' :
752         
753         if env['DIST_TARGET'] != 'i386':
754             
755             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
756             x86_flags = flag_line.split (": ")[1:][0].split ()
757             
758             if "mmx" in x86_flags:
759                 opt_flags.append ("-mmmx")
760             if "sse" in x86_flags:
761                 build_host_supports_sse = 1
762             if "3dnow" in x86_flags:
763                 opt_flags.append ("-m3dnow")
764             
765             if config[config_cpu] == "i586":
766                 opt_flags.append ("-march=i586")
767             elif config[config_cpu] == "i686":
768                 opt_flags.append ("-march=i686")
769     
770     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
771         opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
772         debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
773 # end of processor-specific section
774
775 # optimization section
776 if env['FPU_OPTIMIZATION']:
777     if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
778         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
779         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
780         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
781     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
782         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
783         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
784         if env['DIST_TARGET'] == 'x86_64':
785             opt_flags.append ("-DUSE_X86_64_ASM")
786             debug_flags.append ("-DUSE_X86_64_ASM")
787         if build_host_supports_sse != 1:
788             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)"
789 # end optimization section
790
791 # handle x86/x86_64 libdir properly
792
793 if env['DIST_TARGET'] == 'x86_64':
794     env['LIBDIR']='lib64'
795 else:
796     env['LIBDIR']='lib'
797
798 #
799 # a single way to test if we're on OS X
800 #
801
802 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
803     env['IS_OSX'] = 1
804     # force tiger or later, to avoid issues on PPC which defaults
805     # back to 10.1 if we don't tell it otherwise.
806     env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
807
808     if env['DIST_TARGET'] == 'leopard':
809         # need this to really build against the 10.4 SDK when building on leopard
810         # ideally this would be configurable, but lets just do that later when we need it
811         env.Append(CCFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
812         env.Append(LINKFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
813
814 else:
815     env['IS_OSX'] = 0
816
817 #
818 # save off guessed arch element in an env
819 #
820 env.Append(CONFIG_ARCH=config[config_arch])
821
822
823 #
824 # ARCH="..." overrides all
825 #
826
827 if env['ARCH'] != '':
828     opt_flags = env['ARCH'].split()
829
830 #
831 # prepend boiler plate optimization flags
832 #
833
834 opt_flags[:0] = [
835     "-O3",
836     "-fomit-frame-pointer",
837     "-ffast-math",
838     "-fstrength-reduce",
839     "-pipe"
840     ]
841
842 if env['DEBUG'] == 1:
843     env.Append(CCFLAGS=" ".join (debug_flags))
844     env.Append(LINKFLAGS=" ".join (debug_flags))
845 else:
846     env.Append(CCFLAGS=" ".join (opt_flags))
847     env.Append(LINKFLAGS=" ".join (opt_flags))
848
849 if env['STL_DEBUG'] == 1:
850     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
851
852 if env['UNIVERSAL'] == 1:
853     env.Append(CCFLAGS="-arch i386 -arch ppc")
854     env.Append(LINKFLAGS="-arch i386 -arch ppc")
855
856
857 #
858 # warnings flags
859 #
860
861 env.Append(CCFLAGS="-Wall")
862 env.Append(CXXFLAGS="-Woverloaded-virtual")
863
864 if env['EXTRA_WARN']:
865     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
866     env.Append(CXXFLAGS="-ansi")
867 #    env.Append(CFLAGS="-iso")
868
869 #
870 # fix scons nitpickiness on APPLE
871 #
872
873
874 def prep_libcheck(topenv, libinfo):
875     if topenv['IS_OSX']:
876         #
877         # rationale: GTK-Quartz uses jhbuild and installs to ~/gtk/inst by default.
878         # All libraries needed should be built against this location
879
880         if topenv['GTKOSX']:
881             GTKROOT = os.path.expanduser ('~/gtk/inst')
882             libinfo.Append(CPPPATH= GTKROOT + "/include", LIBPATH= GTKROOT + "/lib")
883             libinfo.Append(CXXFLAGS="-I" + GTKROOT + "/include", LINKFLAGS="-L" + GTKROOT + "/lib")
884
885                 
886
887 prep_libcheck(env, env)
888
889 #
890 # these are part of the Ardour source tree because they are C++
891
892
893 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
894                                  LIBPATH='#libs/vamp-sdk',
895                                  CPPPATH='#libs/vamp-sdk')
896 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
897                                  LIBPATH='#libs/vamp-sdk',
898                                  CPPPATH='#libs/vamp-sdk')
899
900 env['RUBBERBAND'] = False
901
902 conf = Configure (env)
903
904 if conf.CheckHeader ('fftw3.h'):
905     env['RUBBERBAND'] = True
906     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
907                                            LIBPATH='#libs/rubberband',
908                                            CPPPATH='#libs/rubberband',
909                                            CCFLAGS='-DUSE_RUBBERBAND')
910 else:
911     print ""
912     print "-------------------------------------------------------------------------"
913     print "You do not have the FFTW single-precision development package installed."
914     print "This prevents Ardour from using the Rubberband library for timestretching"
915     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
916     print "pitchshifting will not be available."
917     print "-------------------------------------------------------------------------"
918     print ""
919
920 conf.Finish()
921
922 #
923 # Check for libusb
924
925 libraries['usb'] = LibraryInfo ()
926 prep_libcheck(env, libraries['usb'])
927
928 conf = Configure (libraries['usb'])
929 if conf.CheckLib ('usb', 'usb_interrupt_write'):
930     have_libusb = True
931 else:
932     have_libusb = False
933
934 # check for linux/input.h while we're at it for powermate
935 if conf.CheckHeader('linux/input.h'):
936     have_linux_input = True
937 else:
938     have_linux_input = False
939
940 libraries['usb'] = conf.Finish ()
941
942 #
943 # Check for wiimote dependencies
944
945 if env['WIIMOTE']:
946     wiimoteConf = env.Configure ( )
947     if not wiimoteConf.CheckHeader('cwiid.h'):
948         print 'WIIMOTE configured but you are missing libcwiid!'
949         sys.exit(1)
950     if not wiimoteConf.CheckHeader('bluetooth/bluetooth.h'):
951         print 'WIIMOTE configured but you are missing the libbluetooth headers which you need to compile wiimote support!'
952         sys.exit(1)
953     wiimoteConf.Finish()
954
955
956 #
957 # Check for FLAC
958
959 libraries['flac'] = LibraryInfo ()
960 prep_libcheck(env, libraries['flac'])
961 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
962
963 #
964 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
965 #                since the version of libsndfile we have internally does not support
966 #                the new API that libFLAC has adopted
967 #
968
969 conf = Configure (libraries['flac'])
970 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
971     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
972     use_flac = True
973 else:
974     use_flac = False
975     
976 libraries['flac'] = conf.Finish ()
977
978 # or if that fails...
979 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
980
981 # boost (we don't link against boost, just use some header files)
982
983 libraries['boost'] = LibraryInfo ()
984 prep_libcheck(env, libraries['boost'])
985 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
986 conf = Configure (libraries['boost'])
987 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
988         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."
989         sys.exit (1)
990     
991 libraries['boost'] = conf.Finish ()
992
993 #
994 # Check for liblo
995
996 libraries['lo'] = LibraryInfo ()
997 prep_libcheck(env, libraries['lo'])
998
999 conf = Configure (libraries['lo'])
1000 if conf.CheckLib ('lo', 'lo_server_new') == False:
1001     print "liblo does not appear to be installed."
1002     env['HAVE_LIBLO'] = False
1003 else:
1004     env['HAVE_LIBLO'] = True
1005
1006 libraries['lo'] = conf.Finish ()
1007
1008 #
1009 # Check for dmalloc
1010
1011 libraries['dmalloc'] = LibraryInfo ()
1012 prep_libcheck(env, libraries['dmalloc'])
1013
1014 #
1015 # look for the threaded version
1016 #
1017
1018 conf = Configure (libraries['dmalloc'])
1019 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
1020     have_libdmalloc = True
1021 else:
1022     have_libdmalloc = False
1023
1024 libraries['dmalloc'] = conf.Finish ()
1025
1026 #
1027 # ensure FREEDESKTOP target is doable..
1028 #
1029
1030 conf = env.Configure ()
1031 if env['FREEDESKTOP']:
1032         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
1033         if have_update_mime_database[0] != 1:
1034                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
1035                 env['FREEDESKTOP'] = 0
1036         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
1037         if have_gtk_update_icon_cache[0] != 1:
1038                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
1039                 env['FREEDESKTOP'] = 0
1040         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
1041         if have_update_desktop_database[0] != 1:
1042                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
1043                 env['FREEDESKTOP'] = 0
1044 env = conf.Finish()
1045
1046 #
1047 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
1048 #
1049
1050 conf = Configure(env)
1051     
1052 # ALSA, for engine dialog
1053 libraries['asound'] = LibraryInfo ()
1054
1055 if conf.CheckCHeader('alsa/asoundlib.h'):
1056     libraries['asound'] = LibraryInfo (LIBS='asound')
1057
1058 if conf.CheckCHeader('jack/midiport.h'):
1059     libraries['sysmidi'] = LibraryInfo (LIBS='jack')
1060     env['SYSMIDI'] = 'JACK MIDI'
1061     subst_dict['%MIDITAG%'] = "control"
1062     subst_dict['%MIDITYPE%'] = "jack"
1063     env.Append(CCFLAGS=" -DWITH_JACK_MIDI")
1064     print "Using JACK MIDI"
1065 elif conf.CheckCHeader('alsa/asoundlib.h'):
1066     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
1067     env['SYSMIDI'] = 'ALSA Sequencer'
1068     subst_dict['%MIDITAG%'] = "seq"
1069     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1070     print "Using ALSA MIDI"
1071 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1072     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1073     if env['GTKOSX']:
1074         # We need Carbon as well as the rest
1075         libraries['sysmidi'] = LibraryInfo (
1076                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1077     else:
1078         libraries['sysmidi'] = LibraryInfo (
1079                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1080     env['SYSMIDI'] = 'CoreMIDI'
1081     subst_dict['%MIDITAG%'] = "ardour"
1082     subst_dict['%MIDITYPE%'] = "coremidi"
1083 else:
1084     print "It appears you don't have the required MIDI libraries installed. For Linux this means you are missing the development package for ALSA libraries."
1085     sys.exit (1)
1086
1087 env = conf.Finish()
1088
1089 if env['GTKOSX']:
1090     clearlooks_version = 'libs/clearlooks-newer'
1091 else:
1092     clearlooks_version = 'libs/clearlooks-older'
1093
1094 if env['SYSLIBS']:
1095
1096     syslibdeps = \
1097     {
1098         'sigc++-2.0'           : '2.0',
1099         'gtkmm-2.4'            : '2.8',
1100         'libgnomecanvasmm-2.6' : '2.12.0'
1101     }
1102
1103     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1104                     'CheckPKGVersion' : CheckPKGVersion })
1105
1106     for pkg, version in syslibdeps.iteritems():
1107         if not conf.CheckPKGVersion( pkg, version ):
1108             print '%s >= %s not found.' %(pkg, version)
1109             DependenciesRequiredMessage()
1110             Exit(1)
1111     
1112     env = conf.Finish()
1113     
1114     libraries['sigc2'] = LibraryInfo()
1115     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1116     libraries['glibmm2'] = LibraryInfo()
1117     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1118     libraries['cairo'] = LibraryInfo()
1119     libraries['cairo'].ParseConfig('pkg-config --cflags --libs cairo')
1120     libraries['cairomm'] = LibraryInfo()
1121     libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1122     libraries['gdkmm2'] = LibraryInfo()
1123     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1124     libraries['gtkmm2'] = LibraryInfo()
1125     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1126     libraries['atkmm'] = LibraryInfo()
1127     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1128     libraries['pangomm'] = LibraryInfo()
1129     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1130     libraries['libgnomecanvasmm'] = LibraryInfo()
1131     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1132     libraries['taglib'] = LibraryInfo()
1133     libraries['taglib'].ParseConfig ('pkg-config --cflags --libs taglib')
1134
1135 #    libraries['libglademm'] = LibraryInfo()
1136 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1137
1138 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1139     libraries['soundtouch'] = LibraryInfo()
1140     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1141     # Comment the previous line and uncomment this for some versions of Debian:
1142     #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1143
1144     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1145                                             LIBPATH='#libs/appleutility',
1146                                             CPPPATH='#libs/appleutility')
1147     
1148     libraries['sndfile'] = LibraryInfo()
1149     libraries['sndfile'].ParseConfig ('pkg-config --cflags --libs sndfile')
1150     
1151     coredirs = [
1152         'templates',
1153         'manual'
1154     ]
1155     
1156     subdirs = [
1157         'libs/pbd',
1158         'libs/midi++2',
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['pangomm'] = LibraryInfo(LIBS='pangomm',
1195                                     LIBPATH='#libs/gtkmm2/pango',
1196                                     CPPPATH='#libs/gtkmm2/pango')
1197     libraries['cairomm'] = LibraryInfo(LIBS='cairomm',
1198                                     LIBPATH='#libs/cairomm',
1199                                     CPPPATH='#libs/cairomm')
1200     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
1201                                      LIBPATH='#libs/gtkmm2/atk',
1202                                      CPPPATH='#libs/gtkmm2/atk')
1203     libraries['cairomm'] = LibraryInfo(LIBS='cairomm',
1204                                       LIBPATH='#libs/cairomm',
1205                                       CPPPATH='#libs/cairomm')
1206     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
1207                                       LIBPATH='#libs/gtkmm2/gdk',
1208                                       CPPPATH='#libs/gtkmm2/gdk')
1209     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
1210                                      LIBPATH="#libs/gtkmm2/gtk",
1211                                      CPPPATH='#libs/gtkmm2/gtk/')
1212     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
1213                                                 LIBPATH='#libs/libgnomecanvasmm',
1214                                                 CPPPATH='#libs/libgnomecanvasmm')
1215     
1216     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
1217                                           LIBPATH='#libs/soundtouch',
1218                                           CPPPATH=['#libs', '#libs/soundtouch'])
1219     libraries['taglib'] = LibraryInfo(LIBS='libtaglib',
1220                                       LIBPATH='#libs/taglib',
1221                                       CPPPATH=['#libs/taglib/headers','#libs/taglib/headers/taglib'])
1222 #    libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
1223 #                                          LIBPATH='#libs/libglademm',
1224 #                                          CPPPATH='#libs/libglademm')
1225     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1226                                             LIBPATH='#libs/appleutility',
1227                                             CPPPATH='#libs/appleutility')
1228
1229     coredirs = [
1230         'templates',
1231         'manual'
1232     ]
1233     
1234     subdirs = [
1235         'libs/sigc++2',
1236         'libs/taglib',
1237         'libs/pbd',
1238         'libs/midi++2',
1239         'libs/evoral',
1240         'libs/ardour',
1241         'libs/vamp-sdk',
1242         'libs/vamp-plugins/',
1243     # these are unconditionally included but have
1244     # tests internally to avoid compilation etc
1245     # if VST is not set
1246         'libs/fst',
1247         'vst',
1248     # this is unconditionally included but has
1249     # tests internally to avoid compilation etc
1250     # if COREAUDIO is not set
1251         'libs/appleutility'
1252         ]
1253     
1254     gtk_subdirs = [
1255         'libs/glibmm2',
1256         'libs/gtkmm2/pango',
1257         'libs/gtkmm2/atk',
1258         'libs/gtkmm2/gdk',
1259         'libs/gtkmm2/gtk',
1260         'libs/libgnomecanvasmm',
1261         'libs/gtkmm2ext',
1262         'gtk2_ardour',
1263         'libs/cairomm',
1264         clearlooks_version
1265         ]
1266
1267 #
1268 # * always build the LGPL control protocol lib, since we link against it from libardour
1269 # * ditto for generic MIDI and OSC
1270 # * tranzport & wiimote check whether they should build internally, but we need them here
1271 #   so that they are included in the tarball
1272 #
1273
1274 surface_subdirs = [ 'libs/surfaces/control_protocol',
1275                     'libs/surfaces/generic_midi',
1276                     'libs/surfaces/tranzport',
1277                     'libs/surfaces/mackie',
1278                     'libs/surfaces/powermate',
1279                     'libs/surfaces/wiimote',
1280                     'libs/surfaces/osc'
1281                     ]
1282
1283 if env['SURFACES']:
1284     if have_libusb:
1285         env['TRANZPORT'] = 1
1286     else:
1287         env['TRANZPORT'] = 0
1288         print 'Disabled building Tranzport code because libusb could not be found'
1289
1290     if have_linux_input:
1291         env['POWERMATE'] = 1
1292     else:
1293         env['POWERMATE'] = 0
1294         print 'Disabled building Powermate code because linux/input.h could not be found'
1295
1296     if os.access ('libs/surfaces/sony9pin', os.F_OK):
1297         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1298 else:
1299     env['POWERMATE'] = 0
1300     env['TRANZPORT'] = 0
1301
1302 #
1303 # timestretch libraries
1304 #
1305
1306 timefx_subdirs = ['libs/soundtouch']
1307 if env['RUBBERBAND']:
1308     timefx_subdirs += ['libs/rubberband']
1309
1310 opts.Save('scache.conf', env)
1311 Help(opts.GenerateHelpText(env))
1312
1313 final_prefix = '$PREFIX'
1314
1315 if env['DESTDIR'] :
1316     install_prefix = '$DESTDIR/$PREFIX'
1317 else:
1318     install_prefix = env['PREFIX']
1319
1320 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1321 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1322 subst_dict['%PREFIX%'] = final_prefix;
1323
1324 if env['PREFIX'] == '/usr':
1325     final_config_prefix = '/etc'
1326 else:
1327     final_config_prefix = env['PREFIX'] + '/etc'
1328
1329 config_prefix = '$DESTDIR' + final_config_prefix
1330
1331 #
1332 # everybody needs this
1333 #
1334
1335 env.Merge ([ libraries['core'] ])
1336
1337
1338 #
1339 # i18n support
1340 #
1341
1342 conf = Configure (env)
1343 if env['NLS']:
1344     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1345     print 'Checking for internationalization support ...'
1346     have_gettext = conf.TryAction(Action('xgettext --version'))
1347     if have_gettext[0] != 1:
1348         nls_error += ' No xgettext command.'
1349         env['NLS'] = 0
1350     else:
1351         print "Found xgettext"
1352     
1353     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1354     if have_msgmerge[0] != 1:
1355         nls_error += ' No msgmerge command.'
1356         env['NLS'] = 0
1357     else:
1358         print "Found msgmerge"
1359     
1360     if not conf.CheckCHeader('libintl.h'):
1361         nls_error += ' No libintl.h.'
1362         env['NLS'] = 0
1363         
1364     if env['NLS'] == 0:
1365         print nls_error
1366     else:
1367         print "International version will be built."
1368 env = conf.Finish()
1369
1370 if env['NLS'] == 1:
1371     env.Append(CCFLAGS="-DENABLE_NLS")
1372
1373 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict')
1374
1375 #
1376 # the configuration file may be system dependent
1377 #
1378
1379 conf = env.Configure ()
1380
1381 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1382     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1383     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1384 else:
1385     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1386     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1387
1388 # posix_memalign available
1389 if not conf.CheckFunc('posix_memalign'):
1390     print 'Did not find posix_memalign(), using malloc'
1391     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1392
1393
1394 env = conf.Finish()
1395
1396 # Which GTK tooltips API
1397
1398 gtktestenv = env.Clone ()
1399 gtktestenv.Merge ([
1400         libraries['gtk2']
1401         ])
1402
1403 conf = gtktestenv.Configure ()
1404
1405 if conf.CheckFunc('gtk_widget_set_tooltip_text'):
1406     env.Append (CXXFLAGS='-DGTK_NEW_TOOLTIP_API')
1407
1408 conf.Finish ()
1409
1410
1411 # generate the per-user and system rc files from the same source
1412
1413 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1414
1415 # add to the substitution dictionary
1416
1417 subst_dict['%VERSION%'] = ardour_version[0:3]
1418 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1419 subst_dict['%REVISION_STRING%'] = ''
1420 if os.path.exists('.svn'):
1421     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1422
1423 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1424
1425 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1426 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1427                              [ Delete ('$PREFIX/etc/ardour3'),
1428                                Delete ('$PREFIX/lib/ardour3'),
1429                                Delete ('$PREFIX/bin/ardour3'),
1430                                Delete ('$PREFIX/share/ardour3')])
1431
1432 env.Alias('revision', the_revision)
1433 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour3'), 'ardour_system.rc'))
1434 env.Alias('uninstall', remove_ardour)
1435
1436 Default (sysrcbuild)
1437
1438 # source tarball
1439
1440 Precious (env['DISTTREE'])
1441
1442 env.Distribute (env['DISTTREE'],
1443                [ 'SConstruct', 
1444                   'COPYING', 'PACKAGER_README', 'README',
1445                   'ardour.rc.in',
1446                   'tools/config.guess',
1447                   'icons/icon/ardour_icon_mac_mask.png',
1448                   'icons/icon/ardour_icon_mac.png',
1449                   'icons/icon/ardour_icon_tango_16px_blue.png',
1450                   'icons/icon/ardour_icon_tango_16px_red.png',
1451                   'icons/icon/ardour_icon_tango_22px_blue.png',
1452                   'icons/icon/ardour_icon_tango_22px_red.png',
1453                   'icons/icon/ardour_icon_tango_32px_blue.png',
1454                   'icons/icon/ardour_icon_tango_32px_red.png',
1455                   'icons/icon/ardour_icon_tango_48px_blue.png',
1456                   'icons/icon/ardour_icon_tango_48px_red.png'
1457                   ] +
1458                 glob.glob ('ardour.1*') +
1459                 glob.glob ('libs/clearlooks-newer/*.c') +
1460                 glob.glob ('libs/clearlooks-newer/*.h') +
1461                 glob.glob ('libs/clearlooks-newer/SConscript')
1462                 )
1463
1464 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1465 env.Alias ('srctar', srcdist)
1466
1467 #
1468 # don't leave the distree around
1469 #
1470
1471 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1472 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1473
1474 #
1475 # Update revision info before going into subdirs
1476 #
1477
1478 create_stored_revision()
1479
1480 #
1481 # the subdirs
1482 #
1483
1484 for subdir in coredirs:
1485     SConscript (subdir + '/SConscript')
1486
1487 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1488     for subdir in sublistdir:
1489         SConscript (subdir + '/SConscript')
1490
1491 # cleanup
1492 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1493