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