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