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