431fccb6ca1f5a76ca9aa04c45fbe0193c961430
[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 from sets import Set
12 import SCons.Node.FS
13
14 SConsignFile()
15 EnsureSConsVersion(0, 96)
16
17 version = '2.0alpha1'
18
19 subst_dict = { }
20
21 #
22 # Command-line options
23 #
24
25 opts = Options('scache.conf')
26 opts.AddOptions(
27   ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
28     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),
29     BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
30     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
31     BoolOption('DEVBUILD', 'Use shared libardour (developers only)', 0),
32     BoolOption('NLS', 'Set to turn on i18n support', 1),
33     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
34     BoolOption('VST', 'Compile with support for VST', 0),
35     BoolOption('VERSIONED', 'Add version information to ardour/gtk executable name inside the build directory', 0),
36     EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'tiger', 'panther', 'none' ), ignorecase=2),
37     BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1)
38   )
39
40 #----------------------------------------------------------------------
41 # a handy helper that provides a way to merge compile/link information
42 # from multiple different "environments"
43 #----------------------------------------------------------------------
44 #
45 class LibraryInfo(Environment):
46     def __init__(self,*args,**kw):
47         Environment.__init__ (self,*args,**kw)
48         
49     def Merge (self,others):
50         for other in others:
51             self.Append (LIBS = other.get ('LIBS',[]))
52             self.Append (LIBPATH = other.get ('LIBPATH', []))   
53             self.Append (CPPPATH = other.get('CPPPATH', []))
54             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
55         self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
56         self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
57         #doing LINKFLAGS breaks -framework
58     #doing LIBS break link order dependency
59
60
61 env = LibraryInfo (options = opts,
62                    CPPPATH = [ '.' ],
63                    VERSION = version,
64                    TARBALL='ardour-' + version + '.tar.bz2',
65                    DISTFILES = [ ],
66                    DISTTREE  = '#ardour-' + version,
67                    DISTCHECKDIR = '#ardour-' + version + '/check'
68                    )
69
70
71 #----------------------------------------------------------------------
72 # Builders
73 #----------------------------------------------------------------------
74
75 # Handy subst-in-file builder
76
77
78 def do_subst_in_file(targetfile, sourcefile, dict):
79         """Replace all instances of the keys of dict with their values.
80         For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
81         then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
82         """
83         try:
84             f = open(sourcefile, 'rb')
85             contents = f.read()
86             f.close()
87         except:
88             raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
89         for (k,v) in dict.items():
90             contents = re.sub(k, v, contents)
91         try:
92             f = open(targetfile, 'wb')
93             f.write(contents)
94             f.close()
95         except:
96             raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
97         return 0 # success
98  
99 def subst_in_file(target, source, env):
100         if not env.has_key('SUBST_DICT'):
101             raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
102         d = dict(env['SUBST_DICT']) # copy it
103         for (k,v) in d.items():
104             if callable(v):
105                 d[k] = env.subst(v())
106             elif SCons.Util.is_String(v):
107                 d[k]=env.subst(v)
108             else:
109                 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
110         for (t,s) in zip(target, source):
111             return do_subst_in_file(str(t), str(s), d)
112  
113 def subst_in_file_string(target, source, env):
114         """This is what gets printed on the console."""
115         return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
116                           for (t,s) in zip(target, source)])
117  
118 def subst_emitter(target, source, env):
119         """Add dependency from substituted SUBST_DICT to target.
120         Returns original target, source tuple unchanged.
121         """
122         d = env['SUBST_DICT'].copy() # copy it
123         for (k,v) in d.items():
124             if callable(v):
125                 d[k] = env.subst(v())
126             elif SCons.Util.is_String(v):
127                 d[k]=env.subst(v)
128         Depends(target, SCons.Node.Python.Value(d))
129         # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
130         return target, source
131  
132 subst_action = Action (subst_in_file, subst_in_file_string)
133 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
134
135 #
136 # internationalization
137 #
138
139 # po_helper
140 #
141 # this is not a builder. we can't list the .po files as a target,
142 # because then scons -c will remove them (even Precious doesn't alter
143 # this). this function is called whenever a .mo file is being
144 # built, and will conditionally update the .po file if necessary.
145 #
146
147 def po_helper(po,pot):
148     args = [ 'msgmerge',
149              '--update',
150              po,
151              pot,
152              ]
153     print 'Updating ' + po
154     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
155
156 # mo_builder: builder function for (binary) message catalogs (.mo)
157 #
158 # first source:  .po file
159 # second source: .pot file
160 #
161
162 def mo_builder(target,source,env):
163     po_helper (source[0].get_path(), source[1].get_path())
164     args = [ 'msgfmt',
165              '-c',
166              '-o',
167              target[0].get_path(),
168              source[0].get_path()
169              ]
170     return os.spawnvp (os.P_WAIT, 'msgfmt', args)
171
172 mo_bld = Builder (action = mo_builder)
173 env.Append(BUILDERS = {'MoBuild' : mo_bld})
174
175 # pot_builder: builder function for message templates (.pot)
176 #
177 # source: list of C/C++ etc. files to extract messages from
178 #
179
180 def pot_builder(target,source,env):
181     args = [ 'xgettext', 
182              '--keyword=_',
183              '--keyword=N_',
184              '--from-code=UTF-8',
185              '-o', target[0].get_path(), 
186              "--default-domain=" + env['PACKAGE'],
187              '--copyright-holder="Paul Davis"' ]
188     args += [ src.get_path() for src in source ]
189
190     return os.spawnvp (os.P_WAIT, 'xgettext', args)
191
192 pot_bld = Builder (action = pot_builder)
193 env.Append(BUILDERS = {'PotBuild' : pot_bld})
194
195 #
196 # utility function, not a builder
197 #
198
199 def i18n (buildenv, sources, installenv):
200     domain = buildenv['PACKAGE']
201     potfile = buildenv['POTFILE']
202
203     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
204
205     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
206     languages = [ po.replace ('.po', '') for po in p_oze ]
207     m_oze = [ po.replace (".po", ".mo") for po in p_oze ]
208     
209     for mo in m_oze[:]:
210         po = 'po/' + mo.replace (".mo", ".po")
211         installenv.Alias ('install', buildenv.MoBuild (mo, [ po, potfile ]))
212         
213     for lang in languages[:]:
214         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
215         moname = domain + '.mo'
216         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
217
218 #
219 # A generic builder for version.cc files
220
221 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
222 # note: assumes one source files, the header that declares the version variables
223
224 def version_builder (target, source, env):
225    text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
226    text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
227    text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
228
229    try:
230       o = file (target[0].get_path(), 'w')
231       o.write (text)
232       o.close ();
233    except IOError:
234       print "Could not open", target[0].get_path(), " for writing\n"
235       sys.exit (-1)
236
237    text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n";
238    text += "#define __" + env['DOMAIN'] + "_version_h__\n";
239    text += "extern int " + env['DOMAIN'] + "_major_version;\n"
240    text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
241    text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
242    text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n";
243
244    try:
245       o = file (target[1].get_path(), 'w')
246       o.write (text)
247       o.close ();
248    except IOError:
249       print "Could not open", target[1].get_path(), " for writing\n"
250       sys.exit (-1)
251   
252    return None
253
254 version_bld = Builder (action = version_builder)
255 env.Append (BUILDERS = {'VersionBuild' : version_bld})
256
257 #
258 # a builder that makes a hard link from the 'source' executable to a name with
259 # a "build ID" based on the most recent CVS activity that might be reasonably
260 # related to version activity. this relies on the idea that the SConscript
261 # file that builds the executable is updated with new version info and committed
262 # to the source code repository whenever things change.
263 #
264
265 def versioned_builder(target,source,env):
266     # build ID is composed of a representation of the date of the last CVS transaction
267     # for this (SConscript) file
268     
269     try:
270         o = file (source[0].get_dir().get_path() +  '/CVS/Entries', "r")
271     except IOError:
272         print "Could not CVS/Entries for reading"
273         return -1
274
275     last_date = ""        
276     lines = o.readlines()
277     for line in lines:
278         if line[0:12] == '/SConscript/':
279             parts = line.split ("/")
280             last_date = parts[3]
281             break
282     o.close ()
283
284     if last_date == "":
285         print "No SConscript CVS update info found - versioned executable cannot be built"
286         return -1
287
288     tag = time.strftime ('%Y%M%d%H%m', time.strptime (last_date));
289     print "The current build ID is " + tag
290
291     tagged_executable = source[0].get_path() + '-' + tag
292
293     if os.path.exists (tagged_executable):
294         print "Replacing existing executable with the same build tag."
295         os.unlink (tagged_executable)
296
297     return os.link (source[0].get_path(), tagged_executable)
298
299 verbuild = Builder (action = versioned_builder)
300 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
301
302 #
303 # source tar file builder
304 #
305
306 def distcopy (target, source, env):
307     treedir = str (target[0])
308
309     try:
310         os.mkdir (treedir)
311     except OSError, (errnum, strerror):
312         if errnum != errno.EEXIST:
313             print 'mkdir ', treedir, ':', strerror
314
315     cmd = 'tar cf - '
316     #
317     # we don't know what characters might be in the file names
318     # so quote them all before passing them to the shell
319     #
320     all_files = ([ str(s) for s in source ])
321     cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
322     cmd += ' | (cd ' + treedir + ' && tar xf -)'
323     p = os.popen (cmd)
324     return p.close ();
325
326 def tarballer (target, source, env):            
327     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'"
328     print 'running ', cmd, ' ... '
329     p = os.popen (cmd)
330     return p.close ()
331
332 dist_bld = Builder (action = distcopy,
333                     target_factory = SCons.Node.FS.default_fs.Entry,
334                     source_factory = SCons.Node.FS.default_fs.Entry,
335                     multi = 1)
336
337 tarball_bld = Builder (action = tarballer,
338                        target_factory = SCons.Node.FS.default_fs.Entry,
339                        source_factory = SCons.Node.FS.default_fs.Entry)
340
341 env.Append (BUILDERS = {'Distribute' : dist_bld})
342 env.Append (BUILDERS = {'Tarball' : tarball_bld})
343
344 # ----------------------------------------------------------------------
345 # Construction environment setup
346 # ----------------------------------------------------------------------
347
348 libraries = { }
349
350 libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
351
352 libraries['sndfile'] = LibraryInfo()
353 libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
354
355 libraries['lrdf'] = LibraryInfo()
356 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
357
358 libraries['raptor'] = LibraryInfo()
359 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
360
361 libraries['samplerate'] = LibraryInfo()
362 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
363
364 libraries['jack'] = LibraryInfo()
365 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
366
367 libraries['xml'] = LibraryInfo()
368 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
369
370 libraries['glib2'] = LibraryInfo()
371 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
372 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
373 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
374
375 libraries['gtk2'] = LibraryInfo()
376 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
377
378 libraries['pango'] = LibraryInfo()
379 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
380
381 libraries['libgnomecanvas2'] = LibraryInfo()
382 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
383
384 libraries['glade2'] = LibraryInfo()
385 libraries['glade2'].ParseConfig ('pkg-config --cflags --libs libglade-2.0')
386
387 #libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
388
389 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
390 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
391 libraries['pbd3']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
392 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
393 #libraries['cassowary'] = LibraryInfo(LIBS='cassowary', LIBPATH='#libs/cassowary', CPPPATH='#libs/cassowary')
394
395 libraries['fst'] = LibraryInfo()
396 if env['VST']:
397     libraries['fst'].ParseConfig('pkg-config --cflags --libs libfst')
398
399 #
400 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
401
402
403 conf = Configure(env)
404
405 if conf.CheckCHeader('alsa/asoundlib.h'):
406     libraries['sysmidi'] = LibraryInfo (LIBS='asound')
407     env['SYSMIDI'] = 'ALSA Sequencer'
408     subst_dict['%MIDITAG%'] = "seq"
409     subst_dict['%MIDITYPE%'] = "alsa/sequencer"
410 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
411     # this line is needed because scons can't handle -framework in ParseConfig() yet.
412     libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load')
413     env['SYSMIDI'] = 'CoreMIDI'
414     subst_dict['%MIDITAG%'] = "ardour"
415     subst_dict['%MIDITYPE%'] = "coremidi"
416
417 env = conf.Finish()
418
419 if env['SYSLIBS']:
420
421     libraries['sigc2'] = LibraryInfo()
422     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
423     libraries['glibmm2'] = LibraryInfo()
424     libraries['glibmm2'].ParseConfig('pkg-config --cflags --libs glibmm-2.4')
425     libraries['gdkmm2'] = LibraryInfo()
426     libraries['gdkmm2'].ParseConfig ('pkg-config --cflags --libs gdkmm-2.4')
427     libraries['gtkmm2'] = LibraryInfo()
428     libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.4')
429     libraries['atkmm'] = LibraryInfo()
430     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
431     libraries['pangomm'] = LibraryInfo()
432     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
433     libraries['libgnomecanvasmm'] = LibraryInfo()
434     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
435     libraries['libglademm'] = LibraryInfo()
436     libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
437
438 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
439     libraries['soundtouch'] = LibraryInfo()
440     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
441
442     coredirs = [
443         'templates'
444     ]
445
446     subdirs = [
447         'libs/pbd3',
448         'libs/midi++2',
449         'libs/ardour'
450         ]
451
452     gtk_subdirs = [
453 #        'libs/flowcanvas',
454         'libs/gtkmm2ext',
455         'gtk2_ardour'
456         ]
457
458 else:
459     libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
460                                     LIBPATH='#libs/sigc++2',
461                                     CPPPATH='#libs/sigc++2')
462     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
463                                     LIBPATH='#libs/glibmm2',
464                                     CPPPATH='#libs/glibmm2')
465     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
466                                     LIBPATH='#libs/gtkmm2/pango',
467                                     CPPPATH='#libs/gtkmm2/pango')
468     libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
469                                      LIBPATH='#libs/gtkmm2/atk',
470                                      CPPPATH='#libs/gtkmm2/atk')
471     libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
472                                       LIBPATH='#libs/gtkmm2/gdk',
473                                       CPPPATH='#libs/gtkmm2/gdk')
474     libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
475                                      LIBPATH="#libs/gtkmm2/gtk",
476                                      CPPPATH='#libs/gtkmm2/gtk/')
477     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
478                                                 LIBPATH='#libs/libgnomecanvasmm',
479                                                 CPPPATH='#libs/libgnomecanvasmm')
480
481     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
482                                           LIBPATH='#libs/soundtouch',
483                                           CPPPATH=['#libs', '#libs/soundtouch'])
484     libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
485                                           LIBPATH='#libs/libglademm',
486                                           CPPPATH='#libs/libglademm')
487
488     coredirs = [
489         'libs/soundtouch',
490         'templates'
491     ]
492
493     subdirs = [
494 #       'libs/cassowary',
495         'libs/sigc++2',
496         'libs/pbd3',
497         'libs/midi++2',
498         'libs/ardour'
499         ]
500
501     gtk_subdirs = [
502         'libs/glibmm2',
503         'libs/gtkmm2/pango',
504         'libs/gtkmm2/atk',
505         'libs/gtkmm2/gdk',
506         'libs/gtkmm2/gtk',
507     'libs/libglademm',
508         'libs/libgnomecanvasmm',
509 #       'libs/flowcanvas',
510     'libs/gtkmm2ext',
511     'gtk2_ardour'
512         ]
513
514 opts.Save('scache.conf', env)
515 Help(opts.GenerateHelpText(env))
516
517 if os.environ.has_key('PATH'):
518     env.Append(PATH = os.environ['PATH'])
519
520 if os.environ.has_key('PKG_CONFIG_PATH'):
521     env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
522
523 if os.environ.has_key('CC'):
524     env['CC'] = os.environ['CC']
525
526 if os.environ.has_key('CXX'):
527     env['CXX'] = os.environ['CXX']
528
529 if os.environ.has_key('DISTCC_HOSTS'):
530     env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
531     env['ENV']['HOME'] = os.environ['HOME']
532     
533 final_prefix = '$PREFIX'
534 install_prefix = '$DESTDIR/$PREFIX'
535
536 if env['PREFIX'] == '/usr':
537     final_config_prefix = '/etc'
538 else:
539     final_config_prefix = env['PREFIX'] + '/etc'
540
541 config_prefix = '$DESTDIR' + final_config_prefix
542
543
544 # SCons should really do this for us
545
546 conf = Configure (env)
547
548 have_cxx = conf.TryAction (Action (env['CXX'] + ' --version'));
549 if have_cxx[0] != 1:
550     print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
551     exit (1);
552 else:
553     print "Congratulations, you have a functioning C++ compiler."
554     
555 env = conf.Finish()
556
557 #
558 # Compiler flags and other system-dependent stuff
559 #
560
561 opt_flags = []
562 debug_flags = [ '-g' ]
563
564 # guess at the platform, used to define compiler flags
565
566 config_guess = os.popen("tools/config.guess").read()[:-1]
567
568 config_cpu = 0;
569 config_arch = 1;
570 config_kernel = 2;
571 config_os = 3;
572 config = config_guess.split ("-")
573
574 print "system triple: " + config_guess
575
576 # Autodetect
577 if env['DIST_TARGET'] == 'auto':
578     if config[config_arch] == 'apple':
579         # The [.] matches to the dot after the major version, "." would match any character
580         if re.search ("darwin[0-7][.]", config[config_kernel]) != None:
581             env['DIST_TARGET'] = 'panther';
582         else:
583             env['DIST_TARGET'] = 'tiger';
584     else:
585         if re.search ("x86_64", config[config_cpu]) != None:
586             env['DIST_TARGET'] = 'x86_64';
587         elif re.search("i[0-5]86", config[config_cpu]) != None:
588             env['DIST_TARGET'] = 'i386';
589         else:
590             env['DIST_TARGET'] = 'i686';
591     print "\n*******************************"
592     print "detected DIST_TARGET = " + env['DIST_TARGET']
593     print "*******************************\n"
594
595
596 if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
597     #
598     # Apple/PowerPC optimization options
599     #
600     # -mcpu=7450 does not reliably work with gcc 3.*
601     #
602     if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
603         if config[config_arch] == 'apple':
604             opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
605         else:
606             opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"]) 
607     else:
608         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
609     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
610
611 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':
612
613     build_host_supports_sse = 0
614     
615     debug_flags.append ("-DARCH_X86")
616     opt_flags.append ("-DARCH_X86")
617
618     if config[config_kernel] == 'linux' :
619
620         if env['DIST_TARGET'] != 'i386': 
621
622             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
623             x86_flags = flag_line.split (": ")[1:][0].split (' ')
624
625             if "mmx" in x86_flags:
626                 opt_flags.append ("-mmmx")
627             if "sse" in x86_flags:
628                 build_host_supports_sse = 1
629             if "3dnow" in x86_flags:
630                 opt_flags.append ("-m3dnow")
631
632             if config[config_cpu] == "i586":
633                 opt_flags.append ("-march=i586")
634             elif config[config_cpu] == "i686":
635                 opt_flags.append ("-march=i686")
636
637     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
638         opt_flags.extend (["-msse", "-mfpmath=sse"])
639         debug_flags.extend (["-msse", "-mfpmath=sse"])
640 # end of processor-specific section
641
642 # optimization section
643 if env['FPU_OPTIMIZATION']:
644     if env['DIST_TARGET'] == 'tiger':
645         opt_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
646         debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS")
647         libraries['core'].Append(LINKFLAGS= '-framework Accelerate')
648     elif env['DIST_TARGET'] == 'i686' or env['DIST_TARGET'] == 'x86_64':
649         opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
650         debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
651         if env['DIST_TARGET'] == 'x86_64':
652             opt_flags.append ("-DUSE_X86_64_ASM")
653             debug_flags.append ("-DUSE_X86_64_ASM")
654         if build_host_supports_sse != 1:
655             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)"
656 # end optimization section
657
658 #
659 # ARCH="..." overrides all 
660 #
661
662 if env['ARCH'] != '':
663     opt_flags = env['ARCH'].split()
664
665 #
666 # prepend boiler plate optimization flags
667 #
668
669 opt_flags[:0] = [
670     "-O3",
671     "-fomit-frame-pointer",
672     "-ffast-math",
673     "-fstrength-reduce"
674     ]
675
676 if env['DEBUG'] == 1:
677     env.Append(CCFLAGS=" ".join (debug_flags))
678 else:
679     env.Append(CCFLAGS=" ".join (opt_flags))
680
681 env.Append(CCFLAGS="-Wall")
682
683 if env['VST']:
684     env.Append(CCFLAGS="-DVST_SUPPORT")
685
686 #
687 # everybody needs this
688 #
689
690 env.Merge ([ libraries['core'] ])
691
692 #
693 # i18n support 
694 #
695
696 conf = Configure (env)
697
698 if env['NLS']:
699     print 'Checking for internationalization support ...'
700     have_gettext = conf.TryAction(Action('xgettext --version'))
701     if have_gettext[0] != 1:
702         print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
703         env['NLS'] = 0
704         
705     if conf.CheckCHeader('libintl.h') == None:
706         print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
707         env['NLS'] = 0
708
709
710 env = conf.Finish()
711
712 if env['NLS'] == 1:
713     env.Append(CCFLAGS="-DENABLE_NLS")
714
715
716 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
717
718 #
719 # the configuration file may be system dependent
720 #
721
722 conf = env.Configure ()
723
724 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
725     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
726     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
727 else:
728     subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
729     subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
730
731 # posix_memalign available
732 if not conf.CheckFunc('posix_memalign'):
733     print 'Did not find posix_memalign(), using malloc'
734     env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
735
736
737 env = conf.Finish()
738
739 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
740
741 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour_system.rc'))
742 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.rc'))
743
744 Default (rcbuild)
745
746 # source tarball
747
748 Precious (env['DISTTREE'])
749
750 #
751 # note the special "cleanfirst" source name. this triggers removal
752 # of the existing disttree
753 #
754
755 env.Distribute (env['DISTTREE'],
756                 [ 'SConstruct',
757                   'COPYING', 'PACKAGER_README', 'README',
758                   'ardour.rc.in',
759                   'ardour_system.rc',
760                   'tools/config.guess'
761                   ] +
762                 glob.glob ('DOCUMENTATION/AUTHORS*') +
763                 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
764                 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
765                 glob.glob ('DOCUMENTATION/BUILD*') +
766                 glob.glob ('DOCUMENTATION/FAQ*') +
767                 glob.glob ('DOCUMENTATION/README*')
768                 )
769                 
770 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
771 env.Alias ('srctar', srcdist)
772 #
773 # don't leave the distree around 
774 #
775 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
776 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
777
778 #
779 # the subdirs
780
781
782 for subdir in coredirs:
783     SConscript (subdir + '/SConscript')
784
785 for sublistdir in [subdirs, gtk_subdirs]:
786         for subdir in sublistdir:
787                 SConscript (subdir + '/SConscript')
788
789 # cleanup
790 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
791