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