1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2007, 2008, 2010 Arnold Krille
4 # Copyright (C) 2007, 2008 Pieter Palmers
5 # Copyright (C) 2008, 2012 Jonathan Woithe
7 # This file is part of FFADO
8 # FFADO = Free Firewire (pro-)audio drivers for linux
10 # FFADO is based upon FreeBoB.
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.
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.
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/>.
26 FFADO_API_VERSION
= "9"
27 FFADO_VERSION
="2.1.9999"
29 from subprocess
import Popen
, PIPE
32 from string
import Template
34 import distutils
.sysconfig
36 if not os
.path
.isdir( "cache" ):
37 os
.makedirs( "cache" )
39 opts
= Variables( "cache/options.cache" )
42 BoolVariable( "DEBUG", """\
43 Toggle debug-build. DEBUG means \"-g -Wall\" and more, otherwise we will use
44 \"-O2\" to optimize.""", True ),
45 BoolVariable( "PROFILE", "Build with symbols and other profiling info", False ),
46 PathVariable( "PREFIX", "The prefix where ffado will be installed to.", "/usr/local", PathVariable
.PathAccept
),
47 PathVariable( "BINDIR", "Overwrite the directory where apps are installed to.", "$PREFIX/bin", PathVariable
.PathAccept
),
48 PathVariable( "LIBDIR", "Overwrite the directory where libs are installed to.", "$PREFIX/lib", PathVariable
.PathAccept
),
49 PathVariable( "INCLUDEDIR", "Overwrite the directory where headers are installed to.", "$PREFIX/include", PathVariable
.PathAccept
),
50 PathVariable( "SHAREDIR", "Overwrite the directory where misc shared files are installed to.", "$PREFIX/share/libffado", PathVariable
.PathAccept
),
51 PathVariable( "MANDIR", "Overwrite the directory where manpages are installed", "$PREFIX/man", PathVariable
.PathAccept
),
52 PathVariable( "PYPKGDIR", "The directory where the python modules get installed.",
53 distutils
.sysconfig
.get_python_lib( prefix
="$PREFIX" ), PathVariable
.PathAccept
),
54 PathVariable( "UDEVDIR", "Overwrite the directory where udev rules are installed to.", "/lib/udev/rules.d/", PathVariable
.PathAccept
),
55 BoolVariable( "ENABLE_BEBOB", "Enable/Disable support for the BeBoB platform.", True ),
56 BoolVariable( "ENABLE_FIREWORKS", "Enable/Disable support for the ECHO Audio FireWorks platform.", True ),
57 BoolVariable( "ENABLE_OXFORD", "Enable/Disable support for the Oxford Semiconductor FW platform.", True ),
58 BoolVariable( "ENABLE_MOTU", "Enable/Disable support for the MOTU platform.", True ),
59 BoolVariable( "ENABLE_DICE", "Enable/Disable support for the TCAT DICE platform.", True ),
60 BoolVariable( "ENABLE_METRIC_HALO", "Enable/Disable support for the Metric Halo platform.", False ),
61 BoolVariable( "ENABLE_RME", "Enable/Disable support for the RME platform.", True ),
62 BoolVariable( "ENABLE_DIGIDESIGN", "Enable/Disable support for Digidesign interfaces.", False ),
63 BoolVariable( "ENABLE_BOUNCE", "Enable/Disable the BOUNCE device.", False ),
64 BoolVariable( "ENABLE_GENERICAVC", """\
65 Enable/Disable the the generic avc part (mainly used by apple).
66 Note that disabling this option might be overwritten by other devices needing
67 this code.""", False ),
68 BoolVariable( "ENABLE_ALL", "Enable/Disable support for all devices.", False ),
69 BoolVariable( "SERIALIZE_USE_EXPAT", "Use libexpat for XML serialization.", False ),
70 BoolVariable( "BUILD_TESTS", """\
71 Build the tests in their directory. As some contain quite some functionality,
72 this is on by default.
73 If you just want to use ffado with jack without the tools, you can disable this.\
75 BoolVariable( "BUILD_STATIC_TOOLS", "Build a statically linked version of the FFADO tools.", False ),
76 EnumVariable('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values
=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'powerpc64', 'none' ), ignorecase
=2),
77 BoolVariable( "ENABLE_OPTIMIZATIONS", "Enable optimizations and the use of processor specific extentions (MMX/SSE/...).", False ),
78 BoolVariable( "PEDANTIC", "Enable -Werror and more pedantic options during compile.", False ),
79 ( "COMPILE_FLAGS", "Add additional flags to the environment.\nOnly meant for distributors and gentoo-users who want to over-optimize their built.\n Using this is not supported by the ffado-devs!" ),
80 EnumVariable( "ENABLE_SETBUFFERSIZE_API_VER", "Report API version at runtime which includes support for dynamic buffer resizing (requires recent jack).", 'auto', allowed_values
=('auto', 'true', 'false', 'force'), ignorecase
=2),
84 ## Load the builders in config
87 env
= Environment( tools
=['default','scanreplace','pyuic','pyuic4','dbus','doxygen','pkgconfig'], toolpath
=['admin'], ENV
= buildenv
, options
=opts
)
89 if env
.has_key('COMPILE_FLAGS') and len(env
['COMPILE_FLAGS']) > 0:
91 * Usage of additional flags is not supported by the ffado-devs.
94 * Currentl value is '%s'
95 ''' % env
['COMPILE_FLAGS']
96 env
.MergeFlags(env
['COMPILE_FLAGS'])
99 For building ffado you can set different options as listed below. You have to
100 specify them only once, scons will save the last value you used and re-use
102 To really undo your settings and return to the factory defaults, remove the
103 "cache"-folder and the file ".sconsign.dblite" from this directory.
104 For example with: "rm -Rf .sconsign.dblite cache"
106 Note that this is a development version! Don't complain if its not working!
107 See www.ffado.org for stable releases.
109 Help( opts
.GenerateHelpText( env
) )
111 # make sure the necessary dirs exist
112 if not os
.path
.isdir( "cache" ):
113 os
.makedirs( "cache" )
114 if not os
.path
.isdir( 'cache/objects' ):
115 os
.makedirs( 'cache/objects' )
117 CacheDir( 'cache/objects' )
119 opts
.Save( 'cache/options.cache', env
)
121 def ConfigGuess( context
):
122 context
.Message( "Trying to find the system triple: " )
123 ret
= os
.popen( "/bin/sh admin/config.guess" ).read()[:-1]
124 context
.Result( ret
)
127 def CheckForApp( context
, app
):
128 context
.Message( "Checking whether '" + app
+ "' executes " )
129 ret
= context
.TryAction( app
)
130 context
.Result( ret
[0] )
133 def CheckForPyModule( context
, module
):
134 context
.Message( "Checking for the python module '" + module
+ "' " )
135 ret
= context
.TryAction( "python $SOURCE", "import %s" % module
, ".py" )
136 context
.Result( ret
[0] )
139 def CompilerCheck( context
):
140 context
.Message( "Checking for a working C-compiler " )
141 ret
= context
.TryRun( """
145 printf( "Hello World!" );
148 context
.Result( ret
)
151 context
.Message( "Checking for a working C++-compiler " )
152 ret
= context
.TryRun( """
156 std::cout << "Hello World!" << std::endl;
159 context
.Result( ret
)
162 def CheckPKG(context
, name
):
163 context
.Message( 'Checking for %s... ' % name
)
164 ret
= context
.TryAction('pkg-config --exists \'%s\'' % name
)[0]
165 context
.Result( ret
)
169 "ConfigGuess" : ConfigGuess
,
170 "CheckForApp" : CheckForApp
,
171 "CheckForPyModule": CheckForPyModule
,
172 "CompilerCheck" : CompilerCheck
,
173 "CheckPKG" : CheckPKG
,
175 tests
.update( env
['PKGCONFIG_TESTS'] )
176 tests
.update( env
['PYUIC_TESTS'] )
177 tests
.update( env
['PYUIC4_TESTS'] )
179 conf
= Configure( env
,
180 custom_tests
= tests
,
182 log_file
= 'cache/config.log' )
184 version_re
= re
.compile(r
'^(\d+)\.(\d+)\.(\d+)')
186 def VersionInt(vers
):
187 match
= version_re
.match(vers
)
190 (maj
, min, patch
) = match
.group(1, 2, 3)
191 # For now allow "min" to run up to 65535. "maj" and "patch" are
192 # restricted to 0-255.
193 return (int(maj
) << 24) |
(int(min) << 8) |
int(patch
)
196 print 'Checking jackd version...',
197 ret
= Popen("which jackd >/dev/null 2>&1 && jackd --version | tail -n 1 | cut -d ' ' -f 3", shell
=True, stdout
=PIPE
).stdout
.read()[:-1]
199 print "not installed"
203 return VersionInt(ret
)
205 if env
['SERIALIZE_USE_EXPAT']:
206 env
['SERIALIZE_USE_EXPAT']=1
208 env
['SERIALIZE_USE_EXPAT']=0
210 if env
['ENABLE_BOUNCE'] or env
['ENABLE_ALL']:
211 env
['REQUIRE_LIBAVC']=1
213 env
['REQUIRE_LIBAVC']=0
215 if not env
.GetOption('clean'):
217 # Check for working gcc and g++ compilers and their environment.
219 if not conf
.CompilerCheck():
220 print "\nIt seems as if your system isn't even able to compile any C-/C++-programs. Probably you don't have gcc and g++ installed. Compiling a package from source without a working compiler is very hard to do, please install the needed packages.\nHint: on *ubuntu you need both gcc- and g++-packages installed, easiest solution is to install build-essential which depends on gcc and g++."
223 # Check for pkg-config before using pkg-config to check for other dependencies.
224 if not conf
.CheckForPKGConfig():
225 print "\nThe program 'pkg-config' could not be found.\nEither you have to install the corresponding package first or make sure that PATH points to the right directions."
229 # The following checks are for headers and libs and packages we need.
232 # for cache-serialization.
233 if env
['SERIALIZE_USE_EXPAT']:
234 allpresent
&= conf
.CheckHeader( "expat.h" )
235 allpresent
&= conf
.CheckLib( 'expat', 'XML_ExpatVersion', '#include <expat.h>' )
238 'libraw1394' : '2.0.5',
239 'libiec61883' : '1.1.0',
243 if env
['REQUIRE_LIBAVC']:
244 pkgs
['libavc1394'] = '0.5.3'
246 if not env
['SERIALIZE_USE_EXPAT']:
247 pkgs
['libxml++-2.6'] = '2.13.0'
249 # Provide a way for users to compile newer libffado which will work
250 # against older jack installations which will not accept the new API
251 # version reported at runtime.
252 jackd_ver
= CheckJackdVer()
253 if (jackd_ver
!= -1):
254 # If jackd is available, use the version number reported by it. This
255 # means users don't have to have jack development files present on
256 # their system for this to work.
257 have_jack
= (jackd_ver
>= VersionInt('0.0.0'))
258 good_jack1
= (jackd_ver
< VersionInt('1.9.0')) and (jackd_ver
>= VersionInt('0.122.0'))
259 good_jack2
= (jackd_ver
>= VersionInt('1.9.9'))
261 # Jackd is not runnable. Attempt to identify a version from
262 # pkgconfig on the off-chance jack details are available from there.
263 print "Will retry jack detection using pkg-config"
264 have_jack
= conf
.CheckPKG('jack >= 0.0.0')
265 good_jack1
= conf
.CheckPKG('jack < 1.9.0') and conf
.CheckPKG('jack >= 0.122.0')
266 good_jack2
= conf
.CheckPKG('jack >= 1.9.9')
267 if env
['ENABLE_SETBUFFERSIZE_API_VER'] == 'auto':
270 No Jack Audio Connection Kit (JACK) installed: assuming a FFADO
271 setbuffersize-compatible version will be used.
273 elif not(good_jack1
or good_jack2
):
274 FFADO_API_VERSION
="8"
276 Installed Jack Audio Connection Kit (JACK) jack does not support FFADO
277 setbuffersize API: will report earlier API version at runtime. Consider
278 upgrading to jack1 >=0.122.0 or jack2 >=1.9.9 at some point, and then
279 recompile ffado to gain access to this added feature.
282 print "Installed Jack Audio Connection Kit (JACK) supports FFADO setbuffersize API"
283 elif env
['ENABLE_SETBUFFERSIZE_API_VER'] == 'true':
284 if (have_jack
and not(good_jack1
) and not(good_jack2
)):
286 SetBufferSize API version is enabled but no suitable version of Jack Audio
287 Connection Kit (JACK) has been found. The resulting FFADO would cause your
288 jackd to abort with "incompatible FFADO version". Please upgrade to
289 jack1 >=0.122.0 or jack2 >=1.9.9, or set ENABLE_SETBUFFERSIZE_API_VER to "auto"
292 # Although it's not strictly an error, in almost every case that
293 # this occurs the user will want to know about it and fix the
294 # problem, so we exit so they're guaranteed of seeing the above
298 print "Will report SetBufferSize API version at runtime"
299 elif env
['ENABLE_SETBUFFERSIZE_API_VER'] == 'force':
300 print "Will report SetBufferSize API version at runtime"
302 FFADO_API_VERSION
="8"
303 print "Will not report SetBufferSize API version at runtime"
306 name2
= pkg
.replace("+","").replace(".","").replace("-","").upper()
307 env
['%s_FLAGS' % name2
] = conf
.GetPKGFlags( pkg
, pkgs
[pkg
] )
308 #print '%s_FLAGS' % name2
309 if env
['%s_FLAGS'%name2
] == 0:
314 (At least) One of the dependencies is missing. I can't go on without it, please
315 install the needed packages for each of the lines saying "no".
316 (Remember to also install the *-devel packages!)
318 And remember to remove the cache with "rm -Rf .sconsign.dblite cache" so the
319 results above get rechecked.
323 # Check for C99 lrint() and lrintf() functions used to convert from
324 # float to integer more efficiently via float_cast.h. If not
325 # present the standard slower methods will be used instead. This
326 # might not be the best way of testing for these but it's the only
327 # way which seems to work properly. CheckFunc() fails due to
328 # argument count problems.
329 if env
.has_key( 'CFLAGS' ):
330 oldcf
= env
['CFLAGS']
333 oldcf
= env
.Append(CFLAGS
= '-std=c99')
334 if conf
.CheckLibWithHeader( "m", "math.h", "c", "lrint(3.2);" ):
338 if conf
.CheckLibWithHeader( "m", "math.h", "c", "lrintf(3.2);" ):
342 env
['HAVE_LRINT'] = HAVE_LRINT
;
343 env
['HAVE_LRINTF'] = HAVE_LRINTF
;
344 env
.Replace(CFLAGS
=oldcf
)
347 # Optional checks follow:
352 if conf
.CheckForApp( 'which pyuic4' ) and conf
.CheckForPyModule( 'dbus' ) and conf
.CheckForPyModule( 'PyQt4' ) and conf
.CheckForPyModule( 'dbus.mainloop.qt' ):
356 if conf
.CheckForApp( 'xdg-desktop-menu --help' ):
357 env
['XDG_TOOLS'] = True
360 I couldn't find the program 'xdg-desktop-menu'. Together with xdg-icon-resource
361 this is needed to add the fancy entry to your menu. But if the mixer will be
362 installed, you can start it by executing "ffado-mixer".
365 if not build_mixer
and not env
.GetOption('clean'):
367 I couldn't find all the prerequisites ('pyuic4' and the python-modules 'dbus'
368 and 'PyQt4', the packages could be named like dbus-python and PyQt) to build the
370 Therefor the qt4 mixer will not get installed.
374 # Optional pkg-config
382 name2
= pkg
.replace("+","").replace(".","").replace("-","").upper()
383 env
['%s_FLAGS' % name2
] = conf
.GetPKGFlags( pkg
, pkgs
[pkg
] )
385 if not env
['DBUS1_FLAGS'] or not env
['DBUSC1_FLAGS'] or not conf
.CheckForApp('which dbusxx-xml2cpp'):
386 env
['DBUS1_FLAGS'] = ""
387 env
['DBUSC1_FLAGS'] = ""
389 One of the dbus-headers, the dbus-c++-headers and/or the application
390 'dbusxx-xml2cpp' where not found. The dbus-server for ffado will therefore not
394 # Get the directory where dbus stores the service-files
395 env
['dbus_service_dir'] = conf
.GetPKGVariable( 'dbus-1', 'session_bus_services_dir' ).strip()
396 # this is required to indicate that the DBUS version we use has support
397 # for platform dependent threading init functions
398 # this is true for DBUS >= 0.96 or so. Since we require >= 1.0 it is
400 env
['DBUS1_FLAGS'] += " -DDBUS_HAS_THREADS_INIT_DEFAULT"
403 config_guess
= conf
.ConfigGuess()
408 print "Doing a DEBUG build"
409 env
.MergeFlags( "-DDEBUG -Wall -g" )
411 env
.MergeFlags( "-O2 -DNDEBUG" )
414 print "Doing a PROFILE build"
415 env
.MergeFlags( "-Wall -g" )
418 env
.MergeFlags( "-Werror" )
421 if env
['ENABLE_ALL']:
422 env
['ENABLE_BEBOB'] = True
423 env
['ENABLE_FIREWORKS'] = True
424 env
['ENABLE_OXFORD'] = True
425 env
['ENABLE_MOTU'] = True
426 env
['ENABLE_DICE'] = True
427 env
['ENABLE_METRIC_HALO'] = True
428 env
['ENABLE_RME'] = True
429 env
['ENABLE_DIGIDESIGN'] = True
430 env
['ENABLE_BOUNCE'] = True
433 env
['BUILD_STATIC_LIB'] = False
434 if env
['BUILD_STATIC_TOOLS']:
435 print "Building static versions of the tools..."
436 env
['BUILD_STATIC_LIB'] = True
438 env
['build_base']="#/"
441 # Get the DESTDIR (if wanted) from the commandline
443 env
.destdir
= ARGUMENTS
.get( 'DESTDIR', "" )
446 # Uppercase variables are for usage in code, lowercase versions for usage in
447 # scons-files for installing.
449 env
['BINDIR'] = Template( env
['BINDIR'] ).safe_substitute( env
)
450 env
['LIBDIR'] = Template( env
['LIBDIR'] ).safe_substitute( env
)
451 env
['INCLUDEDIR'] = Template( env
['INCLUDEDIR'] ).safe_substitute( env
)
452 env
['SHAREDIR'] = Template( env
['SHAREDIR'] ).safe_substitute( env
)
453 env
['UDEVDIR'] = Template( env
['UDEVDIR'] ).safe_substitute( env
)
454 env
['prefix'] = Template( env
.destdir
+ env
['PREFIX'] ).safe_substitute( env
)
455 env
['bindir'] = Template( env
.destdir
+ env
['BINDIR'] ).safe_substitute( env
)
456 env
['libdir'] = Template( env
.destdir
+ env
['LIBDIR'] ).safe_substitute( env
)
457 env
['includedir'] = Template( env
.destdir
+ env
['INCLUDEDIR'] ).safe_substitute( env
)
458 env
['sharedir'] = Template( env
.destdir
+ env
['SHAREDIR'] ).safe_substitute( env
)
459 env
['mandir'] = Template( env
.destdir
+ env
['MANDIR'] ).safe_substitute( env
)
460 env
['pypkgdir'] = Template( env
.destdir
+ env
['PYPKGDIR'] ).safe_substitute( env
)
461 env
['udevdir'] = Template( env
.destdir
+ env
['UDEVDIR'] ).safe_substitute( env
)
462 env
['PYPKGDIR'] = Template( env
['PYPKGDIR'] ).safe_substitute( env
)
464 env
.Command( target
=env
['sharedir'], source
="", action
=Mkdir( env
['sharedir'] ) )
466 env
.Alias( "install", env
['libdir'] )
467 env
.Alias( "install", env
['includedir'] )
468 env
.Alias( "install", env
['sharedir'] )
469 env
.Alias( "install", env
['bindir'] )
470 env
.Alias( "install", env
['mandir'] )
472 env
.Alias( "install", env
['pypkgdir'] )
475 # shamelessly copied from the Ardour scons file
481 # guess at the platform, used to define compiler flags
487 config
= config_guess
.split ("-")
491 #=== Begin Revised CXXFLAGS =========================================
493 """Run a command without running a shell, return cmd's stdout
495 p
= Popen(cmd
, stdout
=PIPE
)
496 return p
.communicate()[0]
499 """generator which reads lines from Linux /proc/cpuinfo and splits them
500 into key:value tokens and yields (key, value) tuple.
502 f
= open('/proc/cpuinfo', 'r')
506 k
,v
= line
.split(':')
507 yield (k
.strip(), v
.strip())
511 class CpuInfo (object):
512 """Collects information about the CPU, mainly from /proc/cpuinfo
515 self
.sysname
, self
.hostname
, self
.release
, self
.version
, self
.machine
= os
.uname()
516 # general CPU architecture
517 self
.is_x86
= self
.machine
in ('i686', 'x86_64') or \
518 re
.match("i[3-5]86", self
.machine
) or False
519 self
.is_powerpc
= self
.machine
in ('ppc64', 'ppc', 'powerpc', 'powerpc64')
520 #!!! probably not comprehensive
521 self
.is_mips
= self
.machine
== 'mips'
522 #!!! not a comprehensive list. uname -m on one android phone reports 'armv71'
523 # I have no other arm devices I can check
524 self
.is_arm
= self
.machine
in ('armv71', )
529 elif self
.is_powerpc
:
534 # 64-bit (x86_64/AMD64/Intel64)
535 # Long Mode (x86-64: amd64, also known as Intel 64, i.e. 64-bit capable)
536 self
.is_64bit
= (self
.is_x86
and 'lm' in self
.x86_flags
) or \
537 (self
.is_powerpc
and '970' in self
.ppc_type
)
539 # Hardware virtualization capable: vmx (Intel), svm (AMD)
540 self
.has_hwvirt
= self
.is_x86
and (
541 (self
.is_amd
and 'svm' in self
.x86_flags
) or
542 (self
.is_intel
and 'vmx' in self
.x86_flags
))
544 # Physical Address Extensions (support for more than 4GB of RAM)
545 self
.has_pae
= self
.is_x86
and 'pae' in self
.x86_flags
548 def cpu_info_x86(self
):
549 "parse /proc/cpuinfo for x86 kernels"
550 for k
,v
in cpuinfo_kv():
553 if self
.cpu_count
> 1:
554 # assume all CPUs are identical features, no need to
557 elif k
== 'vendor_id': # AuthenticAMD, GenuineIntel
559 self
.is_amd
= v
== 'AuthenticAMD'
560 self
.is_intel
= v
== 'GenuineIntel'
562 self
.x86_flags
= v
.split()
563 elif k
== 'model name':
565 elif k
== 'cpu family':
570 def cpu_info_ppc(self
):
571 "parse /proc/cpuinfo for PowerPC kernels"
572 # http://en.wikipedia.org/wiki/List_of_PowerPC_processors
574 # PowerPC 740 and 750, 233-366 MHz
575 # 745/755, 300–466 MHz
578 # 7400/7410 350 - 550 MHz, uses AltiVec, a SIMD extension of the original PPC specs
579 # 7450 micro-architecture family up to 1.5 GHz and 256 kB on-chip L2 cache and improved Altivec
580 # 7447/7457 micro-architecture family up to 1.8 GHz with 512 kB on-chip L2 cache
581 # 7448 micro-architecture family (1.5 GHz) in 90 nm with 1MB L2 cache and slightly
582 # improved AltiVec (out of order instructions).
583 # 8640/8641/8640D/8641D with one or two e600 (Formerly known as G4) cores, 1MB L2 cache
586 # 970 (2003), 64-bit, derived from POWER4, enhanced with VMX, 512 kB L2 cache, 1.4 – 2 GHz
587 # 970FX (2004), manufactured at 90 nm, 1.8 - 2.7 GHz
588 # 970GX (2006), manufactured at 90 nm, 1MB L2 cache/core, 1.2 - 2.5 GHz
589 # 970MP (2005), dual core, 1 MB L2 cache/core, 1.6 - 2.5 GHz
590 for k
,v
in cpuinfo_kv():
594 self
.is_altivec_supported
= 'altivec' in v
595 ppc_type
, x
= v
.split(',')
596 self
.ppc_type
= ppc_type
.strip()
597 # older kernels might not have a 'processor' line
598 if self
.cpu_count
== 0:
602 def cpu_info_mips(self
):
603 "parse /proc/cpuinfo for MIPS kernels"
604 for k
,v
in cpuinfo_kv():
607 elif k
== 'cpu model':
608 self
.mips_cpu_model
= v
611 def is_userspace_32bit(cpuinfo
):
612 """Even if `uname -m` reports a 64-bit architecture, userspace could still
613 be 32-bit, such as Debian on powerpc64. This function tries to figure out
614 if userspace is 32-bit, i.e. we might need to pass '-m32' or '-m64' to gcc.
616 if not cpuinfo
.is_64bit
:
618 # note that having a 64-bit CPU means nothing for these purposes. You could
619 # run a completely 32-bit system on a 64-bit capable CPU.
621 # Debian ppc64 returns machine 'ppc64', but userspace might be 32-bit
622 # We'll make an educated guess by examining a known executable
624 if os
.path
.isfile(exe
):
625 #print 'Found %s' % exe
626 if os
.path
.islink(exe
):
627 real_exe
= os
.path
.join(os
.path
.dirname(exe
), os
.readlink(exe
))
628 #print '%s is a symlink to %s' % (exe, real_exe)
631 # presumably if a person is running this script, they should have
632 # a gcc toolchain installed...
633 x
= outputof('objdump', '-Wi', real_exe
)
634 # should emit a line that looks like this:
635 # /bin/mount: file format elf32-i386
637 # /bin/mount: file format elf64-x86-64
639 # /bin/mount: file format elf32-powerpc
640 for line
in x
.split('\n'):
642 if line
.startswith(real_exe
) and 'file format' in line
:
643 x
, fmt
= line
.rsplit(None, 1)
644 answer
= 'elf32' in fmt
647 print '!!! Not found %s' % exe
651 def cc_flags_x86(cpuinfo
, enable_optimizations
):
652 """add certain gcc -m flags based on CPU features
654 # See http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/i386-and-x86_002d64-Options.html
656 if cpuinfo
.machine
== 'i586':
657 cc_opts
.append('-march=i586')
658 elif cpuinfo
.machine
== 'i686':
659 cc_opts
.append('-march=i686')
661 if 'mmx' in cpuinfo
.x86_flags
:
662 cc_opts
.append('-mmmx')
664 # map from proc/cpuinfo flags to gcc options
666 ('sse', ('-mfpmath=sse', '-msse')),
668 ('ssse3', '-mssse3'),
670 ('sse4_1', '-msse4.1'),
671 ('sse4_2', '-msse4.2'),
672 ('sse4a', '-msse4a'),
673 ('3dnow', '-m3dnow'),
675 if enable_optimizations
:
676 for flag
, gccopt
in opt_flags
:
677 if flag
in cpuinfo
.x86_flags
:
678 if isinstance(gccopt
, (tuple, list)):
679 cc_opts
.extend(gccopt
)
681 cc_opts
.append(gccopt
)
685 def cc_flags_powerpc(cpuinfo
, enable_optimizations
):
686 """add certain gcc -m flags based on CPU model
689 if cpuinfo
.is_altivec_supported
:
690 cc_opts
.append ('-maltivec')
691 cc_opts
.append ('-mabi=altivec')
693 if re
.match('74[0145][0578]A?', cpuinfo
.ppc_type
) is not None:
694 cc_opts
.append ('-mcpu=7400')
695 cc_opts
.append ('-mtune=7400')
696 elif re
.match('750', cpuinfo
.ppc_type
) is not None:
697 cc_opts
.append ('-mcpu=750')
698 cc_opts
.append ('-mtune=750')
699 elif re
.match('PPC970', cpuinfo
.ppc_type
) is not None:
700 cc_opts
.append ('-mcpu=970')
701 cc_opts
.append ('-mtune=970')
702 elif re
.match('Cell Broadband Engine', cpuinfo
.ppc_type
) is not None:
703 cc_opts
.append('-mcpu=cell')
704 cc_opts
.append('-mtune=cell')
706 #=== End Revised CXXFLAGS =========================================
709 if env
['DIST_TARGET'] == 'auto':
710 if re
.search ("x86_64", config
[config_cpu
]) is not None:
711 env
['DIST_TARGET'] = 'x86_64'
712 elif re
.search("i[0-5]86", config
[config_cpu
]) is not None:
713 env
['DIST_TARGET'] = 'i386'
714 elif re
.search("i686", config
[config_cpu
]) is not None:
715 env
['DIST_TARGET'] = 'i686'
716 elif re
.search("powerpc64", config
[config_cpu
]) is not None:
717 env
['DIST_TARGET'] = 'powerpc64'
718 elif re
.search("powerpc", config
[config_cpu
]) is not None:
719 env
['DIST_TARGET'] = 'powerpc'
721 env
['DIST_TARGET'] = config
[config_cpu
]
722 print "Detected DIST_TARGET = " + env
['DIST_TARGET']
724 #=== Begin Revised CXXFLAGS =========================================
725 # comment on DIST_TARGET up top implies it can be used for cross-compiling
726 # but that's not true because even if it is not 'auto' the original
727 # script still reads /proc/cpuinfo to determine gcc arch flags.
728 # This script does the same as the original. Needs to be fixed someday.
731 opt_flags
.extend(cc_flags_x86(cpuinfo
, env
['ENABLE_OPTIMIZATIONS']))
732 if cpuinfo
.is_powerpc
:
733 opt_flags
.extend(cc_flags_powerpc(cpuinfo
, env
['ENABLE_OPTIMIZATIONS']))
734 if '-msse' in opt_flags
:
736 if '-msse2' in opt_flags
:
739 m32
= is_userspace_32bit(cpuinfo
)
740 print 'User space is %s' % (m32
and '32-bit' or '64-bit')
741 if cpuinfo
.is_powerpc
:
743 print "Doing a 32-bit PowerPC build for %s CPU" % cpuinfo
.ppc_type
744 machineflags
= { 'CXXFLAGS' : ['-m32'] }
746 print "Doing a 64-bit PowerPC build for %s CPU" % cpuinfo
.ppc_type
747 machineflags
= { 'CXXFLAGS' : ['-m64'] }
748 env
.MergeFlags( machineflags
)
751 print "Doing a 32-bit %s build for %s" % (cpuinfo
.machine
, cpuinfo
.model_name
)
752 machineflags
= { 'CXXFLAGS' : ['-m32'] }
754 print "Doing a 64-bit %s build for %s" % (cpuinfo
.machine
, cpuinfo
.model_name
)
755 machineflags
= { 'CXXFLAGS' : ['-m64'] }
757 env
.MergeFlags( machineflags
)
758 #=== End Revised CXXFLAGS =========================================
761 if needs_fPIC
or ( env
.has_key('COMPILE_FLAGS') and '-fPIC' in env
['COMPILE_FLAGS'] ):
762 env
.MergeFlags( "-fPIC" )
764 # end of processor-specific section
765 if env
['ENABLE_OPTIMIZATIONS']:
766 opt_flags
.extend (["-fomit-frame-pointer","-ffast-math","-funroll-loops"])
767 env
.MergeFlags( opt_flags
)
768 print "Doing an optimized build..."
770 env
['REVISION'] = os
.popen('svnversion .').read()[:-1]
771 # This may be as simple as '89' or as complex as '4123:4184M'.
772 # We'll just use the last bit.
773 env
['REVISION'] = env
['REVISION'].split(':')[-1]
775 # try to circumvent localized versions
776 if len(env
['REVISION']) >= 5 and env
['REVISION'][0:6] == 'export':
779 # avoid the 1.999.41- type of version for exported versions
780 if env
['REVISION'] != '':
781 env
['REVISIONSTRING'] = '-' + env
['REVISION']
783 env
['REVISIONSTRING'] = ''
785 env
['FFADO_API_VERSION'] = FFADO_API_VERSION
787 env
['PACKAGE'] = "libffado"
788 env
['VERSION'] = FFADO_VERSION
789 env
['LIBVERSION'] = "1.0.0"
791 env
['CONFIGDIR'] = "~/.ffado"
792 env
['CACHEDIR'] = "~/.ffado"
794 env
['USER_CONFIG_FILE'] = env
['CONFIGDIR'] + "/configuration"
795 env
['SYSTEM_CONFIG_FILE'] = env
['SHAREDIR'] + "/configuration"
797 env
['REGISTRATION_URL'] = "http://ffado.org/deviceregistration/register.php?action=register"
800 # To have the top_srcdir as the doxygen-script is used from auto*
802 env
['top_srcdir'] = env
.Dir( "." ).abspath
807 env
.ScanReplace( "config.h.in" )
808 env
.ScanReplace( "config_debug.h.in" )
809 env
.ScanReplace( "version.h.in" )
811 # ensure that the config.h is updated
812 env
.Depends( "config.h", "SConstruct" )
813 env
.Depends( "config.h", 'cache/options.cache' )
815 # update version.h whenever the version or SVN revision changes
816 env
.Depends( "version.h", env
.Value(env
['REVISION']))
817 env
.Depends( "version.h", env
.Value(env
['VERSION']))
819 env
.Depends( "libffado.pc", "SConstruct" )
820 pkgconfig
= env
.ScanReplace( "libffado.pc.in" )
821 env
.Install( env
['libdir'] + '/pkgconfig', pkgconfig
)
823 env
.Install( env
['sharedir'], 'configuration' )
825 subdirs
=['src','libffado','support','doc']
826 if env
['BUILD_TESTS']:
827 subdirs
.append('tests')
829 env
.SConscript( dirs
=subdirs
, exports
="env" )
831 if 'debian' in COMMAND_LINE_TARGETS
:
832 env
.SConscript("deb/SConscript", exports
="env")
834 # By default only src is built but all is cleaned
835 if not env
.GetOption('clean'):
838 if env
['BUILD_TESTS']:
842 # Deal with the DESTDIR vs. xdg-tools conflict (which is basicely that the
843 # xdg-tools can't deal with DESTDIR, so the packagers have to deal with this
846 if len(env
.destdir
) > 0:
847 if not len( ARGUMENTS
.get( "WILL_DEAL_WITH_XDG_MYSELF", "" ) ) > 0:
850 You are using the (packagers) option DESTDIR to install this package to a
851 different place than the real prefix. As the xdg-tools can't cope with
852 that, the .desktop-files are not installed by this build, you have to
853 deal with them your own.
854 (And you have to look into the SConstruct to learn how to disable this
859 def CleanAction( action
):
860 if env
.GetOption( "clean" ):
861 env
.Execute( action
)
863 if env
.has_key( 'XDG_TOOLS' ) and env
.has_key( 'PYUIC4' ):
864 if not env
.GetOption("clean"):
868 mixerdesktopaction
= env
.Action( "-xdg-desktop-menu %s support/xdg/ffado.org-ffadomixer.desktop" % action
)
869 mixericonaction
= env
.Action( "-xdg-icon-resource %s --size 64 --novendor --context apps support/xdg/hi64-apps-ffado.png ffado" % action
)
870 env
.Command( "__xdgstuff1", None, mixerdesktopaction
)
871 env
.Command( "__xdgstuff2", None, mixericonaction
)
872 env
.Alias( "install", ["__xdgstuff1", "__xdgstuff2" ] )
873 CleanAction( mixerdesktopaction
)
874 CleanAction( mixericonaction
)
877 # Create a tags-file for easier emacs/vim-source-browsing
878 # I don't know if the dependency is right...
880 findcommand
= "find . \( -path \"*.h\" -o -path \"*.cpp\" -o -path \"*.c\" \) \! -path \"*.svn*\" \! -path \"./doc*\" \! -path \"./cache*\""
881 env
.Command( "tags", "", findcommand
+ " |xargs ctags" )
882 env
.Command( "TAGS", "", findcommand
+ " |xargs etags" )
883 env
.AlwaysBuild( "tags", "TAGS" )
884 if 'NoCache' in dir(env
):
885 env
.NoCache( "tags", "TAGS" )
887 # Another convinience target
888 if env
.GetOption( "clean" ):
889 env
.Execute( "rm cache/objects -Rf" )