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