no more disabling strict aliasing
[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     "-pipe"
665     ]
666
667 if env['DEBUG'] == 1:
668     env.Append(CCFLAGS=" ".join (debug_flags))
669     env.Append(LINKFLAGS=" ".join (debug_flags))
670 else:
671     env.Append(CCFLAGS=" ".join (opt_flags))
672     env.Append(LINKFLAGS=" ".join (opt_flags))
673
674 if env['UNIVERSAL'] == 1:
675     env.Append(CCFLAGS="-arch i386 -arch ppc")
676     env.Append(LINKFLAGS="-arch i386 -arch ppc")
677
678 #
679 # warnings flags
680 #
681
682 env.Append(CCFLAGS="-Wall")
683 env.Append(CXXFLAGS="-Woverloaded-virtual")
684
685 if env['EXTRA_WARN']:
686     env.Append(CCFLAGS="-Wextra -pedantic -ansi")
687     env.Append(CXXFLAGS="-ansi")
688 #    env.Append(CFLAGS="-iso")
689
690 if env['LIBLO']:
691     env.Append(CCFLAGS="-DHAVE_LIBLO")
692
693
694 #
695 # fix scons nitpickiness on APPLE
696 #
697
698
699 def prep_libcheck(topenv, libinfo):
700     if topenv['DIST_TARGET'] == 'panther' or topenv['DIST_TARGET'] == 'tiger':
701         libinfo.Append(CCFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
702
703 prep_libcheck(env, env)
704
705 #
706 # Check for libusb
707
708 libraries['usb'] = LibraryInfo ()
709 prep_libcheck(env, libraries['usb'])
710
711 conf = Configure (libraries['usb'])
712 if conf.CheckLib ('usb', 'usb_interrupt_write'):
713     have_libusb = True
714 else:
715     have_libusb = False
716
717 libraries['usb'] = conf.Finish ()
718
719 #
720 # Check for FLAC
721
722 libraries['flac'] = LibraryInfo ()
723 prep_libcheck(env, libraries['flac'])
724 libraries['flac'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local/lib")
725
726 conf = Configure (libraries['flac'])
727 conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new', language='CXX')
728 libraries['flac'] = conf.Finish ()
729
730 # or if that fails...
731 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
732
733 # boost (we don't link against boost, just use some header files)
734
735 libraries['boost'] = LibraryInfo ()
736 prep_libcheck(env, libraries['boost'])
737 libraries['boost'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local/lib")
738 conf = Configure (libraries['boost'])
739 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
740         print "Boost header files do not appear to be installed."
741         sys.exit (1)
742     
743 libraries['boost'] = conf.Finish ()
744
745 #
746 # Check for liblo
747
748 if env['LIBLO']:
749     libraries['lo'] = LibraryInfo ()
750     prep_libcheck(env, libraries['lo'])
751
752     conf = Configure (libraries['lo'])
753     if conf.CheckLib ('lo', 'lo_server_new') == False:
754         print "liblo does not appear to be installed."
755         sys.exit (1)
756     
757     libraries['lo'] = conf.Finish ()
758
759 #
760 # Check for dmalloc
761
762 libraries['dmalloc'] = LibraryInfo ()
763 prep_libcheck(env, libraries['dmalloc'])
764
765 #
766 # look for the threaded version
767 #
768
769 conf = Configure (libraries['dmalloc'])
770 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
771     have_libdmalloc = True
772 else:
773     have_libdmalloc = False
774
775 libraries['dmalloc'] = conf.Finish ()
776
777 #
778 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
779 #
780
781 conf = Configure(env)
782
783 if conf.CheckCHeader('alsa/asoundlib.h'):
784     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
785     env['SYSMIDI'] = 'ALSA Sequencer'
786     subst_dict['%MIDITAG%'] = "seq"
787     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
788 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
789     # this line is needed because scons can't handle -framework in ParseConfig() yet.
790     libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load')
791     env['SYSMIDI'] = 'CoreMIDI'
792     subst_dict['%MIDITAG%'] = "ardour"
793     subst_dict['%MIDITYPE%'] = "coremidi"
794 else:
795     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."
796     sys.exit (1)
797
798 env = conf.Finish()
799
800 if env['SYSLIBS']:
801
802     syslibdeps = \
803     {
804         'sigc++-2.0'           : '2.0',
805         'gtkmm-2.4'            : '2.8',
806         'libgnomecanvasmm-2.6' : '2.12.0'
807     }
808
809     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
810                     'CheckPKGVersion' : CheckPKGVersion })
811
812     for pkg, version in syslibdeps.iteritems():
813         if not conf.CheckPKGVersion( pkg, version ):
814             print '%s >= %s not found.' %(pkg, version)
815             DependenciesRequiredMessage()
816             Exit(1)
817         
818     env = conf.Finish()
819     
820     libraries['sigc2'] = LibraryInfo()
821     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
822     libraries['glibmm2'] = LibraryInfo()
823     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
824     libraries['gdkmm2'] = LibraryInfo()
825     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
826     libraries['gtkmm2'] = LibraryInfo()
827     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
828     libraries['atkmm'] = LibraryInfo()
829     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
830     libraries['pangomm'] = LibraryInfo()
831     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
832     libraries['libgnomecanvasmm'] = LibraryInfo()
833     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
834
835 #
836 # cannot use system one for the time being
837 #
838     
839     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
840                                     LIBPATH='#libs/libsndfile',
841                                     CPPPATH=['#libs/libsndfile/src'])
842
843 #    libraries['libglademm'] = LibraryInfo()
844 #    libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
845
846 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
847     libraries['soundtouch'] = LibraryInfo()
848     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
849     # Comment the previous line and uncomment this for Debian:
850         #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
851
852     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
853                                             LIBPATH='#libs/appleutility',
854                                             CPPPATH='#libs/appleutility')
855     
856     coredirs = [
857         'templates'
858     ]
859     
860     subdirs = [
861         'libs/libsndfile',
862         'libs/pbd',
863         'libs/midi++2',
864         'libs/ardour',
865     # these are unconditionally included but have
866     # tests internally to avoid compilation etc
867     # if VST is not set
868         'libs/fst',
869         'vst',
870     # this is unconditionally included but has
871     # tests internally to avoid compilation etc
872     # if COREAUDIO is not set
873         'libs/appleutility'
874         ]
875     
876     gtk_subdirs = [
877 #        'libs/flowcanvas',
878         'libs/gtkmm2ext',
879         'gtk2_ardour',
880         'libs/clearlooks'
881         ]
882
883 else:
884     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
885                                     LIBPATH='#libs/sigc++2',
886                                     CPPPATH='#libs/sigc++2')
887     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
888                                     LIBPATH='#libs/glibmm2',
889                                     CPPPATH='#libs/glibmm2')
890     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
891                                     LIBPATH='#libs/gtkmm2/pango',
892                                     CPPPATH='#libs/gtkmm2/pango')
893     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
894                                      LIBPATH='#libs/gtkmm2/atk',
895                                      CPPPATH='#libs/gtkmm2/atk')
896     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
897                                       LIBPATH='#libs/gtkmm2/gdk',
898                                       CPPPATH='#libs/gtkmm2/gdk')
899     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
900                                      LIBPATH="#libs/gtkmm2/gtk",
901                                      CPPPATH='#libs/gtkmm2/gtk/')
902     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
903                                                 LIBPATH='#libs/libgnomecanvasmm',
904                                                 CPPPATH='#libs/libgnomecanvasmm')
905     
906     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
907                                           LIBPATH='#libs/soundtouch',
908                                           CPPPATH=['#libs', '#libs/soundtouch'])
909     libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
910                                     LIBPATH='#libs/libsndfile',
911                                     CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
912 #    libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
913 #                                          LIBPATH='#libs/libglademm',
914 #                                          CPPPATH='#libs/libglademm')
915     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
916                                             LIBPATH='#libs/appleutility',
917                                             CPPPATH='#libs/appleutility')
918
919     coredirs = [
920         'libs/soundtouch',
921         'templates'
922     ]
923     
924     subdirs = [
925         'libs/sigc++2',
926         'libs/libsndfile',
927         'libs/pbd',
928         'libs/midi++2',
929         'libs/ardour',
930     # these are unconditionally included but have
931     # tests internally to avoid compilation etc
932     # if VST is not set
933         'libs/fst',
934         'vst',
935     # this is unconditionally included but has
936     # tests internally to avoid compilation etc
937     # if COREAUDIO is not set
938         'libs/appleutility'
939         ]
940     
941     gtk_subdirs = [
942         'libs/glibmm2',
943         'libs/gtkmm2/pango',
944         'libs/gtkmm2/atk',
945         'libs/gtkmm2/gdk',
946         'libs/gtkmm2/gtk',
947         'libs/libgnomecanvasmm',
948 #       'libs/flowcanvas',
949         'libs/gtkmm2ext',
950         'gtk2_ardour',
951         'libs/clearlooks'
952         ]
953
954 #
955 # * always build the LGPL control protocol lib, since we link against it from libardour
956 # * ditto for generic MIDI
957 # * tranzport checks whether it should build internally, but we need here so that
958 #   its included in the tarball
959 #
960
961 surface_subdirs = [ 'libs/surfaces/control_protocol', 'libs/surfaces/generic_midi', 'libs/surfaces/tranzport', 'libs/surfaces/mackie' ]
962
963 if env['SURFACES']:
964     if have_libusb:
965         env['TRANZPORT'] = 1
966     else:
967         env['TRANZPORT'] = 0
968         print 'Disabled building Tranzport code because libusb could not be found'
969     if os.access ('libs/surfaces/sony9pin', os.F_OK):
970         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
971
972 opts.Save('scache.conf', env)
973 Help(opts.GenerateHelpText(env))
974
975 if os.environ.has_key('PATH'):
976     env.Append(PATH = os.environ['PATH'])
977
978 if os.environ.has_key('PKG_CONFIG_PATH'):
979     env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
980
981 if os.environ.has_key('CC'):
982     env['CC'] = os.environ['CC']
983
984 if os.environ.has_key('CXX'):
985     env['CXX'] = os.environ['CXX']
986
987 if os.environ.has_key('DISTCC_HOSTS'):
988     env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
989     env['ENV']['HOME'] = os.environ['HOME']
990
991 final_prefix = '$PREFIX'
992
993 if env['DESTDIR'] :
994     install_prefix = '$DESTDIR/$PREFIX'
995 else:
996     install_prefix = env['PREFIX']
997
998 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
999 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1000 subst_dict['%PREFIX%'] = final_prefix;
1001
1002 if env['PREFIX'] == '/usr':
1003     final_config_prefix = '/etc'
1004 else:
1005     final_config_prefix = env['PREFIX'] + '/etc'
1006
1007 config_prefix = '$DESTDIR' + final_config_prefix
1008
1009 #
1010 # everybody needs this
1011 #
1012
1013 env.Merge ([ libraries['core'] ])
1014
1015
1016 #
1017 # i18n support
1018 #
1019
1020 conf = Configure (env)
1021 if env['NLS']:
1022     nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
1023     print 'Checking for internationalization support ...'
1024     have_gettext = conf.TryAction(Action('xgettext --version'))
1025     if have_gettext[0] != 1:
1026         nls_error += ' No xgettext command.'
1027         env['NLS'] = 0
1028     else:
1029         print "Found xgettext"
1030     
1031     have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1032     if have_msgmerge[0] != 1:
1033         nls_error += ' No msgmerge command.'
1034         env['NLS'] = 0
1035     else:
1036         print "Found msgmerge"
1037     
1038     if not conf.CheckCHeader('libintl.h'):
1039         nls_error += ' No libintl.h.'
1040         env['NLS'] = 0
1041         
1042     if env['NLS'] == 0:
1043         print nls_error
1044     else:
1045         print "International version will be built."
1046 env = conf.Finish()
1047
1048 if env['NLS'] == 1:
1049     env.Append(CCFLAGS="-DENABLE_NLS")
1050
1051 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict')
1052
1053 #
1054 # the configuration file may be system dependent
1055 #
1056
1057 conf = env.Configure ()
1058
1059 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1060     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1061     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1062 else:
1063     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1064     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1065
1066 # posix_memalign available
1067 if not conf.CheckFunc('posix_memalign'):
1068     print 'Did not find posix_memalign(), using malloc'
1069     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1070
1071
1072 env = conf.Finish()
1073
1074 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1075 subst_dict['%VERSION%'] = ardour_version[0:3]
1076 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1077 subst_dict['%REVISION_STRING%'] = ''
1078 if os.path.exists('.svn'):
1079     subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1080
1081 specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1082
1083 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1084
1085 env.Alias('revision', the_revision)
1086 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
1087 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.rc'))
1088
1089 Default (rcbuild)
1090
1091 # source tarball
1092
1093 Precious (env['DISTTREE'])
1094
1095 env.Distribute (env['DISTTREE'],
1096                [ 'SConstruct', 'svn_revision.h',
1097                   'COPYING', 'PACKAGER_README', 'README',
1098                   'ardour.rc.in',
1099                   'ardour.spec',
1100                   'ardour_system.rc',
1101                   'tools/config.guess',
1102                   'icons/icon/ardour_icon_mac_mask.png',
1103                   'icons/icon/ardour_icon_mac.png',
1104                   'icons/icon/ardour_icon_tango_16px_blue.png',
1105                   'icons/icon/ardour_icon_tango_16px_red.png',
1106                   'icons/icon/ardour_icon_tango_22px_blue.png',
1107                   'icons/icon/ardour_icon_tango_22px_red.png',
1108                   'icons/icon/ardour_icon_tango_32px_blue.png',
1109                   'icons/icon/ardour_icon_tango_32px_red.png',
1110                   'icons/icon/ardour_icon_tango_48px_blue.png',
1111                   'icons/icon/ardour_icon_tango_48px_red.png'
1112                   ] +
1113                 glob.glob ('DOCUMENTATION/AUTHORS*') +
1114                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
1115                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
1116                 glob.glob ('DOCUMENTATION/BUILD*') +
1117                 glob.glob ('DOCUMENTATION/FAQ*') +
1118                 glob.glob ('DOCUMENTATION/README*')
1119                 )
1120
1121 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1122 env.Alias ('srctar', srcdist)
1123
1124 #
1125 # don't leave the distree around
1126 #
1127
1128 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1129 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1130
1131 #
1132 # the subdirs
1133 #
1134
1135 for subdir in coredirs:
1136     SConscript (subdir + '/SConscript')
1137
1138 for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]:
1139     for subdir in sublistdir:
1140         SConscript (subdir + '/SConscript')
1141
1142 # cleanup
1143 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
1144