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