9ff6a61e11f3ac9cc029220f0c2df3d08e1731a5
[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         'aubio'                : '0.3.2'
457 }
458
459 def DependenciesRequiredMessage():
460         print 'You do not have the necessary dependencies required to build ardour'
461         print 'Please consult http://ardour.org/building for more information'
462
463 def CheckPKGConfig(context, version):
464     context.Message( 'Checking for pkg-config version >= %s... ' %version )
465     ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
466     context.Result( ret )
467     return ret
468
469 def CheckPKGVersion(context, name, version):
470     context.Message( 'Checking for %s... ' % name )
471     ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
472     context.Result( ret )
473     return ret
474
475 def CheckPKGExists(context, name):
476     context.Message ('Checking for %s...' % name)
477     ret = context.TryAction('pkg-config --exists %s' % name)[0]
478     context.Result (ret)
479     return ret
480
481 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
482                                        'CheckPKGVersion' : CheckPKGVersion })
483
484 # I think a more recent version is needed on win32
485 min_pkg_config_version = '0.8.0'
486
487 if not conf.CheckPKGConfig(min_pkg_config_version):
488      print 'pkg-config >= %s not found.' % min_pkg_config_version
489      Exit(1)
490
491 for pkg, version in deps.iteritems():
492         if not conf.CheckPKGVersion( pkg, version ):
493                 print '%s >= %s not found.' %(pkg, version)
494                 DependenciesRequiredMessage()
495                 Exit(1)
496
497 env = conf.Finish()
498
499 # ----------------------------------------------------------------------
500 # Construction environment setup
501 # ----------------------------------------------------------------------
502
503 libraries = { }
504
505 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
506
507 #libraries['sndfile'] = LibraryInfo()
508 #libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
509
510 libraries['lrdf'] = LibraryInfo()
511 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
512
513 libraries['raptor'] = LibraryInfo()
514 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
515
516 libraries['samplerate'] = LibraryInfo()
517 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
518
519 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
520
521 if conf.CheckPKGExists ('fftw3f'):
522     libraries['fftw3f'] = LibraryInfo()
523     libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
524
525 if conf.CheckPKGExists ('fftw3'):
526     libraries['fftw3'] = LibraryInfo()
527     libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
528
529 if conf.CheckPKGExists ('aubio'):
530     libraries['aubio'] = LibraryInfo()
531     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
532     env['AUBIO'] = 1
533 else:
534     env['AUBIO'] = 0
535
536 env = conf.Finish ()
537
538 if env['FFT_ANALYSIS']:
539         #
540         # Check for fftw3 header as well as the library
541         #
542
543         conf = Configure(libraries['fftw3'])
544
545         if conf.CheckHeader ('fftw3.h') == False:
546             print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
547             sys.exit (1)            
548         conf.Finish()
549
550 if env['FREESOUND']:
551         #
552         # Check for curl header as well as the library
553         #
554
555         libraries['curl'] = LibraryInfo()
556
557         conf = Configure(libraries['curl'])
558
559         if conf.CheckHeader ('curl/curl.h') == False:
560                 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
561                 sys.exit (1)            
562         else:
563                 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
564         conf.Finish()
565 else:
566         print 'FREESOUND support is not enabled.  Build with \'scons FREESOUND=1\' to enable.'
567
568 if env['LV2']:
569         conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion})
570         
571         if conf.CheckPKGVersion('slv2', '0.6.0'):
572                 libraries['slv2'] = LibraryInfo()
573                 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
574                 env.Append (CCFLAGS="-DHAVE_LV2")
575         else:
576                 print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
577                 env['LV2'] = 0
578         conf.Finish()
579 else:
580         print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
581
582 libraries['jack'] = LibraryInfo()
583 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
584
585 libraries['xml'] = LibraryInfo()
586 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
587
588 libraries['xslt'] = LibraryInfo()
589 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
590
591 libraries['glib2'] = LibraryInfo()
592 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
593 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
594 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
595 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
596
597 libraries['freetype2'] = LibraryInfo()
598 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
599
600 libraries['gtk2'] = LibraryInfo()
601 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
602
603 libraries['pango'] = LibraryInfo()
604 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
605
606 libraries['libgnomecanvas2'] = LibraryInfo()
607 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
608
609 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
610
611 # The Ardour Control Protocol Library
612
613 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
614                                       CPPPATH='#libs/surfaces/control_protocol')
615
616 # The Ardour backend/engine
617
618 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
619 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
620 libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
621 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
622
623
624 # SCons should really do this for us
625
626 conf = env.Configure ()
627
628 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
629 if have_cxx[0] != 1:
630     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
631     sys.exit (1)
632 else:
633     print "Congratulations, you have a functioning C++ compiler."
634
635 env = conf.Finish()
636
637
638 #
639 # Compiler flags and other system-dependent stuff
640 #
641
642 opt_flags = []
643 if env['GPROFILE'] == 1:
644     debug_flags = [ '-g', '-pg' ]
645 else:
646     debug_flags = [ '-g' ]
647
648 # guess at the platform, used to define compiler flags
649
650 config_guess = os.popen("tools/config.guess").read()[:-1]
651
652 config_cpu = 0
653 config_arch = 1
654 config_kernel = 2
655 config_os = 3
656 config = config_guess.split ("-")
657
658 print "system triple: " + config_guess
659
660 # Autodetect
661 if env['DIST_TARGET'] == 'auto':
662     if config[config_arch] == 'apple':
663         # The [.] matches to the dot after the major version, "." would match any character
664         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
665             env['DIST_TARGET'] = 'panther'
666         if re.search ("darwin8[.]", config[config_kernel]) != None:
667             env['DIST_TARGET'] = 'tiger'
668         else:
669             env['DIST_TARGET'] = 'leopard'
670     else:
671         if re.search ("x86_64", config[config_cpu]) != None:
672             env['DIST_TARGET'] = 'x86_64'
673         elif re.search("i[0-5]86", config[config_cpu]) != None:
674             env['DIST_TARGET'] = 'i386'
675         elif re.search("powerpc", config[config_cpu]) != None:
676             env['DIST_TARGET'] = 'powerpc'
677         else:
678             env['DIST_TARGET'] = 'i686'
679     print "\n*******************************"
680     print "detected DIST_TARGET = " + env['DIST_TARGET']
681     print "*******************************\n"
682
683
684 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
685     #
686     # Apple/PowerPC optimization options
687     #
688     # -mcpu=7450 does not reliably work with gcc 3.*
689     #
690     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
691         if config[config_arch] == 'apple':
692             ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
693             # to support g3s but still have some optimization for above
694             opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
695         else:
696             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
697     else:
698         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
699     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
700     opt_flags.extend (["-Os"])
701
702 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':
703     
704     build_host_supports_sse = 0
705     
706     debug_flags.append ("-DARCH_X86")
707     opt_flags.append ("-DARCH_X86")
708     
709     if config[config_kernel] == 'linux' :
710         
711         if env['DIST_TARGET'] != 'i386':
712             
713             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
714             x86_flags = flag_line.split (": ")[1:][0].split ()
715             
716             if "mmx" in x86_flags:
717                 opt_flags.append ("-mmmx")
718             if "sse" in x86_flags:
719                 build_host_supports_sse = 1
720             if "3dnow" in x86_flags:
721                 opt_flags.append ("-m3dnow")
722             
723             if config[config_cpu] == "i586":
724                 opt_flags.append ("-march=i586")
725             elif config[config_cpu] == "i686":
726                 opt_flags.append ("-march=i686")
727     
728     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
729         opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
730         debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
731 # end of processor-specific section
732
733 # optimization section
734 if env['FPU_OPTIMIZATION']:
735     if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
736         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
737         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
738         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
739     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
740         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
741         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
742         if env['DIST_TARGET'] == 'x86_64':
743             opt_flags.append ("-DUSE_X86_64_ASM")
744             debug_flags.append ("-DUSE_X86_64_ASM")
745         if build_host_supports_sse != 1:
746             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)"
747 # end optimization section
748
749 # handle x86/x86_64 libdir properly
750
751 if env['DIST_TARGET'] == 'x86_64':
752     env['LIBDIR']='lib64'
753 else:
754     env['LIBDIR']='lib'
755
756 #
757 # a single way to test if we're on OS X
758 #
759
760 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
761     env['IS_OSX'] = 1
762     # force tiger or later, to avoid issues on PPC which defaults
763     # back to 10.1 if we don't tell it otherwise.
764     env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
765
766     if env['DIST_TARGET'] == 'leopard':
767         # need this to really build against the 10.4 SDK when building on leopard
768         # ideally this would be configurable, but lets just do that later when we need it
769         env.Append(CCFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
770         env.Append(LINKFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk")
771
772 else:
773     env['IS_OSX'] = 0
774
775 #
776 # save off guessed arch element in an env
777 #
778 env.Append(CONFIG_ARCH=config[config_arch])
779
780
781 #
782 # ARCH="..." overrides all
783 #
784
785 if env['ARCH'] != '':
786     opt_flags = env['ARCH'].split()
787
788 #
789 # prepend boiler plate optimization flags
790 #
791
792 opt_flags[:0] = [
793     "-O3",
794     "-fomit-frame-pointer",
795     "-ffast-math",
796     "-fstrength-reduce",
797     "-pipe"
798     ]
799
800 if env['DEBUG'] == 1:
801     env.Append(CCFLAGS=" ".join (debug_flags))
802     env.Append(LINKFLAGS=" ".join (debug_flags))
803 else:
804     env.Append(CCFLAGS=" ".join (opt_flags))
805     env.Append(LINKFLAGS=" ".join (opt_flags))
806
807 if env['STL_DEBUG'] == 1:
808     env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
809
810 if env['UNIVERSAL'] == 1:
811     env.Append(CCFLAGS="-arch i386 -arch ppc")
812     env.Append(LINKFLAGS="-arch i386 -arch ppc")
813
814
815 #
816 # warnings flags
817 #
818
819 env.Append(CCFLAGS="-Wall")
820 env.Append(CXXFLAGS="-Woverloaded-virtual")
821
822 if env['EXTRA_WARN']:
823     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
824     env.Append(CXXFLAGS="-ansi")
825 #    env.Append(CFLAGS="-iso")
826
827 if env['LIBLO']:
828     env.Append(CCFLAGS="-DHAVE_LIBLO")
829
830
831 #
832 # fix scons nitpickiness on APPLE
833 #
834
835
836 def prep_libcheck(topenv, libinfo):
837     if topenv['IS_OSX']:
838         #
839         # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default.
840         #            All libraries needed should be built against this location
841         if topenv['GTKOSX']:
842                 gtkroot = os.path.expanduser ("~");
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