root/tags/2.0-beta1/SConstruct

Revision 1048, 16.9 kB (checked in by ppalmers, 4 years ago)

pick a nice version number for alpha1

Line 
1 #! /usr/bin/python
2 #
3 # Copyright (C) 2007-2008 Arnold Krille
4 # Copyright (C) 2007-2008 Pieter Palmers
5 # Copyright (C) 2008 Jonathan Woithe
6 #
7 # This file is part of FFADO
8 # FFADO = Free Firewire (pro-)audio drivers for linux
9 #
10 # FFADO is based upon FreeBoB.
11 #
12 # This program is free software: you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation, either version 2 of the License, or
15 # (at your option) version 3 of the License.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 #
25
26 FFADO_API_VERSION="8"
27 FFADO_VERSION="1.999.20"
28
29 import os
30 import re
31 from string import Template
32 import imp
33
34 build_dir = ARGUMENTS.get('BUILDDIR', "")
35 if build_dir:
36         build_base=build_dir+'/'
37         if not os.path.isdir( build_base ):
38                 os.makedirs( build_base )
39         print "Building into: " + build_base
40 else:
41         build_base=''
42
43 destdir = ARGUMENTS.get( 'DESTDIR', "" )
44
45 if not os.path.isdir( "cache" ):
46         os.makedirs( "cache" )
47
48 opts = Options( "cache/"+build_base+"options.cache" )
49
50 #
51 # If this is just to display a help-text for the variable used via ARGUMENTS, then its wrong...
52 opts.Add( "BUILDDIR", "Path to place the built files in", "")
53
54 opts.AddOptions(
55         BoolOption( "DEBUG", """\
56 Toggle debug-build. DEBUG means \"-g -Wall\" and more, otherwise we will use
57   \"-O2\" to optimise.""", True ),
58         BoolOption( "PROFILE", "Build with symbols and other profiling info", False ),
59         PathOption( "PREFIX", "The prefix where ffado will be installed to.", "/usr/local", PathOption.PathAccept ),
60         PathOption( "BINDIR", "Overwrite the directory where apps are installed to.", "$PREFIX/bin", PathOption.PathAccept ),
61         PathOption( "LIBDIR", "Overwrite the directory where libs are installed to.", "$PREFIX/lib", PathOption.PathAccept ),
62         PathOption( "INCLUDEDIR", "Overwrite the directory where headers are installed to.", "$PREFIX/include", PathOption.PathAccept ),
63         PathOption( "SHAREDIR", "Overwrite the directory where misc shared files are installed to.", "$PREFIX/share/libffado", PathOption.PathAccept ),
64         BoolOption( "ENABLE_BEBOB", "Enable/Disable the bebob part.", True ),
65         BoolOption( "ENABLE_FIREWORKS", "Enable/Disable the ECHO Audio FireWorks avc part.", True ),
66         BoolOption( "ENABLE_MOTU", "Enable/Disable the Motu part.", True ),
67         BoolOption( "ENABLE_DICE", "Enable/Disable the DICE part.", False ),
68         BoolOption( "ENABLE_METRIC_HALO", "Enable/Disable the Metric Halo part.", False ),
69         BoolOption( "ENABLE_RME", "Enable/Disable the RME part.", False ),
70         BoolOption( "ENABLE_BOUNCE", "Enable/Disable the BOUNCE part.", False ),
71         BoolOption( "ENABLE_GENERICAVC", """\
72 Enable/Disable the the generic avc part (mainly used by apple).
73   Note that disabling this option might be overwritten by other devices needing
74   this code.""", False ),
75         BoolOption( "ENABLE_ALL", "Enable/Disable support for all devices.", False ),
76         BoolOption( "BUILD_TESTS", """\
77 Build the tests in their directory. As some contain quite some functionality,
78   this is on by default.
79   If you just want to use ffado with jack without the tools, you can disable this.\
80 """, True ),
81     BoolOption( "BUILD_STATIC_TOOLS", "Build a statically linked version of the FFADO tools.", False ),
82     EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'none' ), ignorecase=2),
83     BoolOption( "ENABLE_OPTIMIZATIONS", "Enable optimizations and the use of processor specific extentions (MMX/SSE/...).", False ),
84
85         )
86
87 ## Load the builders in config
88 buildenv=os.environ
89 vars_to_check = [
90         'PATH',
91         'PKG_CONFIG_PATH',
92         'LD_LIBRARY_PATH',
93         'XDG_CONFIG_DIRS',
94         'XDG_DATA_DIRS',
95         'HOME',
96 ]
97 for var in vars_to_check:
98         if os.environ.has_key(var):
99                 buildenv[var]=os.environ[var]
100         else:
101                 buildenv[var]=''
102
103 env = Environment( tools=['default','scanreplace','pyuic','dbus','doxygen','pkgconfig'], toolpath=['admin'], ENV = buildenv, options=opts )
104
105
106 Help( """
107 For building ffado you can set different options as listed below. You have to
108 specify them only once, scons will save the last value you used and re-use
109 that.
110 To really undo your settings and return to the factory defaults, remove the
111 "cache"-folder and the file ".sconsign.dblite" from this directory.
112 For example with: "rm -Rf .sconsign.dblite cache"
113
114 Note that this is a development version! Don't complain if its not working!
115 See www.ffado.org for stable releases.
116 """ )
117 Help( opts.GenerateHelpText( env ) )
118
119 # make sure the necessary dirs exist
120 if not os.path.isdir( "cache/" + build_base ):
121         os.makedirs( "cache/" + build_base )
122 if not os.path.isdir( 'cache/objects' ):
123         os.makedirs( 'cache/objects' )
124
125 CacheDir( 'cache/objects' )
126
127 opts.Save( 'cache/' + build_base + "options.cache", env )
128
129 def ConfigGuess( context ):
130         context.Message( "Trying to find the system triple: " )
131         ret = os.popen( "admin/config.guess" ).read()[:-1]
132         context.Result( ret )
133         return ret
134
135 def CheckForApp( context, app ):
136         context.Message( "Checking wether '" + app + "' executes " )
137         ret = context.TryAction( app )
138         context.Result( ret[0] )
139         return ret[0]
140
141 def CheckForPyModule( context, module ):
142         context.Message( "Checking for the python module '" + module + "' " )
143         ret = True
144         try:
145                 imp.find_module( module )
146         except ImportError:
147                 ret = False
148         context.Result( ret )
149         return ret
150
151 tests = {
152         "ConfigGuess" : ConfigGuess,
153         "CheckForApp" : CheckForApp,
154         "CheckForPyModule": CheckForPyModule,
155 }
156 tests.update( env['PKGCONFIG_TESTS'] )
157 tests.update( env['PYUIC_TESTS'] )
158
159 conf = Configure( env,
160         custom_tests = tests,
161         conf_dir = "cache/" + build_base,
162         log_file = "cache/" + build_base + 'config.log' )
163
164 if not env.GetOption('clean'):
165         #
166         # Check if the environment can actually compile c-files by checking for a
167         # header shipped with gcc.
168         #
169         if not conf.CheckHeader( "stdio.h", language="C" ):
170                 print "It seems as if stdio.h is missing. This probably means that your build environment is broken, please make sure you have a working c-compiler and libstdc installed and usable."
171                 Exit( 1 )
172         #
173         # ... and do the same with a c++-header. Because some distributions have
174         # distinct packages for gcc and g++.
175         #
176         if not conf.CheckHeader( "iostream", language="C++" ):
177                 print "It seems as if iostream is missing. This probably means that your build environment is broken, please make sure you have a working c++-compiler installed and usable."
178                 Exit( 1 )
179
180         #
181         # The following checks are for headers and libs and packages we need.
182         #
183         allpresent = 1;
184         allpresent &= conf.CheckHeader( "expat.h" )
185         allpresent &= conf.CheckLib( 'expat', 'XML_ExpatVersion', '#include <expat.h>' )
186        
187         allpresent &= conf.CheckForPKGConfig();
188
189         pkgs = {
190                 'libraw1394' : '1.3.0',
191                 'libavc1394' : '0.5.3',
192                 'libiec61883' : '1.1.0',
193                 'alsa' : '1.0.0',
194                 'libxml++-2.6' : '2.13.0',
195                 'dbus-1' : '1.0',
196                 }
197         for pkg in pkgs:
198                 name2 = pkg.replace("+","").replace(".","").replace("-","").upper()
199                 env['%s_FLAGS' % name2] = conf.GetPKGFlags( pkg, pkgs[pkg] )
200                 if env['%s_FLAGS'%name2] == 0:
201                         allpresent &= 0
202
203         if not allpresent:
204                 print """
205 (At least) One of the dependencies is missing. I can't go on without it, please
206 install the needed packages for each of the lines saying "no".
207 (Remember to also install the *-devel packages!)
208
209 And remember to remove the cache with "rm -Rf .sconsign.dblite cache" so the
210 results above get rechecked.
211 """
212                 Exit( 1 )
213
214         # Check for C99 lrint() and lrintf() functions used to convert from
215         # float to integer more efficiently via float_cast.h.  If not
216         # present the standard slower methods will be used instead.  This
217         # might not be the best way of testing for these but it's the only
218         # way which seems to work properly.  CheckFunc() fails due to
219         # argument count problems.
220         oldcf = env['CFLAGS']
221         oldcf = env.Append(CFLAGS = '-std=c99')
222         if conf.CheckLibWithHeader( "m", "math.h", "c", "lrint(3.2);" ):
223                 HAVE_LRINT = 1
224         else:
225                 HAVE_LRINT = 0
226         if conf.CheckLibWithHeader( "m", "math.h", "c", "lrintf(3.2);" ):
227                 HAVE_LRINTF = 1
228         else:
229                 HAVE_LRINTF = 0
230         env['HAVE_LRINT'] = HAVE_LRINT;
231         env['HAVE_LRINTF'] = HAVE_LRINTF;
232         env.Replace(CFLAGS=oldcf)
233
234         #
235         # Optional checks follow:
236         #
237         env['ALSA_SEQ_OUTPUT'] = conf.CheckLib( 'asound', symbol='snd_seq_event_output_direct', autoadd=0 )
238
239 if conf.CheckForApp( "which pyuic" ) and conf.CheckForPyModule( 'dbus' ) and conf.CheckForPyModule( 'qt' ):
240         env['PYUIC'] = True
241
242         if conf.CheckForApp( "xdg-desktop-menu --help" ):
243                 env['XDG_TOOLS'] = True
244         else:
245                 print """
246 I couldn't find the program 'xdg-desktop-menu'. Together with xdg-icon-resource
247 this is needed to add the fancy entry to your menu. But the mixer will be installed, you can start it by executing "ffadomixer".
248 """
249
250 else:
251         print """
252 I couldn't find all the prerequisites ('pyuic' and the python-modules 'dbus' and
253 'qt', the packages could be named like dbus-python and PyQt) to build the mixer.
254 Therefor the mixer won't get installed.
255 """
256
257 config_guess = conf.ConfigGuess()
258
259 env = conf.Finish()
260
261 if env['DEBUG']:
262         print "Doing a DEBUG build"
263         # -Werror could be added to, which would force the devs to really remove all the warnings :-)
264         env.AppendUnique( CCFLAGS=["-DDEBUG","-Wall","-g"] )
265         env.AppendUnique( CFLAGS=["-DDEBUG","-Wall","-g"] )
266 else:
267         env.AppendUnique( CCFLAGS=["-O2","-DNDEBUG"] )
268         env.AppendUnique( CFLAGS=["-O2","-DNDEBUG"] )
269
270 if env['PROFILE']:
271         print "Doing a PROFILE build"
272         # -Werror could be added to, which would force the devs to really remove all the warnings :-)
273         env.AppendUnique( CCFLAGS=["-Wall","-g"] )
274         env.AppendUnique( CFLAGS=["-Wall","-g"] )
275
276
277 # this is required to indicate that the DBUS version we use has support
278 # for platform dependent threading init functions
279 # this is true for DBUS >= 0.96 or so. Since we require >= 1.0 it is
280 # always true
281 env.AppendUnique( CCFLAGS=["-DDBUS_HAS_THREADS_INIT_DEFAULT"] )
282
283 if env['ENABLE_ALL']:
284         env['ENABLE_BEBOB'] = True
285         env['ENABLE_FIREWORKS'] = True
286         env['ENABLE_MOTU'] = True
287         env['ENABLE_DICE'] = True
288         env['ENABLE_METRIC_HALO'] = True
289         env['ENABLE_RME'] = True
290         env['ENABLE_BOUNCE'] = True
291
292 if env['ENABLE_BEBOB'] or env['ENABLE_DICE'] or env['ENABLE_BOUNCE'] or env['ENABLE_FIREWORKS']:
293         env['ENABLE_GENERICAVC'] = True
294
295 env['BUILD_STATIC_LIB'] = False
296 if env['BUILD_STATIC_TOOLS']:
297     print "Building static versions of the tools..."
298     env['BUILD_STATIC_LIB'] = True
299
300 if build_base:
301         env['build_base']="#/"+build_base
302 else:
303         env['build_base']="#/"
304
305 #
306 # Uppercase variables are for usage in code, lowercase versions for usage in
307 # scons-files for installing.
308 #
309 env['BINDIR'] = Template( env['BINDIR'] ).safe_substitute( env )
310 env['LIBDIR'] = Template( env['LIBDIR'] ).safe_substitute( env )
311 env['INCLUDEDIR'] = Template( env['INCLUDEDIR'] ).safe_substitute( env )
312 env['SHAREDIR'] = Template( env['SHAREDIR'] ).safe_substitute( env )
313 env['bindir'] = Template( destdir + env['BINDIR'] ).safe_substitute( env )
314 env['libdir'] = Template( destdir + env['LIBDIR'] ).safe_substitute( env )
315 env['includedir'] = Template( destdir + env['INCLUDEDIR'] ).safe_substitute( env )
316 env['sharedir'] = Template( destdir + env['SHAREDIR'] ).safe_substitute( env )
317
318 env.Command( target=env['sharedir'], source="", action=Mkdir( env['sharedir'] ) )
319
320 env.Alias( "install", env['libdir'] )
321 env.Alias( "install", env['includedir'] )
322 env.Alias( "install", env['sharedir'] )
323 env.Alias( "install", env['bindir'] )
324
325 #
326 # shamelessly copied from the Ardour scons file
327 #
328
329 opt_flags = []
330 env['USE_SSE'] = 0
331
332 # guess at the platform, used to define compiler flags
333
334 config_cpu = 0
335 config_arch = 1
336 config_kernel = 2
337 config_os = 3
338 config = config_guess.split ("-")
339
340 # Autodetect
341 if env['DIST_TARGET'] == 'auto':
342     if re.search ("x86_64", config[config_cpu]) != None:
343         env['DIST_TARGET'] = 'x86_64'
344     elif re.search("i[0-5]86", config[config_cpu]) != None:
345         env['DIST_TARGET'] = 'i386'
346     else:
347         env['DIST_TARGET'] = 'i686'
348     print "Detected DIST_TARGET = " + env['DIST_TARGET']
349
350 if ((re.search ("i[0-9]86", config[config_cpu]) != None) or (re.search ("x86_64", config[config_cpu]) != None)):
351    
352     build_host_supports_sse = 0
353     build_host_supports_sse2 = 0
354     build_host_supports_sse3 = 0
355
356     if config[config_kernel] == 'linux' :
357        
358         if env['DIST_TARGET'] != 'i386':
359            
360             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
361             x86_flags = flag_line.split (": ")[1:][0].split ()
362            
363             if "mmx" in x86_flags:
364                 opt_flags.append ("-mmmx")
365             if "sse" in x86_flags:
366                 build_host_supports_sse = 1
367             if "sse2" in x86_flags:
368                 build_host_supports_sse2 = 1
369             #if "sse3" in x86_flags:
370                 #build_host_supports_sse3 = 1
371             if "3dnow" in x86_flags:
372                 opt_flags.append ("-m3dnow")
373            
374             if config[config_cpu] == "i586":
375                 opt_flags.append ("-march=i586")
376             elif config[config_cpu] == "i686":
377                 opt_flags.append ("-march=i686")
378
379     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) \
380        and build_host_supports_sse and env['ENABLE_OPTIMIZATIONS']:
381         opt_flags.extend (["-msse", "-mfpmath=sse"])
382         env['USE_SSE'] = 1
383
384     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) \
385        and build_host_supports_sse2 and env['ENABLE_OPTIMIZATIONS']:
386         opt_flags.extend (["-msse2"])
387         env['USE_SSE2'] = 1
388
389     #if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) \
390        #and build_host_supports_sse2 and env['ENABLE_OPTIMIZATIONS']:
391         #opt_flags.extend (["-msse3"])
392         #env['USE_SSE3'] = 1
393
394 # end of processor-specific section
395 if env['ENABLE_OPTIMIZATIONS']:
396     opt_flags.extend (["-fomit-frame-pointer","-ffast-math","-funroll-loops"])
397     env.AppendUnique( CCFLAGS=opt_flags )
398     env.AppendUnique( CFLAGS=opt_flags )
399     print "Doing an optimized build..."
400
401 env['REVISION'] = os.popen('svnversion .').read()[:-1]
402 # This may be as simple as '89' or as complex as '4123:4184M'.
403 # We'll just use the last bit.
404 env['REVISION'] = env['REVISION'].split(':')[-1]
405
406 if env['REVISION'] == 'exported':
407         env['REVISION'] = ''
408
409 env['FFADO_API_VERSION']=FFADO_API_VERSION
410
411 env['PACKAGE'] = "libffado"
412 env['VERSION'] = FFADO_VERSION
413 env['LIBVERSION'] = "1.0.0"
414
415 #
416 # To have the top_srcdir as the doxygen-script is used from auto*
417 #
418 env['top_srcdir'] = env.Dir( "." ).abspath
419
420 #
421 # Start building
422 #
423 env.ScanReplace( "config.h.in" )
424 # ensure that the config.h is updated with the version
425 env.Depends( "config.h", "SConstruct" )
426 env.Depends( "config.h", 'cache/' + build_base + "options.cache" )
427
428 env.Depends( "libffado.pc", "SConstruct" )
429 pkgconfig = env.ScanReplace( "libffado.pc.in" )
430 env.Install( env['libdir'] + '/pkgconfig', pkgconfig )
431
432 subdirs=['external','src','libffado','tests','support','doc']
433 if build_base:
434         env.SConscript( dirs=subdirs, exports="env", build_dir=build_base+subdir )
435 else:
436         env.SConscript( dirs=subdirs, exports="env" )
437
438 if 'debian' in COMMAND_LINE_TARGETS:
439         env.SConscript("deb/SConscript", exports="env")
440
441 # By default only src is built but all is cleaned
442 if not env.GetOption('clean'):
443     Default( 'src' )
444     Default( 'support' )
445     if env['BUILD_TESTS']:
446         Default( 'tests' )
447
448 #
449 # Deal with the DESTDIR vs. xdg-tools conflict (which is basicely that the
450 # xdg-tools can't deal with DESTDIR, so the packagers have to deal with this
451 # their own :-/
452 #
453 if len(destdir) > 0:
454         if not len( ARGUMENTS.get( "WILL_DEAL_WITH_XDG_MYSELF", "" ) ) > 0:
455                 print """
456 WARNING!
457 You are using the (packagers) option DESTDIR to install this package to a
458 different place than the real prefix. As the xdg-tools can't cope with
459 that, the .desktop-files are not installed by this build, you have to
460 deal with them your own.
461 (And you have to look into the SConstruct to learn how to disable this
462 message.)
463 """
464 else:
465
466         def CleanAction( action ):
467                 if env.GetOption( "clean" ):
468                         env.Execute( action )
469
470         if env.has_key( 'XDG_TOOLS' ) and env.has_key( 'PYUIC' ):
471                 if not env.GetOption("clean"):
472                         action = "install"
473                 else:
474                         action = "uninstall"
475                 mixerdesktopaction = env.Action( "xdg-desktop-menu %s support/xdg/ffado.org-ffadomixer.desktop" % action )
476                 mixericonaction = env.Action( "xdg-icon-resource %s --size 64 --context apps support/xdg/hi64-apps-ffado.png" % action )
477                 env.Command( "__xdgstuff1", None, mixerdesktopaction )
478                 env.Command( "__xdgstuff2", None, mixericonaction )
479                 env.Alias( "install", ["__xdgstuff1", "__xdgstuff2" ] )
480                 CleanAction( mixerdesktopaction )
481                 CleanAction( mixericonaction )
482
483 #
484 # Create a tags-file for easier emacs/vim-source-browsing
485 #  I don't know if the dependency is right...
486 #
487 findcommand = "find . \( -path \"*.h\" -o -path \"*.cpp\" -o -path \"*.c\" \) \! -path \"*.svn*\" \! -path \"./doc*\" \! -path \"./cache*\""
488 env.Command( "tags", "", findcommand + " |xargs ctags" )
489 env.Command( "TAGS", "", findcommand + " |xargs etags" )
490 env.AlwaysBuild( "tags", "TAGS" )
491 env.NoCache( "tags", "TAGS" )
492
Note: See TracBrowser for help on using the browser.