Remove unnecessary 0 checks before delete; see http://www.parashift.com/c++-faq-lite...
[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('LIBLO', 'Compile with support for liblo library', 1),
49     BoolOption('NLS', 'Set to turn on i18n support', 1),
50     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
51     BoolOption('SURFACES', 'Build support for control surfaces', 1),
52     BoolOption('WIIMOTE', 'Build the wiimote control surface', 0),
53     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),
54     BoolOption('UNIVERSAL', 'Compile as universal binary.  Requires that external libraries are already universal.', 0),
55     BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
56     BoolOption('VST', 'Compile with support for VST', 0),
57     BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 1),
58     BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
59     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),
60     BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
61     BoolOption('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1)
62 )
63
64 #----------------------------------------------------------------------
65 # a handy helper that provides a way to merge compile/link information
66 # from multiple different "environments"
67 #----------------------------------------------------------------------
68 #
69 class LibraryInfo(Environment):
70     def __init__(self,*args,**kw):
71         Environment.__init__ (self,*args,**kw)
72     
73     def Merge (self,others):
74         for other in others:
75             self.Append (LIBS = other.get ('LIBS',[]))
76             self.Append (LIBPATH = other.get ('LIBPATH', []))
77             self.Append (CPPPATH = other.get('CPPPATH', []))
78             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
79             self.Append (CCFLAGS = other.get('CCFLAGS', []))
80         self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
81         self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
82         #doing LINKFLAGS breaks -framework
83         #doing LIBS break link order dependency
84     
85     def ENV_update(self, src_ENV):
86         for k in src_ENV.keys():
87             if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
88                                                   'LIB', 'INCLUDE' ]:
89                 self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
90             else:
91                 self['ENV'][k]=src_ENV[k]
92
93 env = LibraryInfo (options = opts,
94                    CPPPATH = [ '.' ],
95                    VERSION = ardour_version,
96                    TARBALL='ardour-' + ardour_version + '.tar.bz2',
97                    DISTFILES = [ ],
98                    DISTTREE  = '#ardour-' + ardour_version,
99                    DISTCHECKDIR = '#ardour-' + ardour_version + '/check'
100                    )
101
102 env.ENV_update(os.environ)
103
104 #----------------------------------------------------------------------
105 # Builders
106 #----------------------------------------------------------------------
107
108 # Handy subst-in-file builder
109 #
110
111 def do_subst_in_file(targetfile, sourcefile, dict):
112     """Replace all instances of the keys of dict with their values.
113     For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
114     then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
115     """
116     try:
117         f = open(sourcefile, 'rb')
118         contents = f.read()
119         f.close()
120     except:
121         raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
122     for (k,v) in dict.items():
123         contents = re.sub(k, v, contents)
124     try:
125         f = open(targetfile, 'wb')
126         f.write(contents)
127         f.close()
128     except:
129         raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
130     return 0 # success
131
132 def subst_in_file(target, source, env):
133     if not env.has_key('SUBST_DICT'):
134         raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
135     d = dict(env['SUBST_DICT']) # copy it
136     for (k,v) in d.items():
137         if callable(v):
138             d[k] = env.subst(v())
139         elif SCons.Util.is_String(v):
140             d[k]=env.subst(v)
141         else:
142             raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
143     for (t,s) in zip(target, source):
144         return do_subst_in_file(str(t), str(s), d)
145
146 def subst_in_file_string(target, source, env):
147     """This is what gets printed on the console."""
148     return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
149                       for (t,s) in zip(target, source)])
150
151 def subst_emitter(target, source, env):
152     """Add dependency from substituted SUBST_DICT to target.
153     Returns original target, source tuple unchanged.
154     """
155     d = env['SUBST_DICT'].copy() # copy it
156     for (k,v) in d.items():
157         if callable(v):
158             d[k] = env.subst(v())
159         elif SCons.Util.is_String(v):
160             d[k]=env.subst(v)
161     Depends(target, SCons.Node.Python.Value(d))
162     # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
163     return target, source
164
165 subst_action = Action (subst_in_file, subst_in_file_string)
166 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
167
168 #
169 # internationalization
170 #
171
172 # po_builder: builder function to copy po files to the parent directory while updating them
173 #
174 # first source:  .po file
175 # second source: .pot file
176 #
177
178 def po_builder(target,source,env):
179     os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
180     args = [ 'msgmerge',
181              '--update',
182              str(target[0]),
183              str(source[1])
184              ]
185     print 'Updating ' + str(target[0])
186     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
187
188 po_bld = Builder (action = po_builder)
189 env.Append(BUILDERS = {'PoBuild' : po_bld})
190
191 # mo_builder: builder function for (binary) message catalogs (.mo)
192 #
193 # first source:  .po file
194 #
195
196 def mo_builder(target,source,env):
197     args = [ 'msgfmt',
198              '-c',
199              '-o',
200              target[0].get_path(),
201              source[0].get_path()
202              ]
203     return os.spawnvp (os.P_WAIT, 'msgfmt', args)
204
205 mo_bld = Builder (action = mo_builder)
206 env.Append(BUILDERS = {'MoBuild' : mo_bld})
207
208 # pot_builder: builder function for message templates (.pot)
209 #
210 # source: list of C/C++ etc. files to extract messages from
211 #
212
213 def pot_builder(target,source,env):
214     args = [ 'xgettext',
215              '--keyword=_',
216              '--keyword=N_',
217              '--from-code=UTF-8',
218              '-o', target[0].get_path(),
219              "--default-domain=" + env['PACKAGE'],
220              '--copyright-holder="Paul Davis"' ]
221     args += [ src.get_path() for src in source ]
222     
223     return os.spawnvp (os.P_WAIT, 'xgettext', args)
224
225 pot_bld = Builder (action = pot_builder)
226 env.Append(BUILDERS = {'PotBuild' : pot_bld})
227
228 #
229 # utility function, not a builder
230 #
231
232 def i18n (buildenv, sources, installenv):
233     domain = buildenv['PACKAGE']
234     potfile = buildenv['POTFILE']
235     
236     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
237     
238     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
239     languages = [ po.replace ('.po', '') for po in p_oze ]
240     
241     for po_file in p_oze:
242         buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
243         mo_file = po_file.replace (".po", ".mo")
244         installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
245         installenv.Alias ('msgupdate', buildenv.MoBuild (mo_file, po_file))
246     
247     for lang in languages:
248         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
249         moname = domain + '.mo'
250         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
251
252
253 def fetch_svn_revision (path):
254     cmd = "LANG= "
255     cmd += "svn info "
256     cmd += path
257     cmd += " | awk '/^Revision:/ { print $2}'"
258     return commands.getoutput (cmd)
259
260 def fetch_git_revision (path):
261     cmd = "LANG= "
262     cmd += "git log --abbrev HEAD^..HEAD "
263     cmd += path
264     output = commands.getoutput (cmd)
265     output = output.splitlines ()
266
267     rev = output[0].replace ("commit", "git")[0:10]
268     for line in output:
269         try:
270             if "git-svn-id" in line:
271                 line = line.split('@')
272                 line = line[1].split(' ')
273                 rev = line[0]
274         except:
275             pass
276
277     return rev
278
279 def create_stored_revision (target = None, source = None, env = None):
280     rev = ""
281     if os.path.exists('.svn'):    
282         rev = fetch_svn_revision ('.');
283     elif os.path.exists('.git'):
284         rev = fetch_git_revision ('.');
285     elif os.path.exists('libs/ardour/svn_revision.cc'):
286         print "Using packaged svn revision"
287         return
288     else:
289         if not os.path.exists('libs/ardour/ardour/svn_revision.h'):    
290             print "This release of ardour is missing libs/ardour/ardour/svn_revision.h. Blame the packager."
291             sys.exit (-1)
292
293     try:
294         text  = "#include <ardour/svn_revision.h>\n"
295         text += "namespace ARDOUR {\n";
296         text += "extern const char* svn_revision = \"" + rev + "\";\n";
297         text += "}\n";
298         print '============> writing svn revision info to libs/ardour/svn_revision.cc\n'
299         o = file ('libs/ardour/svn_revision.cc', 'w')
300         o.write (text)
301         o.close ()
302     except IOError:
303         print "Could not open libs/ardour/svn_revision.cc for writing\n"
304         sys.exit (-1)
305
306 #
307 # A generic builder for version.cc files
308 #
309 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
310 # note: assumes one source files, the header that declares the version variables
311 #
312
313 def version_builder (target, source, env):
314
315     text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
316     text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
317     text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
318     
319     try:
320         o = file (target[0].get_path(), 'w')
321         o.write (text)
322         o.close ()
323     except IOError:
324         print "Could not open", target[0].get_path(), " for writing\n"
325         sys.exit (-1)
326
327     text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
328     text += "#define __" + env['DOMAIN'] + "_version_h__\n"
329     text += "extern const char* " + env['DOMAIN'] + "_revision;\n"
330     text += "extern int " + env['DOMAIN'] + "_major_version;\n"
331     text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
332     text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
333     text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
334     
335     try:
336         o = file (target[1].get_path(), 'w')
337         o.write (text)
338         o.close ()
339     except IOError:
340         print "Could not open", target[1].get_path(), " for writing\n"
341         sys.exit (-1)
342         
343     return None
344
345 version_bld = Builder (action = version_builder)
346 env.Append (BUILDERS = {'VersionBuild' : version_bld})
347
348 #
349 # a builder that makes a hard link from the 'source' executable to a name with
350 # a "build ID" based on the most recent CVS activity that might be reasonably
351 # related to version activity. this relies on the idea that the SConscript
352 # file that builds the executable is updated with new version info and committed
353 # to the source code repository whenever things change.
354 #
355
356 def versioned_builder(target,source,env):
357     w, r = os.popen2( "LANG= svn info | awk '/^Revision:/ { print $2}'")
358     
359     last_revision = r.readline().strip()
360     w.close()
361     r.close()
362     if last_revision == "":
363         print "No SVN info found - versioned executable cannot be built"
364         return -1
365     
366     print "The current build ID is " + last_revision
367     
368     tagged_executable = source[0].get_path() + '-' + last_revision
369     
370     if os.path.exists (tagged_executable):
371         print "Replacing existing executable with the same build tag."
372         os.unlink (tagged_executable)
373     
374     return os.link (source[0].get_path(), tagged_executable)
375
376 verbuild = Builder (action = versioned_builder)
377 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
378
379 #
380 # source tar file builder
381 #
382
383 def distcopy (target, source, env):
384     treedir = str (target[0])
385     
386     try:
387         os.mkdir (treedir)
388     except OSError, (errnum, strerror):
389         if errnum != errno.EEXIST:
390             print 'mkdir ', treedir, ':', strerror
391     
392     cmd = 'tar cf - '
393     #
394     # we don't know what characters might be in the file names
395     # so quote them all before passing them to the shell
396     #
397     all_files = ([ str(s) for s in source ])
398     cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
399     cmd += ' | (cd ' + treedir + ' && tar xf -)'
400     p = os.popen (cmd)
401     return p.close ()
402
403 def tarballer (target, source, env):
404     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'" + " --exclude .svn --exclude '.svn/*'"
405     print 'running ', cmd, ' ... '
406     p = os.popen (cmd)
407     return p.close ()
408
409 dist_bld = Builder (action = distcopy,
410                     target_factory = SCons.Node.FS.default_fs.Entry,
411                     source_factory = SCons.Node.FS.default_fs.Entry,
412                     multi = 1)
413
414 tarball_bld = Builder (action = tarballer,
415                        target_factory = SCons.Node.FS.default_fs.Entry,
416                        source_factory = SCons.Node.FS.default_fs.Entry)
417
418 env.Append (BUILDERS = {'Distribute' : dist_bld})
419 env.Append (BUILDERS = {'Tarball' : tarball_bld})
420
421 #
422 # Make sure they know what they are doing
423 #
424
425 if env['VST']:
426     if os.path.isfile('.personal_use_only'):
427         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."
428     else:
429         sys.stdout.write ("Are you building Ardour for personal use (rather than distribution to others)? [no]: ")
430         answer = sys.stdin.readline ()
431         answer = answer.rstrip().strip()
432         if answer == "yes" or answer == "y":
433             fh = open('.personal_use_only', 'w')
434             fh.close()
435             print "OK, VST support will be enabled"
436         else:
437             print 'You cannot build Ardour with VST support for distribution to others.\nIt is a violation of several different licenses. Build with VST=false.'
438             sys.exit (-1);
439 else:
440     if os.path.isfile('.personal_use_only'):
441         os.remove('.personal_use_only')
442
443 ####################
444 # push environment
445 ####################
446
447 def pushEnvironment(context):
448     if os.environ.has_key('PATH'):
449         context.Append(PATH = os.environ['PATH'])
450         
451     if os.environ.has_key('PKG_CONFIG_PATH'):
452         context.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
453             
454     if os.environ.has_key('CC'):
455         context['CC'] = os.environ['CC']
456                 
457     if os.environ.has_key('CXX'):
458         context['CXX'] = os.environ['CXX']
459
460     if os.environ.has_key('DISTCC_HOSTS'):
461         context['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
462         context['ENV']['HOME'] = os.environ['HOME']
463
464 pushEnvironment (env)
465
466 #######################
467 # Dependency Checking #
468 #######################
469
470 deps = \
471 {
472         'glib-2.0'             : '2.10.1',
473         'gthread-2.0'          : '2.10.1',
474         'gtk+-2.0'             : '2.12.1',
475         'libxml-2.0'           : '2.6.0',
476         'samplerate'           : '0.1.0',
477         'raptor'               : '1.4.2',
478         'lrdf'                 : '0.4.0',
479         'jack'                 : '0.109.0',
480         'libgnomecanvas-2.0'   : '2.0',
481         'aubio'                : '0.3.2',
482         'ogg'                  : '1.1.2',
483         'flac'                 : '1.2.1',
484         'sndfile'              : '1.0.18'
485 }
486
487 def DependenciesRequiredMessage():
488         print 'You do not have the necessary dependencies required to build ardour'
489         print 'Please consult http://ardour.org/building for more information'
490
491 def CheckPKGConfig(context, version):
492     context.Message( 'Checking for pkg-config version >= %s... ' %version )
493     ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
494     context.Result( ret )
495     return ret
496
497 def CheckPKGVersion(context, name, version):
498     context.Message( 'Checking for %s... ' % name )
499     ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
500     context.Result( ret )
501     return ret
502
503 def CheckPKGExists(context, name):
504     context.Message ('Checking for %s...' % name)
505     ret = context.TryAction('pkg-config --exists %s' % name)[0]
506     context.Result (ret)
507     return ret
508
509 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
510                                        'CheckPKGVersion' : CheckPKGVersion })
511
512 # I think a more recent version is needed on win32
513 min_pkg_config_version = '0.8.0'
514
515 if not conf.CheckPKGConfig(min_pkg_config_version):
516      print 'pkg-config >= %s not found.' % min_pkg_config_version
517      Exit(1)
518
519 for pkg, version in deps.iteritems():
520         if not conf.CheckPKGVersion( pkg, version ):
521                 print '%s >= %s not found.' %(pkg, version)
522                 DependenciesRequiredMessage()
523                 Exit(1)
524
525 env = conf.Finish()
526
527 # ----------------------------------------------------------------------
528 # Construction environment setup
529 # ----------------------------------------------------------------------
530
531 libraries = { }
532
533 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
534
535 libraries['sndfile'] = LibraryInfo()
536 libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
537
538 libraries['lrdf'] = LibraryInfo()
539 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
540
541 libraries['raptor'] = LibraryInfo()
542 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
543
544 libraries['samplerate'] = LibraryInfo()
545 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
546
547 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
548
549 if conf.CheckPKGExists ('fftw3f'):
550     libraries['fftw3f'] = LibraryInfo()
551     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
552
553 if conf.CheckPKGExists ('fftw3'):
554     libraries['fftw3'] = LibraryInfo()
555     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
556
557 if conf.CheckPKGExists ('aubio'):
558     libraries['aubio'] = LibraryInfo()
559     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
560     env['AUBIO'] = 1
561 else:
562     env['AUBIO'] = 0
563
564 env = conf.Finish ()
565
566 #
567 # Check for fftw3 header as well as the library
568 #
569
570 conf = Configure(libraries['fftw3'])
571
572 if conf.CheckHeader ('fftw3.h') == False:
573     print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
574     sys.exit (1)            
575 conf.Finish()
576
577 if env['FREESOUND']:
578         #
579         # Check for curl header as well as the library
580         #
581
582         libraries['curl'] = LibraryInfo()
583
584         conf = Configure(libraries['curl'])
585
586         if conf.CheckHeader ('curl/curl.h') == False:
587                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
588                 sys.exit (1)            
589         else:
590                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
591         conf.Finish()
592 else:
593         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
594
595 if env['LV2']:
596         conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion})
597         
598         if conf.CheckPKGVersion('slv2', '0.6.2'):
599                 libraries['slv2'] = LibraryInfo()
600                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
601                 env.Append (CCFLAGS="-DHAVE_LV2")
602         else:
603                 print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
604                 env['LV2'] = 0
605         conf.Finish()
606 else:
607         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
608
609 if not env['WIIMOTE']:
610         print 'WIIMOTE not enabled. Build with \'scons WIIMOTE=1\' to enable support.'
611
612 libraries['jack'] = LibraryInfo()
613 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
614
615 libraries['xml'] = LibraryInfo()
616 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
617
618 libraries['xslt'] = LibraryInfo()
619 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
620
621 libraries['uuid'] = LibraryInfo()
622 libraries['uuid'].ParseConfig('pkg-config --cflags --libs uuid')
623
624 libraries['glib2'] = LibraryInfo()
625 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
626 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
627 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
628 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
629
630 libraries['freetype2'] = LibraryInfo()
631 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
632
633 libraries['gtk2'] = LibraryInfo()
634 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
635
636 libraries['pango'] = LibraryInfo()
637 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
638
639 libraries['pangocairo'] = LibraryInfo()
640 libraries['pangocairo'].ParseConfig ('pkg-config --cflags --libs pangocairo')
641
642 libraries['libgnomecanvas2'] = LibraryInfo()
643 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
644
645 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
646
647 # The Ardour Control Protocol Library
648
649 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
650                                       CPPPATH='#libs/surfaces/control_protocol')
651
652 # The Ardour backend/engine
653
654 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
655 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
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 = [ '-g', '-pg' ]
682 else:
683     debug_flags = [ '-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 if env['LIBLO']:
871     env.Append(CCFLAGS="-DHAVE_LIBLO")
872
873
874 #
875 # fix scons nitpickiness on APPLE
876 #
877
878
879 def prep_libcheck(topenv, libinfo):
880     if topenv['IS_OSX']:
881         #
882         # rationale: GTK-Quartz uses jhbuild and installs to ~/gtk/inst by default.
883         # All libraries needed should be built against this location
884
885         if topenv['GTKOSX']:
886             GTKROOT = os.path.expanduser ('~/gtk/inst')
887             libinfo.Append(CPPPATH= GTKROOT + "/include", LIBPATH= GTKROOT + "/lib")
888             libinfo.Append(CXXFLAGS="-I" + GTKROOT + "/include", LINKFLAGS="-L" + GTKROOT + "/lib")
889
890                 
891
892 prep_libcheck(env, env)
893
894 #
895 # these are part of the Ardour source tree because they are C++
896
897
898 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
899                                  LIBPATH='#libs/vamp-sdk',
900                                  CPPPATH='#libs/vamp-sdk')
901 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
902                                  LIBPATH='#libs/vamp-sdk',
903                                  CPPPATH='#libs/vamp-sdk')
904
905 env['RUBBERBAND'] = False
906
907 conf = Configure (env)
908
909 if conf.CheckHeader ('fftw3.h'):
910     env['RUBBERBAND'] = True
911     libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
912                                            LIBPATH='#libs/rubberband',
913                                            CPPPATH='#libs/rubberband',
914                                            CCFLAGS='-DUSE_RUBBERBAND')
915 else:
916     print ""
917     print "-------------------------------------------------------------------------"
918     print "You do not have the FFTW single-precision development package installed."
919     print "This prevents Ardour from using the Rubberband library for timestretching"
920     print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
921     print "pitchshifting will not be available."
922     print "-------------------------------------------------------------------------"
923     print ""
924
925 conf.Finish()
926
927 #
928 # Check for libusb
929
930 libraries['usb'] = LibraryInfo ()
931 prep_libcheck(env, libraries['usb'])
932
933 conf = Configure (libraries['usb'])
934 if conf.CheckLib ('usb', 'usb_interrupt_write'):
935     have_libusb = True
936 else:
937     have_libusb = False
938
939 # check for linux/input.h while we're at it for powermate
940 if conf.CheckHeader('linux/input.h'):
941     have_linux_input = True
942 else:
943     have_linux_input = False
944
945 libraries['usb'] = conf.Finish ()
946
947 #
948 # Check for wiimote dependencies
949
950 if env['WIIMOTE']:
951     wiimoteConf = env.Configure ( )
952     if not wiimoteConf.CheckHeader('cwiid.h'):
953         print 'WIIMOTE configured but you are missing libcwiid!'
954         sys.exit(1)
955     if not wiimoteConf.CheckHeader('bluetooth/bluetooth.h'):
956         print 'WIIMOTE configured but you are missing the libbluetooth headers which you need to compile wiimote support!'
957         sys.exit(1)
958     wiimoteConf.Finish()
959
960
961 #
962 # Check for FLAC
963
964 libraries['flac'] = LibraryInfo ()
965 prep_libcheck(env, libraries['flac'])
966 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
967
968 #
969 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
970 #                since the version of libsndfile we have internally does not support
971 #                the new API that libFLAC has adopted
972 #
973
974 conf = Configure (libraries['flac'])
975 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
976     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
977     use_flac = True
978 else:
979     use_flac = False
980     
981 libraries['flac'] = conf.Finish ()
982
983 # or if that fails...
984 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
985
986 # boost (we don't link against boost, just use some header files)
987
988 libraries['boost'] = LibraryInfo ()
989 prep_libcheck(env, libraries['boost'])
990 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
991 conf = Configure (libraries['boost'])
992 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
993         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."
994         sys.exit (1)
995     
996 libraries['boost'] = conf.Finish ()
997
998 #
999 # Check for liblo
1000
1001 if env['LIBLO']:
1002     libraries['lo'] = LibraryInfo ()
1003     prep_libcheck(env, libraries['lo'])
1004
1005     conf = Configure (libraries['lo'])
1006     if conf.CheckLib ('lo', 'lo_server_new') == False:
1007         print "liblo does not appear to be installed."
1008         sys.exit (1)
1009     
1010     libraries['lo'] = conf.Finish ()
1011
1012 #
1013 # Check for dmalloc
1014
1015 libraries['dmalloc'] = LibraryInfo ()
1016 prep_libcheck(env, libraries['dmalloc'])
1017
1018 #
1019 # look for the threaded version
1020 #
1021
1022 conf = Configure (libraries['dmalloc'])
1023 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
1024     have_libdmalloc = True
1025 else:
1026     have_libdmalloc = False
1027
1028 libraries['dmalloc'] = conf.Finish ()
1029
1030 #
1031 # ensure FREEDESKTOP target is doable..
1032 #
1033
1034 conf = env.Configure ()
1035 if env['FREEDESKTOP']:
1036         have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
1037         if have_update_mime_database[0] != 1:
1038                 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
1039                 env['FREEDESKTOP'] = 0
1040         have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
1041         if have_gtk_update_icon_cache[0] != 1:
1042                 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
1043                 env['FREEDESKTOP'] = 0
1044         have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
1045         if have_update_desktop_database[0] != 1:
1046                 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
1047                 env['FREEDESKTOP'] = 0
1048 env = conf.Finish()
1049
1050 #
1051 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
1052 #
1053
1054 conf = Configure(env)
1055     
1056 # ALSA, for engine dialog
1057 libraries['asound'] = LibraryInfo ()
1058
1059 if conf.CheckCHeader('alsa/asoundlib.h'):
1060     libraries['asound'] = LibraryInfo (LIBS='asound')
1061
1062 if conf.CheckCHeader('jack/midiport.h'):
1063     libraries['sysmidi'] = LibraryInfo (LIBS='jack')
1064     env['SYSMIDI'] = 'JACK MIDI'
1065     subst_dict['%MIDITAG%'] = "control"
1066     subst_dict['%MIDITYPE%'] = "jack"
1067     print "Using JACK MIDI"
1068 elif conf.CheckCHeader('alsa/asoundlib.h'):
1069     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
1070     env['SYSMIDI'] = 'ALSA Sequencer'
1071     subst_dict['%MIDITAG%'] = "seq"
1072     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
1073     print "Using ALSA MIDI"
1074 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
1075     # this line is needed because scons can't handle -framework in ParseConfig() yet.
1076     if env['GTKOSX']:
1077         # We need Carbon as well as the rest
1078         libraries['sysmidi'] = LibraryInfo (
1079                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
1080     else:
1081         libraries['sysmidi'] = LibraryInfo (
1082                 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
1083     env['SYSMIDI'] = 'CoreMIDI'
1084     subst_dict['%MIDITAG%'] = "ardour"
1085     subst_dict['%MIDITYPE%'] = "coremidi"
1086 else:
1087     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."
1088     sys.exit (1)
1089
1090 env = conf.Finish()
1091
1092 if env['GTKOSX']:
1093     clearlooks_version = 'libs/clearlooks-newer'
1094 else:
1095     clearlooks_version = 'libs/clearlooks-older'
1096
1097 if env['SYSLIBS']:
1098
1099     syslibdeps = \
1100     {
1101         'sigc++-2.0'           : '2.0',
1102         'gtkmm-2.4'            : '2.8',
1103         'libgnomecanvasmm-2.6' : '2.12.0'
1104     }
1105
1106     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1107                     'CheckPKGVersion' : CheckPKGVersion })
1108
1109     for pkg, version in syslibdeps.iteritems():
1110         if not conf.CheckPKGVersion( pkg, version ):
1111             print '%s >= %s not found.' %(pkg, version)
1112             DependenciesRequiredMessage()
1113             Exit(1)
1114     
1115     env = conf.Finish()
1116     
1117     libraries['sigc2'] = LibraryInfo()
1118     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1119     libraries['glibmm2'] = LibraryInfo()
1120     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1121     libraries['cairo'] = LibraryInfo()
1122     libraries['cairo'].ParseConfig('pkg-config --cflags --libs cairo')
1123     libraries['cairomm'] = LibraryInfo()
1124     libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1125     libraries['gdkmm2'] = LibraryInfo()
1126     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1127     libraries['gtkmm2'] = LibraryInfo()
1128     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1129     libraries['atkmm'] = LibraryInfo()
1130     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1131     libraries['pangomm'] = LibraryInfo()
1132     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1133     libraries['libgnomecanvasmm'] = LibraryInfo()
1134     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1135     libraries['taglib'] = LibraryInfo()
1136     libraries['taglib'].ParseConfig ('pkg-config --cflags --libs taglib')
1137
1138 #    libraries['libglademm'] = LibraryInfo()
1139 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1140
1141 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1142     libraries['soundtouch'] = LibraryInfo()
1143     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1144     # Comment the previous line and uncomment this for some versions of Debian:
1145     #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1146
1147     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1148                                             LIBPATH='#libs/appleutility',
1149                                             CPPPATH='#libs/appleutility')
1150     
1151     libraries['sndfile'] = LibraryInfo()
1152     libraries['sndfile'].ParseConfig ('pkg-config --cflags --libs sndfile')
1153     
1154     coredirs = [
1155         'templates',
1156         'manual'
1157     ]
1158     
1159     subdirs = [
1160         'libs/pbd',
1161         'libs/midi++2',
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/headers','#libs/taglib/headers/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',
1243         'libs/ardour',
1244         'libs/vamp-sdk',
1245         'libs/vamp-plugins/',
1246     # these are unconditionally included but have
1247     # tests internally to avoid compilation etc
1248     # if VST is not set
1249         'libs/fst',
1250         'vst',
1251     # this is unconditionally included but has
1252     # tests internally to avoid compilation etc
1253     # if COREAUDIO is not set
1254         'libs/appleutility'
1255         ]
1256     
1257     gtk_subdirs = [
1258         'libs/glibmm2',
1259         'libs/gtkmm2/pango',
1260         'libs/gtkmm2/atk',
1261         'libs/gtkmm2/gdk',
1262         'libs/gtkmm2/gtk',
1263         'libs/libgnomecanvasmm',
1264         'libs/gtkmm2ext',
1265         'gtk2_ardour',
1266         'libs/cairomm',
1267         clearlooks_version
1268         ]
1269
1270 #
1271 # * always build the LGPL control protocol lib, since we link against it from libardour
1272 # * ditto for generic MIDI
1273 # * tranzport & wiimote check whether they should build internally, but we need them here
1274 #   so that they are included in the tarball
1275 #
1276
1277 surface_subdirs = [ 'libs/surfaces/control_protocol',
1278                     'libs/surfaces/generic_midi',
1279                     'libs/surfaces/tranzport',
1280                     'libs/surfaces/mackie',
1281                     'libs/surfaces/powermate',
1282                     'libs/surfaces/wiimote'
1283                     ]
1284
1285 if env['SURFACES']:
1286     if have_libusb:
1287         env['TRANZPORT'] = 1
1288     else:
1289         env['TRANZPORT'] = 0
1290         print 'Disabled building Tranzport code because libusb could not be found'
1291
1292     if have_linux_input:
1293         env['POWERMATE'] = 1
1294     else:
1295         env['POWERMATE'] = 0
1296         print 'Disabled building Powermate code because linux/input.h could not be found'
1297
1298     if os.access ('libs/surfaces/sony9pin', os.F_OK):
1299         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1300 else:
1301     env['POWERMATE'] = 0
1302     env['TRANZPORT'] = 0
1303
1304 #
1305 # timestretch libraries
1306 #
1307
1308 timefx_subdirs = ['libs/soundtouch']
1309 if env['RUBBERBAND']:
1310     timefx_subdirs += ['libs/rubberband']
1311
1312 opts.Save('scache.conf', env)
1313 Help(opts.GenerateHelpText(env))
1314
1315 final_prefix = '$PREFIX'
1316
1317 if env['DESTDIR'] :
1318     install_prefix = '$DESTDIR/$PREFIX'
1319 else:
1320     install_prefix = env['PREFIX']
1321
1322 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1323 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1324 subst_dict['%PREFIX%'] = final_prefix;
1325
1326 if env['PREFIX'] == '/usr':
1327     final_config_prefix = '/etc'
1328 else:
1329     final_config_prefix = env['PREFIX'] + '/etc'
1330
1331 config_prefix = '$DESTDIR' + final_config_prefix
1332
1333 #
1334 # everybody needs this
1335 #
1336
1337 env.Merge ([ libraries['core'] ])
1338
1339
1340 #
1341 # i18n support
1342 #
1343
1344 conf = Configure (env)
1345 if env['NLS']:
1346     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1347     print 'Checking for internationalization support ...'
1348     have_gettext = conf.TryAction(Action('xgettext --version'))
1349     if have_gettext[0] != 1:
1350         nls_error += ' No xgettext command.'
1351         env['NLS'] = 0
1352     else:
1353         print "Found xgettext"
1354     
1355     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1356     if have_msgmerge[0] != 1:
1357         nls_error += ' No msgmerge command.'
1358         env['NLS'] = 0
1359     else:
1360         print "Found msgmerge"
1361     
1362     if not conf.CheckCHeader('libintl.h'):
1363         nls_error += ' No libintl.h.'
1364         env['NLS'] = 0
1365         
1366     if env['NLS'] == 0:
1367         print nls_error
1368     else:
1369         print "International version will be built."
1370 env = conf.Finish()
1371
1372 if env['NLS'] == 1:
1373     env.Append(CCFLAGS="-DENABLE_NLS")
1374
1375 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict')
1376
1377 #
1378 # the configuration file may be system dependent
1379 #
1380
1381 conf = env.Configure ()
1382
1383 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1384     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1385     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1386 else:
1387     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1388     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1389
1390 # posix_memalign available
1391 if not conf.CheckFunc('posix_memalign'):
1392     print 'Did not find posix_memalign(), using malloc'
1393     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1394
1395
1396 env = conf.Finish()
1397
1398 # Which GTK tooltips API
1399
1400 gtktestenv = env.Clone ()
1401 gtktestenv.Merge ([
1402         libraries['gtk2']
1403         ])
1404
1405 conf = gtktestenv.Configure ()
1406
1407 if conf.CheckFunc('gtk_widget_set_tooltip_text'):
1408     env.Append (CXXFLAGS='-DGTK_NEW_TOOLTIP_API')
1409
1410 conf.Finish ()
1411
1412
1413 # generate the per-user and system rc files from the same source
1414
1415 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1416
1417 # add to the substitution dictionary
1418
1419 subst_dict['%VERSION%'] = ardour_version[0:3]
1420 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1421 subst_dict['%REVISION_STRING%'] = ''
1422 if os.path.exists('.svn'):
1423     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1424
1425 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1426
1427 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1428 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1429                              [ Delete ('$PREFIX/etc/ardour3'),
1430                                Delete ('$PREFIX/lib/ardour3'),
1431                                Delete ('$PREFIX/bin/ardour3'),
1432                                Delete ('$PREFIX/share/ardour3')])
1433
1434 env.Alias('revision', the_revision)
1435 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour3'), 'ardour_system.rc'))
1436 env.Alias('uninstall', remove_ardour)
1437
1438 Default (sysrcbuild)
1439
1440 # source tarball
1441
1442 Precious (env['DISTTREE'])
1443
1444 env.Distribute (env['DISTTREE'],
1445                [ 'SConstruct', 
1446                   'COPYING', 'PACKAGER_README', 'README',
1447                   'ardour.rc.in',
1448                   'tools/config.guess',
1449                   'icons/icon/ardour_icon_mac_mask.png',
1450                   'icons/icon/ardour_icon_mac.png',
1451                   'icons/icon/ardour_icon_tango_16px_blue.png',
1452                   'icons/icon/ardour_icon_tango_16px_red.png',
1453                   'icons/icon/ardour_icon_tango_22px_blue.png',
1454                   'icons/icon/ardour_icon_tango_22px_red.png',
1455                   'icons/icon/ardour_icon_tango_32px_blue.png',
1456                   'icons/icon/ardour_icon_tango_32px_red.png',
1457                   'icons/icon/ardour_icon_tango_48px_blue.png',
1458                   'icons/icon/ardour_icon_tango_48px_red.png'
1459                   ] +
1460                 glob.glob ('ardour.1*') +
1461                 glob.glob ('libs/clearlooks-newer/*.c') +
1462                 glob.glob ('libs/clearlooks-newer/*.h') +
1463                 glob.glob ('libs/clearlooks-newer/SConscript')
1464                 )
1465
1466 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1467 env.Alias ('srctar', srcdist)
1468
1469 #
1470 # don't leave the distree around
1471 #
1472
1473 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1474 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1475
1476 #
1477 # Update revision info before going into subdirs
1478 #
1479
1480 create_stored_revision()
1481
1482 #
1483 # the subdirs
1484 #
1485
1486 for subdir in coredirs:
1487     SConscript (subdir + '/SConscript')
1488
1489 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1490     for subdir in sublistdir:
1491         SConscript (subdir + '/SConscript')
1492
1493 # cleanup
1494 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1495