16 EnsureSConsVersion(0, 96)
23 # Command-line options
26 opts = Options('scache.conf')
28 ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
29 BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
30 BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
31 BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
32 PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
33 EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'none' ), ignorecase=2),
34 BoolOption('DMALLOC', 'Compile and link using the dmalloc library', 0),
35 BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0),
36 BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 0),
37 BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
38 BoolOption('LIBLO', 'Compile with support for liblo library', 1),
39 BoolOption('NLS', 'Set to turn on i18n support', 1),
40 PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
41 BoolOption('SURFACES', 'Build support for control surfaces', 0),
42 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),
43 BoolOption('VERSIONED', 'Add version information to ardour/gtk executable name inside the build directory', 0),
44 BoolOption('VST', 'Compile with support for VST', 0)
47 #----------------------------------------------------------------------
48 # a handy helper that provides a way to merge compile/link information
49 # from multiple different "environments"
50 #----------------------------------------------------------------------
52 class LibraryInfo(Environment):
53 def __init__(self,*args,**kw):
54 Environment.__init__ (self,*args,**kw)
56 def Merge (self,others):
58 self.Append (LIBS = other.get ('LIBS',[]))
59 self.Append (LIBPATH = other.get ('LIBPATH', []))
60 self.Append (CPPPATH = other.get('CPPPATH', []))
61 self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
62 self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
63 self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
64 #doing LINKFLAGS breaks -framework
65 #doing LIBS break link order dependency
67 def ENV_update(self, src_ENV):
68 for k in src_ENV.keys():
69 if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
71 self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
73 self['ENV'][k]=src_ENV[k]
75 env = LibraryInfo (options = opts,
78 TARBALL='ardour-' + version + '.tar.bz2',
80 DISTTREE = '#ardour-' + version,
81 DISTCHECKDIR = '#ardour-' + version + '/check'
84 env.ENV_update(os.environ)
86 #----------------------------------------------------------------------
88 #----------------------------------------------------------------------
90 # Handy subst-in-file builder
93 def do_subst_in_file(targetfile, sourcefile, dict):
94 """Replace all instances of the keys of dict with their values.
95 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
96 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
99 f = open(sourcefile, 'rb')
103 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
104 for (k,v) in dict.items():
105 contents = re.sub(k, v, contents)
107 f = open(targetfile, 'wb')
111 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
114 def subst_in_file(target, source, env):
115 if not env.has_key('SUBST_DICT'):
116 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
117 d = dict(env['SUBST_DICT']) # copy it
118 for (k,v) in d.items():
120 d[k] = env.subst(v())
121 elif SCons.Util.is_String(v):
124 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
125 for (t,s) in zip(target, source):
126 return do_subst_in_file(str(t), str(s), d)
128 def subst_in_file_string(target, source, env):
129 """This is what gets printed on the console."""
130 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
131 for (t,s) in zip(target, source)])
133 def subst_emitter(target, source, env):
134 """Add dependency from substituted SUBST_DICT to target.
135 Returns original target, source tuple unchanged.
137 d = env['SUBST_DICT'].copy() # copy it
138 for (k,v) in d.items():
140 d[k] = env.subst(v())
141 elif SCons.Util.is_String(v):
143 Depends(target, SCons.Node.Python.Value(d))
144 # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
145 return target, source
147 subst_action = Action (subst_in_file, subst_in_file_string)
148 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
151 # internationalization
154 # po_builder: builder function to copy po files to the parent directory while updating them
156 # first source: .po file
157 # second source: .pot file
160 def po_builder(target,source,env):
161 os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
167 print 'Updating ' + str(target[0])
168 return os.spawnvp (os.P_WAIT, 'msgmerge', args)
170 po_bld = Builder (action = po_builder)
171 env.Append(BUILDERS = {'PoBuild' : po_bld})
173 # mo_builder: builder function for (binary) message catalogs (.mo)
175 # first source: .po file
178 def mo_builder(target,source,env):
182 target[0].get_path(),
185 return os.spawnvp (os.P_WAIT, 'msgfmt', args)
187 mo_bld = Builder (action = mo_builder)
188 env.Append(BUILDERS = {'MoBuild' : mo_bld})
190 # pot_builder: builder function for message templates (.pot)
192 # source: list of C/C++ etc. files to extract messages from
195 def pot_builder(target,source,env):
200 '-o', target[0].get_path(),
201 "--default-domain=" + env['PACKAGE'],
202 '--copyright-holder="Paul Davis"' ]
203 args += [ src.get_path() for src in source ]
205 return os.spawnvp (os.P_WAIT, 'xgettext', args)
207 pot_bld = Builder (action = pot_builder)
208 env.Append(BUILDERS = {'PotBuild' : pot_bld})
211 # utility function, not a builder
214 def i18n (buildenv, sources, installenv):
215 domain = buildenv['PACKAGE']
216 potfile = buildenv['POTFILE']
218 installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
220 p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
221 languages = [ po.replace ('.po', '') for po in p_oze ]
223 for po_file in p_oze:
224 buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
225 mo_file = po_file.replace (".po", ".mo")
226 installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
228 for lang in languages:
229 modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
230 moname = domain + '.mo'
231 installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
234 # A generic builder for version.cc files
236 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
237 # note: assumes one source files, the header that declares the version variables
239 def version_builder (target, source, env):
240 text = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
241 text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
242 text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
245 o = file (target[0].get_path(), 'w')
249 print "Could not open", target[0].get_path(), " for writing\n"
252 text = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
253 text += "#define __" + env['DOMAIN'] + "_version_h__\n"
254 text += "extern int " + env['DOMAIN'] + "_major_version;\n"
255 text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
256 text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
257 text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
260 o = file (target[1].get_path(), 'w')
264 print "Could not open", target[1].get_path(), " for writing\n"
269 version_bld = Builder (action = version_builder)
270 env.Append (BUILDERS = {'VersionBuild' : version_bld})
273 # a builder that makes a hard link from the 'source' executable to a name with
274 # a "build ID" based on the most recent CVS activity that might be reasonably
275 # related to version activity. this relies on the idea that the SConscript
276 # file that builds the executable is updated with new version info and committed
277 # to the source code repository whenever things change.
280 def versioned_builder(target,source,env):
281 # build ID is composed of a representation of the date of the last CVS transaction
282 # for this (SConscript) file
285 o = file (source[0].get_dir().get_path() + '/CVS/Entries', "r")
287 print "Could not CVS/Entries for reading"
291 lines = o.readlines()
293 if line[0:12] == '/SConscript/':
294 parts = line.split ("/")
300 print "No SConscript CVS update info found - versioned executable cannot be built"
303 tag = time.strftime ('%Y%M%d%H%m', time.strptime (last_date))
304 print "The current build ID is " + tag
306 tagged_executable = source[0].get_path() + '-' + tag
308 if os.path.exists (tagged_executable):
309 print "Replacing existing executable with the same build tag."
310 os.unlink (tagged_executable)
312 return os.link (source[0].get_path(), tagged_executable)
314 verbuild = Builder (action = versioned_builder)
315 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
318 # source tar file builder
321 def distcopy (target, source, env):
322 treedir = str (target[0])
326 except OSError, (errnum, strerror):
327 if errnum != errno.EEXIST:
328 print 'mkdir ', treedir, ':', strerror
332 # we don't know what characters might be in the file names
333 # so quote them all before passing them to the shell
335 all_files = ([ str(s) for s in source ])
336 cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
337 cmd += ' | (cd ' + treedir + ' && tar xf -)'
341 def tarballer (target, source, env):
342 cmd = 'tar -jcf ' + str (target[0]) + ' ' + str(source[0]) + " --exclude '*~'"
343 print 'running ', cmd, ' ... '
347 dist_bld = Builder (action = distcopy,
348 target_factory = SCons.Node.FS.default_fs.Entry,
349 source_factory = SCons.Node.FS.default_fs.Entry,
352 tarball_bld = Builder (action = tarballer,
353 target_factory = SCons.Node.FS.default_fs.Entry,
354 source_factory = SCons.Node.FS.default_fs.Entry)
356 env.Append (BUILDERS = {'Distribute' : dist_bld})
357 env.Append (BUILDERS = {'Tarball' : tarball_bld})
360 # Make sure they know what they are doing
364 sys.stdout.write ("Are you building Ardour for personal use (rather than distributiont to others)? [no]: ")
365 answer = sys.stdin.readline ()
366 answer = answer.rstrip().strip()
367 if answer != "yes" and answer != "y":
368 print 'You cannot build Ardour with VST support for distribution to others.\nIt is a violation of several different licenses. VST support disabled.'
371 print "OK, VST support will be enabled"
374 # ----------------------------------------------------------------------
375 # Construction environment setup
376 # ----------------------------------------------------------------------
380 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
382 #libraries['sndfile'] = LibraryInfo()
383 #libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
385 libraries['lrdf'] = LibraryInfo()
386 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
388 libraries['raptor'] = LibraryInfo()
389 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
391 libraries['samplerate'] = LibraryInfo()
392 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
394 if env['FFT_ANALYSIS']:
395 libraries['fftw3f'] = LibraryInfo()
396 libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
398 libraries['jack'] = LibraryInfo()
399 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
401 libraries['xml'] = LibraryInfo()
402 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
404 libraries['xslt'] = LibraryInfo()
405 libraries['xslt'].ParseConfig('pkg-config --cflags --libs libxslt')
407 libraries['glib2'] = LibraryInfo()
408 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
409 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
410 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
411 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gthread-2.0')
413 libraries['gtk2'] = LibraryInfo()
414 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
416 libraries['pango'] = LibraryInfo()
417 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
419 libraries['libgnomecanvas2'] = LibraryInfo()
420 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
422 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
424 # The Ardour Control Protocol Library
426 libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/control_protocol',
427 CPPPATH='#libs/surfaces/control_protocol')
429 # The Ardour backend/engine
431 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
432 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
433 libraries['pbd'] = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
434 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
439 libraries['usb'] = LibraryInfo ()
441 conf = Configure (libraries['usb'])
442 if conf.CheckLib ('usb', 'usb_interrupt_write'):
447 libraries['usb'] = conf.Finish ()
452 libraries['flac'] = LibraryInfo ()
454 conf = Configure (libraries['flac'])
455 conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new', language='CXX')
456 libraries['flac'] = conf.Finish ()
458 # or if that fails...
459 #libraries['flac'] = LibraryInfo (LIBS='FLAC')
461 # boost (we don't link against boost, just use some header files)
463 libraries['boost'] = LibraryInfo ()
464 conf = Configure (libraries['boost'])
465 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == 0:
466 print "Boost header files do not appear to be installed."
469 libraries['boost'] = conf.Finish ()
475 libraries['lo'] = LibraryInfo ()
477 conf = Configure (libraries['lo'])
478 if conf.CheckLib ('lo', 'lo_server_new') == False:
479 print "liblo does not appear to be installed."
482 libraries['lo'] = conf.Finish ()
487 libraries['dmalloc'] = LibraryInfo ()
490 # look for the threaded version
493 conf = Configure (libraries['dmalloc'])
494 if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
495 have_libdmalloc = True
497 have_libdmalloc = False
499 libraries['dmalloc'] = conf.Finish ()
502 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
505 conf = Configure(env)
506 if conf.CheckCHeader('jack/midiport.h'):
507 libraries['sysmidi'] = LibraryInfo (LIBS='jack')
508 env['SYSMIDI'] = 'JACK MIDI'
509 subst_dict['%MIDITAG%'] = "control"
510 subst_dict['%MIDITYPE%'] = "jack"
511 print "Using JACK MIDI"
512 elif conf.CheckCHeader('alsa/asoundlib.h'):
513 libraries['sysmidi'] = LibraryInfo (LIBS='asound')
514 env['SYSMIDI'] = 'ALSA Sequencer'
515 subst_dict['%MIDITAG%'] = "seq"
516 subst_dict['%MIDITYPE%'] = "alsa/sequencer"
517 print "Using ALSA MIDI"
518 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
519 # this line is needed because scons can't handle -framework in ParseConfig() yet.
520 libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load')
521 env['SYSMIDI'] = 'CoreMIDI'
522 subst_dict['%MIDITAG%'] = "ardour"
523 subst_dict['%MIDITYPE%'] = "coremidi"
524 print "Using CoreMIDI"
526 print "It appears you don't have the required MIDI libraries installed."
533 libraries['sigc2'] = LibraryInfo()
534 libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
535 libraries['glibmm2'] = LibraryInfo()
536 libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
537 libraries['gdkmm2'] = LibraryInfo()
538 libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
539 libraries['gtkmm2'] = LibraryInfo()
540 libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
541 libraries['atkmm'] = LibraryInfo()
542 libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
543 libraries['pangomm'] = LibraryInfo()
544 libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
545 libraries['libgnomecanvasmm'] = LibraryInfo()
546 libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
549 # cannot use system one for the time being
552 libraries['sndfile'] = LibraryInfo(LIBS='libsndfile',
553 LIBPATH='#libs/libsndfile',
554 CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
556 # libraries['libglademm'] = LibraryInfo()
557 # libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
559 # libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
560 libraries['soundtouch'] = LibraryInfo()
561 libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
563 libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
564 LIBPATH='#libs/appleutility',
565 CPPPATH='#libs/appleutility')
579 subdirs = ['libs/fst'] + subdirs + ['vst']
582 subdirs = subdirs + ['libs/appleutility']
591 libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
592 LIBPATH='#libs/sigc++2',
593 CPPPATH='#libs/sigc++2')
594 libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
595 LIBPATH='#libs/glibmm2',
596 CPPPATH='#libs/glibmm2')
597 libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
598 LIBPATH='#libs/gtkmm2/pango',
599 CPPPATH='#libs/gtkmm2/pango')
600 libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
601 LIBPATH='#libs/gtkmm2/atk',
602 CPPPATH='#libs/gtkmm2/atk')
603 libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
604 LIBPATH='#libs/gtkmm2/gdk',
605 CPPPATH='#libs/gtkmm2/gdk')
606 libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
607 LIBPATH="#libs/gtkmm2/gtk",
608 CPPPATH='#libs/gtkmm2/gtk/')
609 libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
610 LIBPATH='#libs/libgnomecanvasmm',
611 CPPPATH='#libs/libgnomecanvasmm')
613 libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
614 LIBPATH='#libs/soundtouch',
615 CPPPATH=['#libs', '#libs/soundtouch'])
616 libraries['sndfile'] = LibraryInfo(LIBS='libsndfile',
617 LIBPATH='#libs/libsndfile',
618 CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
619 # libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
620 # LIBPATH='#libs/libglademm',
621 # CPPPATH='#libs/libglademm')
622 libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
623 LIBPATH='#libs/appleutility',
624 CPPPATH='#libs/appleutility')
640 subdirs = ['libs/fst'] + subdirs + ['vst']
643 subdirs = subdirs + ['libs/appleutility']
651 'libs/libgnomecanvasmm',
658 # always build the LGPL control protocol lib, since we link against it ourselves
659 # ditto for generic MIDI
662 surface_subdirs = [ 'libs/surfaces/control_protocol', 'libs/surfaces/generic_midi' ]
666 surface_subdirs += [ 'libs/surfaces/tranzport' ]
667 if os.access ('libs/surfaces/sony9pin', os.F_OK):
668 surface_subdirs += [ 'libs/surfaces/sony9pin' ]
670 opts.Save('scache.conf', env)
671 Help(opts.GenerateHelpText(env))
673 if os.environ.has_key('PATH'):
674 env.Append(PATH = os.environ['PATH'])
676 if os.environ.has_key('PKG_CONFIG_PATH'):
677 env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
679 if os.environ.has_key('CC'):
680 env['CC'] = os.environ['CC']
682 if os.environ.has_key('CXX'):
683 env['CXX'] = os.environ['CXX']
685 if os.environ.has_key('DISTCC_HOSTS'):
686 env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
687 env['ENV']['HOME'] = os.environ['HOME']
689 final_prefix = '$PREFIX'
690 install_prefix = '$DESTDIR/$PREFIX'
692 subst_dict['INSTALL_PREFIX'] = install_prefix;
694 if env['PREFIX'] == '/usr':
695 final_config_prefix = '/etc'
697 final_config_prefix = env['PREFIX'] + '/etc'
699 config_prefix = '$DESTDIR' + final_config_prefix
701 # For colorgcc ( so says the wiki, but it's still not working :/ anyone? )
702 if os.environ.has_key('PATH'):
703 env['PATH'] = os.environ['PATH']
704 if os.environ.has_key('TERM'):
705 env['TERM'] = os.environ['TERM']
706 if os.environ.has_key('HOME'):
707 env['HOME'] = os.environ['HOME']
710 # SCons should really do this for us
712 conf = Configure (env)
714 have_cxx = conf.TryAction (Action (env['CXX'] + ' --version'))
716 print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
719 print "Congratulations, you have a functioning C++ compiler."
724 # Compiler flags and other system-dependent stuff
728 debug_flags = [ '-g' ]
730 # guess at the platform, used to define compiler flags
732 config_guess = os.popen("tools/config.guess").read()[:-1]
738 config = config_guess.split ("-")
740 print "system triple: " + config_guess
743 if env['DIST_TARGET'] == 'auto':
744 if config[config_arch] == 'apple':
745 # The [.] matches to the dot after the major version, "." would match any character
746 if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
747 env['DIST_TARGET'] = 'panther'
749 env['DIST_TARGET'] = 'tiger'
751 if re.search ("x86_64", config[config_cpu]) != None:
752 env['DIST_TARGET'] = 'x86_64'
753 elif re.search("i[0-5]86", config[config_cpu]) != None:
754 env['DIST_TARGET'] = 'i386'
755 elif re.search("powerpc", config[config_cpu]) != None:
756 env['DIST_TARGET'] = 'powerpc'
758 env['DIST_TARGET'] = 'i686'
759 print "\n*******************************"
760 print "detected DIST_TARGET = " + env['DIST_TARGET']
761 print "*******************************\n"
764 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
766 # Apple/PowerPC optimization options
768 # -mcpu=7450 does not reliably work with gcc 3.*
770 if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
771 if config[config_arch] == 'apple':
772 opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
774 opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
776 opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
777 opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
779 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':
781 build_host_supports_sse = 0
783 debug_flags.append ("-DARCH_X86")
784 opt_flags.append ("-DARCH_X86")
786 if config[config_kernel] == 'linux' :
788 if env['DIST_TARGET'] != 'i386':
790 flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
791 x86_flags = flag_line.split (": ")[1:][0].split (' ')
793 if "mmx" in x86_flags:
794 opt_flags.append ("-mmmx")
795 if "sse" in x86_flags:
796 build_host_supports_sse = 1
797 if "3dnow" in x86_flags:
798 opt_flags.append ("-m3dnow")
800 if config[config_cpu] == "i586":
801 opt_flags.append ("-march=i586")
802 elif config[config_cpu] == "i686":
803 opt_flags.append ("-march=i686")
805 if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
806 opt_flags.extend (["-msse", "-mfpmath=sse"])
807 debug_flags.extend (["-msse", "-mfpmath=sse"])
808 # end of processor-specific section
810 # optimization section
811 if env['FPU_OPTIMIZATION']:
812 if env['DIST_TARGET'] == 'tiger':
813 opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
814 debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
815 libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
816 elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
817 opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
818 debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
819 if env['DIST_TARGET'] == 'x86_64':
820 opt_flags.append ("-DUSE_X86_64_ASM")
821 debug_flags.append ("-DUSE_X86_64_ASM")
822 if build_host_supports_sse != 1:
823 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)"
824 # end optimization section
827 # save off guessed arch element in an env
829 env.Append(CONFIG_ARCH=config[config_arch])
833 # ARCH="..." overrides all
836 if env['ARCH'] != '':
837 opt_flags = env['ARCH'].split()
840 # prepend boiler plate optimization flags
845 "-fomit-frame-pointer",
850 if env['DEBUG'] == 1:
851 env.Append(CCFLAGS=" ".join (debug_flags))
853 env.Append(CCFLAGS=" ".join (opt_flags))
859 env.Append(CCFLAGS="-Wall")
860 env.Append(CXXFLAGS="-Woverloaded-virtual")
862 if env['EXTRA_WARN']:
863 env.Append(CCFLAGS="-Wextra -pedantic")
864 env.Append(CXXFLAGS="-ansi")
867 env.Append(CCFLAGS="-DHAVE_LIBLO")
870 # everybody needs this
873 env.Merge ([ libraries['core'] ])
876 # fix scons nitpickiness on APPLE
879 if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
880 env.Append(CCFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
886 conf = Configure (env)
888 nls_error = 'This system is not configured for internationalized applications. An english-only version will be built:'
889 print 'Checking for internationalization support ...'
890 have_gettext = conf.TryAction(Action('xgettext --version'))
891 if have_gettext[0] != 1:
892 nls_error += ' No xgettext command.'
895 print "Found xgettext"
897 have_msgmerge = conf.TryAction(Action('msgmerge --version'))
898 if have_msgmerge[0] != 1:
899 nls_error += ' No msgmerge command.'
902 print "Found msgmerge"
904 if not conf.CheckCHeader('libintl.h'):
905 nls_error += ' No libintl.h.'
911 print "International version will be built."
915 env.Append(CCFLAGS="-DENABLE_NLS")
917 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
920 # the configuration file may be system dependent
923 conf = env.Configure ()
925 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
926 subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
927 subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
929 subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
930 subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
932 # posix_memalign available
933 if not conf.CheckFunc('posix_memalign'):
934 print 'Did not find posix_memalign(), using malloc'
935 env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
940 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
942 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour_system.rc'))
943 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.rc'))
949 Precious (env['DISTTREE'])
952 # note the special "cleanfirst" source name. this triggers removal
953 # of the existing disttree
956 env.Distribute (env['DISTTREE'],
958 'COPYING', 'PACKAGER_README', 'README',
963 glob.glob ('DOCUMENTATION/AUTHORS*') +
964 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
965 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
966 glob.glob ('DOCUMENTATION/BUILD*') +
967 glob.glob ('DOCUMENTATION/FAQ*') +
968 glob.glob ('DOCUMENTATION/README*')
971 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
972 env.Alias ('srctar', srcdist)
974 # don't leave the distree around
976 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
977 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
983 for subdir in coredirs:
984 SConscript (subdir + '/SConscript')
986 for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]:
987 for subdir in sublistdir:
988 SConscript (subdir + '/SConscript')
991 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])