17 EnsureSConsVersion(0, 96)
19 ardour_version = '2.3'
24 # Command-line options
27 opts = Options('scache.conf')
29 ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
30 ('WINDOWS_KEY', 'Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key', 'Mod4'),
31 BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
32 BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
33 BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
34 BoolOption('NATIVE_OSX_KEYS', 'Build key bindings file that matches OS X conventions', 0),
35 BoolOption('OLDFONTS', 'Old school font sizes', 0),
36 BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
37 BoolOption('STL_DEBUG', 'Set to build with Standard Template Library Debugging', 0),
38 PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
39 EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'leopard', 'none' ), ignorecase=2),
40 BoolOption('DMALLOC', 'Compile and link using the dmalloc library', 0),
41 BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0),
42 BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 1),
43 BoolOption('FREESOUND', 'Include Freesound database lookup', 0),
44 BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
45 BoolOption('LIBLO', 'Compile with support for liblo library', 1),
46 BoolOption('NLS', 'Set to turn on i18n support', 1),
47 PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
48 BoolOption('SURFACES', 'Build support for control surfaces', 1),
49 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),
50 BoolOption('UNIVERSAL', 'Compile as universal binary. Requires that external libraries are already universal.', 0),
51 BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
52 BoolOption('VST', 'Compile with support for VST', 0),
53 BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 1),
54 BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
55 BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
56 BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1)
59 #----------------------------------------------------------------------
60 # a handy helper that provides a way to merge compile/link information
61 # from multiple different "environments"
62 #----------------------------------------------------------------------
64 class LibraryInfo(Environment):
65 def __init__(self,*args,**kw):
66 Environment.__init__ (self,*args,**kw)
68 def Merge (self,others):
70 self.Append (LIBS = other.get ('LIBS',[]))
71 self.Append (LIBPATH = other.get ('LIBPATH', []))
72 self.Append (CPPPATH = other.get('CPPPATH', []))
73 self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
74 self.Append (CCFLAGS = other.get('CCFLAGS', []))
75 self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
76 self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
77 #doing LINKFLAGS breaks -framework
78 #doing LIBS break link order dependency
80 def ENV_update(self, src_ENV):
81 for k in src_ENV.keys():
82 if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
84 self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
86 self['ENV'][k]=src_ENV[k]
88 env = LibraryInfo (options = opts,
90 VERSION = ardour_version,
91 TARBALL='ardour-' + ardour_version + '.tar.bz2',
93 DISTTREE = '#ardour-' + ardour_version,
94 DISTCHECKDIR = '#ardour-' + ardour_version + '/check'
97 env.ENV_update(os.environ)
99 #----------------------------------------------------------------------
101 #----------------------------------------------------------------------
103 # Handy subst-in-file builder
106 def do_subst_in_file(targetfile, sourcefile, dict):
107 """Replace all instances of the keys of dict with their values.
108 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
109 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
112 f = open(sourcefile, 'rb')
116 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
117 for (k,v) in dict.items():
118 contents = re.sub(k, v, contents)
120 f = open(targetfile, 'wb')
124 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
127 def subst_in_file(target, source, env):
128 if not env.has_key('SUBST_DICT'):
129 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
130 d = dict(env['SUBST_DICT']) # copy it
131 for (k,v) in d.items():
133 d[k] = env.subst(v())
134 elif SCons.Util.is_String(v):
137 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
138 for (t,s) in zip(target, source):
139 return do_subst_in_file(str(t), str(s), d)
141 def subst_in_file_string(target, source, env):
142 """This is what gets printed on the console."""
143 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
144 for (t,s) in zip(target, source)])
146 def subst_emitter(target, source, env):
147 """Add dependency from substituted SUBST_DICT to target.
148 Returns original target, source tuple unchanged.
150 d = env['SUBST_DICT'].copy() # copy it
151 for (k,v) in d.items():
153 d[k] = env.subst(v())
154 elif SCons.Util.is_String(v):
156 Depends(target, SCons.Node.Python.Value(d))
157 # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
158 return target, source
160 subst_action = Action (subst_in_file, subst_in_file_string)
161 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
164 # internationalization
167 # po_builder: builder function to copy po files to the parent directory while updating them
169 # first source: .po file
170 # second source: .pot file
173 def po_builder(target,source,env):
174 os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
180 print 'Updating ' + str(target[0])
181 return os.spawnvp (os.P_WAIT, 'msgmerge', args)
183 po_bld = Builder (action = po_builder)
184 env.Append(BUILDERS = {'PoBuild' : po_bld})
186 # mo_builder: builder function for (binary) message catalogs (.mo)
188 # first source: .po file
191 def mo_builder(target,source,env):
195 target[0].get_path(),
198 return os.spawnvp (os.P_WAIT, 'msgfmt', args)
200 mo_bld = Builder (action = mo_builder)
201 env.Append(BUILDERS = {'MoBuild' : mo_bld})
203 # pot_builder: builder function for message templates (.pot)
205 # source: list of C/C++ etc. files to extract messages from
208 def pot_builder(target,source,env):
213 '-o', target[0].get_path(),
214 "--default-domain=" + env['PACKAGE'],
215 '--copyright-holder="Paul Davis"' ]
216 args += [ src.get_path() for src in source ]
218 return os.spawnvp (os.P_WAIT, 'xgettext', args)
220 pot_bld = Builder (action = pot_builder)
221 env.Append(BUILDERS = {'PotBuild' : pot_bld})
224 # utility function, not a builder
227 def i18n (buildenv, sources, installenv):
228 domain = buildenv['PACKAGE']
229 potfile = buildenv['POTFILE']
231 installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
233 p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
234 languages = [ po.replace ('.po', '') for po in p_oze ]
236 for po_file in p_oze:
237 buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
238 mo_file = po_file.replace (".po", ".mo")
239 installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
240 installenv.Alias ('msgupdate', buildenv.MoBuild (mo_file, po_file))
242 for lang in languages:
243 modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
244 moname = domain + '.mo'
245 installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
248 def fetch_svn_revision (path):
252 cmd += " | awk '/^Revision:/ { print $2}'"
253 return commands.getoutput (cmd)
255 def create_stored_revision (target = None, source = None, env = None):
256 if os.path.exists('.svn'):
257 rev = fetch_svn_revision ('.');
259 text = "#ifndef __ardour_svn_revision_h__\n"
260 text += "#define __ardour_svn_revision_h__\n"
261 text += "static const char* ardour_svn_revision = \"" + rev + "\";\n";
263 print '============> writing svn revision info to svn_revision.h\n'
264 o = file ('svn_revision.h', 'w')
268 print "Could not open svn_revision.h for writing\n"
271 print "You cannot use \"scons revision\" on without using a checked out"
272 print "copy of the Ardour source code repository"
276 # A generic builder for version.cc files
278 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
279 # note: assumes one source files, the header that declares the version variables
282 def version_builder (target, source, env):
284 text = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
285 text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
286 text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
289 o = file (target[0].get_path(), 'w')
293 print "Could not open", target[0].get_path(), " for writing\n"
296 text = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
297 text += "#define __" + env['DOMAIN'] + "_version_h__\n"
298 text += "extern const char* " + env['DOMAIN'] + "_revision;\n"
299 text += "extern int " + env['DOMAIN'] + "_major_version;\n"
300 text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
301 text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
302 text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
305 o = file (target[1].get_path(), 'w')
309 print "Could not open", target[1].get_path(), " for writing\n"
314 version_bld = Builder (action = version_builder)
315 env.Append (BUILDERS = {'VersionBuild' : version_bld})
318 # a builder that makes a hard link from the 'source' executable to a name with
319 # a "build ID" based on the most recent CVS activity that might be reasonably
320 # related to version activity. this relies on the idea that the SConscript
321 # file that builds the executable is updated with new version info and committed
322 # to the source code repository whenever things change.
325 def versioned_builder(target,source,env):
326 w, r = os.popen2( "LANG= svn info | awk '/^Revision:/ { print $2}'")
328 last_revision = r.readline().strip()
331 if last_revision == "":
332 print "No SVN info found - versioned executable cannot be built"
335 print "The current build ID is " + last_revision
337 tagged_executable = source[0].get_path() + '-' + last_revision
339 if os.path.exists (tagged_executable):
340 print "Replacing existing executable with the same build tag."
341 os.unlink (tagged_executable)
343 return os.link (source[0].get_path(), tagged_executable)
345 verbuild = Builder (action = versioned_builder)
346 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
349 # source tar file builder
352 def distcopy (target, source, env):
353 treedir = str (target[0])
357 except OSError, (errnum, strerror):
358 if errnum != errno.EEXIST:
359 print 'mkdir ', treedir, ':', strerror
363 # we don't know what characters might be in the file names
364 # so quote them all before passing them to the shell
366 all_files = ([ str(s) for s in source ])
367 cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
368 cmd += ' | (cd ' + treedir + ' && tar xf -)'
372 def tarballer (target, source, env):
373 cmd = 'tar -jcf ' + str (target[0]) + ' ' + str(source[0]) + " --exclude '*~'" + " --exclude .svn --exclude '.svn/*'"
374 print 'running ', cmd, ' ... '
378 dist_bld = Builder (action = distcopy,
379 target_factory = SCons.Node.FS.default_fs.Entry,
380 source_factory = SCons.Node.FS.default_fs.Entry,
383 tarball_bld = Builder (action = tarballer,
384 target_factory = SCons.Node.FS.default_fs.Entry,
385 source_factory = SCons.Node.FS.default_fs.Entry)
387 env.Append (BUILDERS = {'Distribute' : dist_bld})
388 env.Append (BUILDERS = {'Tarball' : tarball_bld})
391 # Make sure they know what they are doing
395 if os.path.isfile('.personal_use_only'):
396 print "Enabling VST support. Note that distributing a VST-enabled ardour\nis a violation of several different licences.\nBuild with VST=false if you intend to distribute ardour to others."
398 sys.stdout.write ("Are you building Ardour for personal use (rather than distribution to others)? [no]: ")
399 answer = sys.stdin.readline ()
400 answer = answer.rstrip().strip()
401 if answer == "yes" or answer == "y":
402 fh = open('.personal_use_only', 'w')
404 print "OK, VST support will be enabled"
406 print 'You cannot build Ardour with VST support for distribution to others.\nIt is a violation of several different licenses. Build with VST=false.'
409 if os.path.isfile('.personal_use_only'):
410 os.remove('.personal_use_only')
416 def pushEnvironment(context):
417 if os.environ.has_key('PATH'):
418 context.Append(PATH = os.environ['PATH'])
420 if os.environ.has_key('PKG_CONFIG_PATH'):
421 context.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
423 if os.environ.has_key('CC'):
424 context['CC'] = os.environ['CC']
426 if os.environ.has_key('CXX'):
427 context['CXX'] = os.environ['CXX']
429 if os.environ.has_key('DISTCC_HOSTS'):
430 context['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
431 context['ENV']['HOME'] = os.environ['HOME']
433 pushEnvironment (env)
435 #######################
436 # Dependency Checking #
437 #######################
441 'glib-2.0' : '2.10.1',
442 'gthread-2.0' : '2.10.1',
443 'gtk+-2.0' : '2.8.1',
444 'libxml-2.0' : '2.6.0',
445 'samplerate' : '0.1.0',
449 'libgnomecanvas-2.0' : '2.0'
452 def DependenciesRequiredMessage():
453 print 'You do not have the necessary dependencies required to build ardour'
454 print 'Please consult http://ardour.org/building for more information'
456 def CheckPKGConfig(context, version):
457 context.Message( 'Checking for pkg-config version >= %s... ' %version )
458 ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
459 context.Result( ret )
462 def CheckPKGVersion(context, name, version):
463 context.Message( 'Checking for %s... ' % name )
464 ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
465 context.Result( ret )
468 def CheckPKGExists(context, name):
469 context.Message ('Checking for %s...' % name)
470 ret = context.TryAction('pkg-config --exists %s' % name)[0]
474 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
475 'CheckPKGVersion' : CheckPKGVersion })
477 # I think a more recent version is needed on win32
478 min_pkg_config_version = '0.8.0'
480 if not conf.CheckPKGConfig(min_pkg_config_version):
481 print 'pkg-config >= %s not found.' % min_pkg_config_version
484 for pkg, version in deps.iteritems():
485 if not conf.CheckPKGVersion( pkg, version ):
486 print '%s >= %s not found.' %(pkg, version)
487 DependenciesRequiredMessage()
492 # ----------------------------------------------------------------------
493 # Construction environment setup
494 # ----------------------------------------------------------------------
498 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
500 #libraries['sndfile'] = LibraryInfo()
501 #libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
503 libraries['lrdf'] = LibraryInfo()
504 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
506 libraries['raptor'] = LibraryInfo()
507 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
509 libraries['samplerate'] = LibraryInfo()
510 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
512 conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
514 if conf.CheckPKGExists ('fftw3f'):
515 libraries['fftw3f'] = LibraryInfo()
516 libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
518 if conf.CheckPKGExists ('fftw3'):
519 libraries['fftw3'] = LibraryInfo()
520 libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
524 if env['FFT_ANALYSIS']:
526 # Check for fftw3 header as well as the library
529 conf = Configure(libraries['fftw3'])
531 if conf.CheckHeader ('fftw3.h') == False:
532 print ('Ardour cannot be compiled without the FFTW3 headers, which do not seem to be installed')
538 # Check for curl header as well as the library
541 conf = Configure(libraries['curl'])
543 if conf.CheckHeader ('curl/curl.h') == False:
544 print ('Ardour cannot be compiled without the curl headers, which do not seem to be installed')
548 libraries['curl'] = LibraryInfo()
549 libraries['curl'].ParseConfig('pkg-config --cflags --libs libcurl')
554 conf = env.Configure(custom_tests = { 'CheckPKGExists' : CheckPKGExists })
556 if conf.CheckPKGExists ('\"slv2 >= 0.6.0\"'):
557 libraries['slv2'] = LibraryInfo()
558 libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
559 env.Append (CCFLAGS="-DHAVE_LV2")
561 print 'Building Ardour with LV2 support requires SLV2 >= 0.6.0'
562 print 'WARNING: SLV2 not found, or too old. Ardour will be built without LV2 support.'
563 print 'Until the 2.4 release, Ardour requires SLV2 out of SVN.'
564 print 'Testing would be very much appreciated! svn co http://svn.drobilla.net/lad/slv2'
568 print 'LV2 support is not enabled. Build with \'scons LV2=1\' to enable.'
570 libraries['jack'] = LibraryInfo()
571 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
573 libraries['xml'] = LibraryInfo()
574 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
576 libraries['xslt'] = LibraryInfo()
577 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
579 libraries['glib2'] = LibraryInfo()
580 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
581 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
582 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
583 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
585 libraries['freetype2'] = LibraryInfo()
586 libraries['freetype2'].ParseConfig ('pkg-config --cflags --libs freetype2')
588 libraries['gtk2'] = LibraryInfo()
589 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
591 libraries['pango'] = LibraryInfo()
592 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
594 libraries['libgnomecanvas2'] = LibraryInfo()
595 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
597 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
599 # The Ardour Control Protocol Library
601 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
602 CPPPATH='#libs/surfaces/control_protocol')
604 # The Ardour backend/engine
606 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
607 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
608 libraries['pbd'] = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
609 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
612 # SCons should really do this for us
614 conf = env.Configure ()
616 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
618 print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
621 print "Congratulations, you have a functioning C++ compiler."
627 # Compiler flags and other system-dependent stuff
631 if env['GPROFILE'] == 1:
632 debug_flags = [ '-g', '-pg' ]
634 debug_flags = [ '-g' ]
636 # guess at the platform, used to define compiler flags
638 config_guess = os.popen("tools/config.guess").read()[:-1]
644 config = config_guess.split ("-")
646 print "system triple: " + config_guess
649 if env['DIST_TARGET'] == 'auto':
650 if config[config_arch] == 'apple':
651 # The [.] matches to the dot after the major version, "." would match any character
652 if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
653 env['DIST_TARGET'] = 'panther'
654 if re.search ("darwin8[.]", config[config_kernel]) != None:
655 env['DIST_TARGET'] = 'tiger'
657 env['DIST_TARGET'] = 'leopard'
659 if re.search ("x86_64", config[config_cpu]) != None:
660 env['DIST_TARGET'] = 'x86_64'
661 elif re.search("i[0-5]86", config[config_cpu]) != None:
662 env['DIST_TARGET'] = 'i386'
663 elif re.search("powerpc", config[config_cpu]) != None:
664 env['DIST_TARGET'] = 'powerpc'
666 env['DIST_TARGET'] = 'i686'
667 print "\n*******************************"
668 print "detected DIST_TARGET = " + env['DIST_TARGET']
669 print "*******************************\n"
672 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
674 # Apple/PowerPC optimization options
676 # -mcpu=7450 does not reliably work with gcc 3.*
678 if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
679 if config[config_arch] == 'apple':
680 ## opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
681 # to support g3s but still have some optimization for above
682 opt_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
684 opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
686 opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
687 opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
688 opt_flags.extend (["-Os"])
690 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':
692 build_host_supports_sse = 0
694 debug_flags.append ("-DARCH_X86")
695 opt_flags.append ("-DARCH_X86")
697 if config[config_kernel] == 'linux' :
699 if env['DIST_TARGET'] != 'i386':
701 flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
702 x86_flags = flag_line.split (": ")[1:][0].split ()
704 if "mmx" in x86_flags:
705 opt_flags.append ("-mmmx")
706 if "sse" in x86_flags:
707 build_host_supports_sse = 1
708 if "3dnow" in x86_flags:
709 opt_flags.append ("-m3dnow")
711 if config[config_cpu] == "i586":
712 opt_flags.append ("-march=i586")
713 elif config[config_cpu] == "i686":
714 opt_flags.append ("-march=i686")
716 if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
717 opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
718 debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
719 # end of processor-specific section
721 # optimization section
722 if env['FPU_OPTIMIZATION']:
723 if env['DIST_TARGET'] == 'tiger' or env['DIST_TARGET'] == 'leopard':
724 opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
725 debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
726 libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
727 elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
728 opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
729 debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
730 if env['DIST_TARGET'] == 'x86_64':
731 opt_flags.append ("-DUSE_X86_64_ASM")
732 debug_flags.append ("-DUSE_X86_64_ASM")
733 if build_host_supports_sse != 1:
734 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)"
735 # end optimization section
737 # handle x86/x86_64 libdir properly
739 if env['DIST_TARGET'] == 'x86_64':
740 env['LIBDIR']='lib64'
745 # a single way to test if we're on OS X
748 if env['DIST_TARGET'] in ['panther', 'tiger', 'leopard' ]:
750 # force tiger or later, to avoid issues on PPC which defaults
751 # back to 10.1 if we don't tell it otherwise.
752 env.Append (CCFLAGS="-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
757 # save off guessed arch element in an env
759 env.Append(CONFIG_ARCH=config[config_arch])
763 # ARCH="..." overrides all
766 if env['ARCH'] != '':
767 opt_flags = env['ARCH'].split()
770 # prepend boiler plate optimization flags
775 "-fomit-frame-pointer",
781 if env['DEBUG'] == 1:
782 env.Append(CCFLAGS=" ".join (debug_flags))
783 env.Append(LINKFLAGS=" ".join (debug_flags))
785 env.Append(CCFLAGS=" ".join (opt_flags))
786 env.Append(LINKFLAGS=" ".join (opt_flags))
788 if env['STL_DEBUG'] == 1:
789 env.Append(CXXFLAGS="-D_GLIBCXX_DEBUG")
791 if env['UNIVERSAL'] == 1:
792 env.Append(CCFLAGS="-arch i386 -arch ppc")
793 env.Append(LINKFLAGS="-arch i386 -arch ppc")
800 env.Append(CCFLAGS="-Wall")
801 env.Append(CXXFLAGS="-Woverloaded-virtual")
803 if env['EXTRA_WARN']:
804 env.Append(CCFLAGS="-Wextra -pedantic -ansi")
805 env.Append(CXXFLAGS="-ansi")
806 # env.Append(CFLAGS="-iso")
809 env.Append(CCFLAGS="-DHAVE_LIBLO")
813 # fix scons nitpickiness on APPLE
817 def prep_libcheck(topenv, libinfo):
820 # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default.
821 # All libraries needed should be built against this location
823 libinfo.Append(CPPPATH="/opt/gtk/include", LIBPATH="/opt/gtk/lib")
824 libinfo.Append(CXXFLAGS="-I/opt/gtk/include", LINKFLAGS="-L/opt/gtk/lib")
825 libinfo.Append(CPPPATH="/opt/local/include", LIBPATH="/opt/local/lib")
826 libinfo.Append(CXXFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
828 prep_libcheck(env, env)
832 # these are part of the Ardour source tree because they are C++
835 libraries['vamp'] = LibraryInfo (LIBS='vampsdk',
836 LIBPATH='#libs/vamp-sdk',
837 CPPPATH='#libs/vamp-sdk')
838 libraries['vamphost'] = LibraryInfo (LIBS='vamphostsdk',
839 LIBPATH='#libs/vamp-sdk',
840 CPPPATH='#libs/vamp-sdk')
842 env['RUBBERBAND'] = False
844 conf = Configure (env)
846 if conf.CheckHeader ('fftw3.h'):
847 env['RUBBERBAND'] = True
848 libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
849 LIBPATH='#libs/rubberband',
850 CPPPATH='#libs/rubberband',
851 CCFLAGS='-DUSE_RUBBERBAND')
854 print "-------------------------------------------------------------------------"
855 print "You do not have the FFTW single-precision development package installed."
856 print "This prevents Ardour from using the Rubberband library for timestretching"
857 print "and pitchshifting. It will fall back on SoundTouch for timestretch, and "
858 print "pitchshifting will not be available."
859 print "-------------------------------------------------------------------------"
867 libraries['usb'] = LibraryInfo ()
868 prep_libcheck(env, libraries['usb'])
870 conf = Configure (libraries['usb'])
871 if conf.CheckLib ('usb', 'usb_interrupt_write'):
876 # check for linux/input.h while we're at it for powermate
877 if conf.CheckHeader('linux/input.h'):
878 have_linux_input = True
880 have_linux_input = False
882 libraries['usb'] = conf.Finish ()
887 libraries['flac'] = LibraryInfo ()
888 prep_libcheck(env, libraries['flac'])
889 libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
892 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
893 # since the version of libsndfile we have internally does not support
894 # the new API that libFLAC has adopted
897 conf = Configure (libraries['flac'])
898 if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
899 conf.env.Append(CCFLAGS='-DHAVE_FLAC')
904 libraries['flac'] = conf.Finish ()
906 # or if that fails...
907 #libraries['flac'] = LibraryInfo (LIBS='FLAC')
909 # boost (we don't link against boost, just use some header files)
911 libraries['boost'] = LibraryInfo ()
912 prep_libcheck(env, libraries['boost'])
913 libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
914 conf = Configure (libraries['boost'])
915 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
916 print "Boost header files do not appear to be installed."
919 libraries['boost'] = conf.Finish ()
925 libraries['lo'] = LibraryInfo ()
926 prep_libcheck(env, libraries['lo'])
928 conf = Configure (libraries['lo'])
929 if conf.CheckLib ('lo', 'lo_server_new') == False:
930 print "liblo does not appear to be installed."
933 libraries['lo'] = conf.Finish ()
938 libraries['dmalloc'] = LibraryInfo ()
939 prep_libcheck(env, libraries['dmalloc'])
942 # look for the threaded version
945 conf = Configure (libraries['dmalloc'])
946 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
947 have_libdmalloc = True
949 have_libdmalloc = False
951 libraries['dmalloc'] = conf.Finish ()
954 # ensure FREEDESKTOP target is doable..
957 conf = env.Configure ()
958 if env['FREEDESKTOP']:
959 have_update_mime_database = conf.TryAction (Action ('update-mime-database -v'))
960 if have_update_mime_database[0] != 1:
961 print "Warning. You have no update-mime-database command in your PATH. FREEDESKTOP is now disabled."
962 env['FREEDESKTOP'] = 0
963 have_gtk_update_icon_cache = conf.TryAction (Action ('gtk-update-icon-cache -?'))
964 if have_gtk_update_icon_cache[0] != 1:
965 print "Warning. You have no gtk-update-icon-cache command in your PATH. FREEDESKTOP is now disabled."
966 env['FREEDESKTOP'] = 0
967 have_update_desktop_database = conf.TryAction (Action ('update-desktop-database -?'))
968 if have_update_desktop_database[0] != 1:
969 print "Warning. You have no update-desktop-database command in your PATH. FREEDESKTOP is now disabled."
970 env['FREEDESKTOP'] = 0
974 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
977 conf = Configure(env)
979 if conf.CheckCHeader('alsa/asoundlib.h'):
980 libraries['sysmidi'] = LibraryInfo (LIBS='asound')
981 env['SYSMIDI'] = 'ALSA Sequencer'
982 subst_dict['%MIDITAG%'] = "seq"
983 subst_dict['%MIDITYPE%'] = "alsa/sequencer"
984 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
985 # this line is needed because scons can't handle -framework in ParseConfig() yet.
987 # We need Carbon as well as the rest
988 libraries['sysmidi'] = LibraryInfo (
989 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
991 libraries['sysmidi'] = LibraryInfo (
992 LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
993 env['SYSMIDI'] = 'CoreMIDI'
994 subst_dict['%MIDITAG%'] = "ardour"
995 subst_dict['%MIDITYPE%'] = "coremidi"
997 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."
1006 'sigc++-2.0' : '2.0',
1007 'gtkmm-2.4' : '2.8',
1008 'libgnomecanvasmm-2.6' : '2.12.0'
1011 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
1012 'CheckPKGVersion' : CheckPKGVersion })
1014 for pkg, version in syslibdeps.iteritems():
1015 if not conf.CheckPKGVersion( pkg, version ):
1016 print '%s >= %s not found.' %(pkg, version)
1017 DependenciesRequiredMessage()
1022 libraries['sigc2'] = LibraryInfo()
1023 libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
1024 libraries['glibmm2'] = LibraryInfo()
1025 libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
1026 libraries['cairomm'] = LibraryInfo()
1027 libraries['cairomm'].ParseConfig('pkg-config --cflags --libs cairomm-1.0')
1028 libraries['gdkmm2'] = LibraryInfo()
1029 libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
1030 libraries['gtkmm2'] = LibraryInfo()
1031 libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
1032 libraries['atkmm'] = LibraryInfo()
1033 libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
1034 libraries['pangomm'] = LibraryInfo()
1035 libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
1036 libraries['libgnomecanvasmm'] = LibraryInfo()
1037 libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
1040 # cannot use system one for the time being
1043 libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1044 LIBPATH='#libs/libsndfile',
1045 CPPPATH=['#libs/libsndfile/src'])
1047 # libraries['libglademm'] = LibraryInfo()
1048 # libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
1050 # libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
1051 libraries['soundtouch'] = LibraryInfo()
1052 #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
1053 # Comment the previous line and uncomment this for Debian:
1054 libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
1056 libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1057 LIBPATH='#libs/appleutility',
1058 CPPPATH='#libs/appleutility')
1070 'libs/vamp-plugins/',
1071 # these are unconditionally included but have
1072 # tests internally to avoid compilation etc
1076 # this is unconditionally included but has
1077 # tests internally to avoid compilation etc
1078 # if COREAUDIO is not set
1083 # 'libs/flowcanvas',
1090 libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
1091 LIBPATH='#libs/sigc++2',
1092 CPPPATH='#libs/sigc++2')
1093 libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
1094 LIBPATH='#libs/glibmm2',
1095 CPPPATH='#libs/glibmm2')
1096 libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
1097 LIBPATH='#libs/gtkmm2/pango',
1098 CPPPATH='#libs/gtkmm2/pango')
1099 libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
1100 LIBPATH='#libs/gtkmm2/atk',
1101 CPPPATH='#libs/gtkmm2/atk')
1102 libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
1103 LIBPATH='#libs/gtkmm2/gdk',
1104 CPPPATH='#libs/gtkmm2/gdk')
1105 libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
1106 LIBPATH="#libs/gtkmm2/gtk",
1107 CPPPATH='#libs/gtkmm2/gtk/')
1108 libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
1109 LIBPATH='#libs/libgnomecanvasmm',
1110 CPPPATH='#libs/libgnomecanvasmm')
1112 libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
1113 LIBPATH='#libs/soundtouch',
1114 CPPPATH=['#libs', '#libs/soundtouch'])
1115 libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
1116 LIBPATH='#libs/libsndfile',
1117 CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
1118 # libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
1119 # LIBPATH='#libs/libglademm',
1120 # CPPPATH='#libs/libglademm')
1121 libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
1122 LIBPATH='#libs/appleutility',
1123 CPPPATH='#libs/appleutility')
1136 'libs/vamp-plugins/',
1137 # these are unconditionally included but have
1138 # tests internally to avoid compilation etc
1142 # this is unconditionally included but has
1143 # tests internally to avoid compilation etc
1144 # if COREAUDIO is not set
1150 'libs/gtkmm2/pango',
1154 'libs/libgnomecanvasmm',
1161 # * always build the LGPL control protocol lib, since we link against it from libardour
1162 # * ditto for generic MIDI
1163 # * tranzport checks whether it should build internally, but we need here so that
1164 # its included in the tarball
1167 surface_subdirs = [ 'libs/surfaces/control_protocol',
1168 'libs/surfaces/generic_midi',
1169 'libs/surfaces/tranzport',
1170 'libs/surfaces/mackie',
1171 'libs/surfaces/powermate'
1176 env['TRANZPORT'] = 1
1178 env['TRANZPORT'] = 0
1179 print 'Disabled building Tranzport code because libusb could not be found'
1181 if have_linux_input:
1182 env['POWERMATE'] = 1
1184 env['POWERMATE'] = 0
1185 print 'Disabled building Powermate code because linux/input.h could not be found'
1187 if os.access ('libs/surfaces/sony9pin', os.F_OK):
1188 surface_subdirs += [ 'libs/surfaces/sony9pin' ]
1190 env['POWERMATE'] = 0
1191 env['TRANZPORT'] = 0
1194 # timestretch libraries
1197 timefx_subdirs = ['libs/soundtouch']
1198 if env['RUBBERBAND']:
1199 timefx_subdirs += ['libs/rubberband']
1201 opts.Save('scache.conf', env)
1202 Help(opts.GenerateHelpText(env))
1204 final_prefix = '$PREFIX'
1207 install_prefix = '$DESTDIR/$PREFIX'
1209 install_prefix = env['PREFIX']
1211 subst_dict['%INSTALL_PREFIX%'] = install_prefix;
1212 subst_dict['%FINAL_PREFIX%'] = final_prefix;
1213 subst_dict['%PREFIX%'] = final_prefix;
1215 if env['PREFIX'] == '/usr':
1216 final_config_prefix = '/etc'
1218 final_config_prefix = env['PREFIX'] + '/etc'
1220 config_prefix = '$DESTDIR' + final_config_prefix
1223 # everybody needs this
1226 env.Merge ([ libraries['core'] ])
1233 conf = Configure (env)
1235 nls_error = 'This system is not configured for internationalized applications. An english-only version will be built:'
1236 print 'Checking for internationalization support ...'
1237 have_gettext = conf.TryAction(Action('xgettext --version'))
1238 if have_gettext[0] != 1:
1239 nls_error += ' No xgettext command.'
1242 print "Found xgettext"
1244 have_msgmerge = conf.TryAction(Action('msgmerge --version'))
1245 if have_msgmerge[0] != 1:
1246 nls_error += ' No msgmerge command.'
1249 print "Found msgmerge"
1251 if not conf.CheckCHeader('libintl.h'):
1252 nls_error += ' No libintl.h.'
1258 print "International version will be built."
1262 env.Append(CCFLAGS="-DENABLE_NLS")
1264 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n ardour_version subst_dict use_flac')
1267 # the configuration file may be system dependent
1270 conf = env.Configure ()
1272 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
1273 subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
1274 subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
1276 subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
1277 subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
1279 # posix_memalign available
1280 if not conf.CheckFunc('posix_memalign'):
1281 print 'Did not find posix_memalign(), using malloc'
1282 env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
1287 # generate the per-user and system rc files from the same source
1289 sysrcbuild = env.SubstInFile ('ardour_system.rc','ardour.rc.in', SUBST_DICT = subst_dict)
1291 # add to the substitution dictionary
1293 subst_dict['%VERSION%'] = ardour_version[0:3]
1294 subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
1295 subst_dict['%REVISION_STRING%'] = ''
1296 if os.path.exists('.svn'):
1297 subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
1299 # specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
1301 the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
1302 remove_ardour = env.Command ('frobnicatory_decoy2', [],
1303 [ Delete ('$PREFIX/etc/ardour2'),
1304 Delete ('$PREFIX/lib/ardour2'),
1305 Delete ('$PREFIX/bin/ardour2'),
1306 Delete ('$PREFIX/share/ardour2')])
1308 env.Alias('revision', the_revision)
1309 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
1310 env.Alias('uninstall', remove_ardour)
1312 Default (sysrcbuild)
1316 Precious (env['DISTTREE'])
1318 env.Distribute (env['DISTTREE'],
1319 [ 'SConstruct', 'svn_revision.h',
1320 'COPYING', 'PACKAGER_README', 'README',
1322 'tools/config.guess',
1323 'icons/icon/ardour_icon_mac_mask.png',
1324 'icons/icon/ardour_icon_mac.png',
1325 'icons/icon/ardour_icon_tango_16px_blue.png',
1326 'icons/icon/ardour_icon_tango_16px_red.png',
1327 'icons/icon/ardour_icon_tango_22px_blue.png',
1328 'icons/icon/ardour_icon_tango_22px_red.png',
1329 'icons/icon/ardour_icon_tango_32px_blue.png',
1330 'icons/icon/ardour_icon_tango_32px_red.png',
1331 'icons/icon/ardour_icon_tango_48px_blue.png',
1332 'icons/icon/ardour_icon_tango_48px_red.png'
1334 glob.glob ('DOCUMENTATION/AUTHORS*') +
1335 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
1336 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
1337 glob.glob ('DOCUMENTATION/BUILD*') +
1338 glob.glob ('DOCUMENTATION/FAQ*') +
1339 glob.glob ('DOCUMENTATION/README*')
1342 srcdist = env.Tarball(env['TARBALL'], [ env['DISTTREE'], the_revision ])
1343 env.Alias ('srctar', srcdist)
1346 # don't leave the distree around
1349 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
1350 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
1356 for subdir in coredirs:
1357 SConscript (subdir + '/SConscript')
1359 for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
1360 for subdir in sublistdir:
1361 SConscript (subdir + '/SConscript')
1364 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])