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_BUILD", "Build with \"-g -Wall\" rather than \"-O2\"", False ),
43 BoolVariable( "DEBUG", "Enable support for debug messages", True ),
44 BoolVariable( "PROFILE", "Build with symbols and other profiling info", False ),
45 PathVariable( "PREFIX", "The prefix where ffado will be installed to.", "/usr/local", PathVariable
.PathAccept
),
46 PathVariable( "BINDIR", "Overwrite the directory where apps are installed to.", "$PREFIX/bin", PathVariable
.PathAccept
),
47 PathVariable( "LIBDIR", "Overwrite the directory where libs are installed to.", "$PREFIX/lib", PathVariable
.PathAccept
),
48 PathVariable( "INCLUDEDIR", "Overwrite the directory where headers are installed to.", "$PREFIX/include", PathVariable
.PathAccept
),
49 PathVariable( "SHAREDIR", "Overwrite the directory where misc shared files are installed to.", "$PREFIX/share/libffado", PathVariable
.PathAccept
),
50 PathVariable( "MANDIR", "Overwrite the directory where manpages are installed", "$PREFIX/man", PathVariable
.PathAccept
),
51 PathVariable( "PYPKGDIR", "The directory where the python modules get installed.",
52 distutils
.sysconfig
.get_python_lib( prefix
="$PREFIX" ), PathVariable
.PathAccept
),
53 PathVariable( "UDEVDIR", "Overwrite the directory where udev rules are installed to.", "/lib/udev/rules.d/", PathVariable
.PathAccept
),
54 BoolVariable( "ENABLE_BEBOB", "Enable/Disable support for the BeBoB platform.", True ),
55 BoolVariable( "ENABLE_FIREWORKS", "Enable/Disable support for the ECHO Audio FireWorks platform.", True ),
56 BoolVariable( "ENABLE_OXFORD", "Enable/Disable support for the Oxford Semiconductor FW platform.", True ),
57 BoolVariable( "ENABLE_MOTU", "Enable/Disable support for the MOTU platform.", True ),
58 BoolVariable( "ENABLE_DICE", "Enable/Disable support for the TCAT DICE platform.", True ),
59 BoolVariable( "ENABLE_METRIC_HALO", "Enable/Disable support for the Metric Halo platform.", False ),
60 BoolVariable( "ENABLE_RME", "Enable/Disable support for the RME platform.", True ),
61 BoolVariable( "ENABLE_DIGIDESIGN", "Enable/Disable support for Digidesign interfaces.", False ),
62 BoolVariable( "ENABLE_BOUNCE", "Enable/Disable the BOUNCE device.", False ),
63 BoolVariable( "ENABLE_GENERICAVC", """\
64 Enable/Disable the the generic avc part (mainly used by apple).
65 Note that disabling this option might be overwritten by other devices needing
66 this code.""", False ),
67 BoolVariable( "ENABLE_ALL", "Enable/Disable support for all devices.", False ),
68 BoolVariable( "SERIALIZE_USE_EXPAT", "Use libexpat for XML serialization.", False ),
69 BoolVariable( "BUILD_TESTS", """\
70 Build the tests in their directory. As some contain quite some functionality,
71 this is on by default.
72 If you just want to use ffado with jack without the tools, you can disable this.\
74 BoolVariable( "BUILD_STATIC_TOOLS", "Build a statically linked version of the FFADO tools.", False ),
75 EnumVariable('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values
=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'powerpc64', 'none' ), ignorecase
=2),
76 BoolVariable( "ENABLE_OPTIMIZATIONS", "Enable optimizations and the use of processor specific extentions (MMX/SSE/...).", False ),
77 BoolVariable( "PEDANTIC", "Enable -Werror and more pedantic options during compile.", False ),
78 ( "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!" ),
79 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),
83 ## Load the builders in config
86 env
= Environment( tools
=['default','scanreplace','pyuic','pyuic4','dbus','doxygen','pkgconfig'], toolpath
=['admin'], ENV
= buildenv
, options
=opts
)
88 if env
.has_key('COMPILE_FLAGS') and len(env
['COMPILE_FLAGS']) > 0:
90 * Usage of additional flags is not supported by the ffado-devs.
93 * Currentl value is '%s'
94 ''' % env
['COMPILE_FLAGS']
95 env
.MergeFlags(env
['COMPILE_FLAGS'])
98 For building ffado you can set different options as listed below. You have to
99 specify them only once, scons will save the last value you used and re-use
101 To really undo your settings and return to the factory defaults, remove the
102 "cache"-folder and the file ".sconsign.dblite" from this directory.
103 For example with: "rm -Rf .sconsign.dblite cache"
105 Note that this is a development version! Don't complain if its not working!
106 See www.ffado.org for stable releases.
108 Help( opts
.GenerateHelpText( env
) )
110 # make sure the necessary dirs exist
111 if not os
.path
.isdir( "cache" ):
112 os
.makedirs( "cache" )
113 if not os
.path
.isdir( 'cache/objects' ):
114 os
.makedirs( 'cache/objects' )
116 CacheDir( 'cache/objects' )
118 opts
.Save( 'cache/options.cache', env
)
120 def ConfigGuess( context
):
121 context
.Message( "Trying to find the system triple: " )
122 ret
= os
.popen( "/bin/sh admin/config.guess" ).read()[:-1]
123 context
.Result( ret
)
126 def CheckForApp( context
, app
):
127 context
.Message( "Checking whether '" + app
+ "' executes " )
128 ret
= context
.TryAction( app
)
129 context
.Result( ret
[0] )
132 def CheckForPyModule( context
, module
):
133 context
.Message( "Checking for the python module '" + module
+ "' " )
134 ret
= context
.TryAction( "python $SOURCE", "import %s" % module
, ".py" )
135 context
.Result( ret
[0] )
138 def CompilerCheck( context
):
139 context
.Message( "Checking for a working C-compiler " )
140 ret
= context
.TryRun( """
144 printf( "Hello World!" );
147 context
.Result( ret
)
150 context
.Message( "Checking for a working C++-compiler " )
151 ret
= context
.TryRun( """
155 std::cout << "Hello World!" << std::endl;
158 context
.Result( ret
)
161 def CheckPKG(context
, name
):
162 context
.Message( 'Checking for %s... ' % name
)
163 ret
= context
.TryAction('pkg-config --exists \'%s\'' % name
)[0]
164 context
.Result( ret
)
168 "ConfigGuess" : ConfigGuess
,
169 "CheckForApp" : CheckForApp
,
170 "CheckForPyModule": CheckForPyModule
,
171 "CompilerCheck" : CompilerCheck
,
172 "CheckPKG" : CheckPKG
,
174 tests
.update( env
['PKGCONFIG_TESTS'] )
175 tests
.update( env
['PYUIC_TESTS'] )
176 tests
.update( env
['PYUIC4_TESTS'] )
178 conf
= Configure( env
,
179 custom_tests
= tests
,
181 log_file
= 'cache/config.log' )
183 version_re
= re
.compile(r
'^(\d+)\.(\d+)\.(\d+)')
185 def VersionInt(vers
):
186 match
= version_re
.match(vers
)
189 (maj
, min, patch
) = match
.group(1, 2, 3)
190 # For now allow "min" to run up to 65535. "maj" and "patch" are
191 # restricted to 0-255.
192 return (int(maj
) << 24) |
(int(min) << 8) |
int(patch
)
195 print 'Checking jackd version...',
196 ret
= Popen("which jackd >/dev/null 2>&1 && jackd --version | tail -n 1 | cut -d ' ' -f 3", shell
=True, stdout
=PIPE
).stdout
.read()[:-1]
198 print "not installed"
202 return VersionInt(ret
)
204 if env
['SERIALIZE_USE_EXPAT']:
205 env
['SERIALIZE_USE_EXPAT']=1
207 env
['SERIALIZE_USE_EXPAT']=0
209 if env
['ENABLE_BOUNCE'] or env
['ENABLE_ALL']:
210 env
['REQUIRE_LIBAVC']=1
212 env
['REQUIRE_LIBAVC']=0
214 if not env
.GetOption('clean'):
216 # Check for working gcc and g++ compilers and their environment.
218 if not conf
.CompilerCheck():
219 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++."
222 # Check for pkg-config before using pkg-config to check for other dependencies.
223 if not conf
.CheckForPKGConfig():
224 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."
228 # The following checks are for headers and libs and packages we need.
231 # for cache-serialization.
232 if env
['SERIALIZE_USE_EXPAT']:
233 allpresent
&= conf
.CheckHeader( "expat.h" )
234 allpresent
&= conf
.CheckLib( 'expat', 'XML_ExpatVersion', '#include <expat.h>' )
237 'libraw1394' : '2.0.5',
238 'libiec61883' : '1.1.0',
242 if env
['REQUIRE_LIBAVC']:
243 pkgs
['libavc1394'] = '0.5.3'
245 if not env
['SERIALIZE_USE_EXPAT']:
246 pkgs
['libxml++-2.6'] = '2.13.0'
248 # Provide a way for users to compile newer libffado which will work
249 # against older jack installations which will not accept the new API
250 # version reported at runtime.
251 jackd_ver
= CheckJackdVer()
252 if (jackd_ver
!= -1):
253 # If jackd is available, use the version number reported by it. This
254 # means users don't have to have jack development files present on
255 # their system for this to work.
256 have_jack
= (jackd_ver
>= VersionInt('0.0.0'))
257 good_jack1
= (jackd_ver
< VersionInt('1.9.0')) and (jackd_ver
>= VersionInt('0.121.4'))
258 good_jack2
= (jackd_ver
>= VersionInt('1.9.9'))
260 # Jackd is not runnable. Attempt to identify a version from
261 # pkgconfig on the off-chance jack details are available from there.
262 print "Will retry jack detection using pkg-config"
263 have_jack
= conf
.CheckPKG('jack >= 0.0.0')
264 good_jack1
= conf
.CheckPKG('jack < 1.9.0') and conf
.CheckPKG('jack >= 0.122.0')
265 good_jack2
= conf
.CheckPKG('jack >= 1.9.9')
266 if env
['ENABLE_SETBUFFERSIZE_API_VER'] == 'auto':
269 No Jack Audio Connection Kit (JACK) installed: assuming a FFADO
270 setbuffersize-compatible version will be used.
272 elif not(good_jack1
or good_jack2
):
273 FFADO_API_VERSION
="8"
275 Installed Jack Audio Connection Kit (JACK) jack does not support FFADO
276 setbuffersize API: will report earlier API version at runtime. Consider
277 upgrading to jack1 >=0.122.0 or jack2 >=1.9.9 at some point, and then
278 recompile ffado to gain access to this added feature.
281 print "Installed Jack Audio Connection Kit (JACK) supports FFADO setbuffersize API"
282 elif env
['ENABLE_SETBUFFERSIZE_API_VER'] == 'true':
283 if (have_jack
and not(good_jack1
) and not(good_jack2
)):
285 SetBufferSize API version is enabled but no suitable version of Jack Audio
286 Connection Kit (JACK) has been found. The resulting FFADO would cause your
287 jackd to abort with "incompatible FFADO version". Please upgrade to
288 jack1 >=0.122.0 or jack2 >=1.9.9, or set ENABLE_SETBUFFERSIZE_API_VER to "auto"
291 # Although it's not strictly an error, in almost every case that
292 # this occurs the user will want to know about it and fix the
293 # problem, so we exit so they're guaranteed of seeing the above
297 print "Will report SetBufferSize API version at runtime"
298 elif env
['ENABLE_SETBUFFERSIZE_API_VER'] == 'force':
299 print "Will report SetBufferSize API version at runtime"
301 FFADO_API_VERSION
="8"
302 print "Will not report SetBufferSize API version at runtime"
305 name2
= pkg
.replace("+","").replace(".","").replace("-","").upper()
306 env
['%s_FLAGS' % name2
] = conf
.GetPKGFlags( pkg
, pkgs
[pkg
] )
307 #print '%s_FLAGS' % name2
308 if env
['%s_FLAGS'%name2
] == 0:
313 (At least) One of the dependencies is missing. I can't go on without it, please
314 install the needed packages for each of the lines saying "no".
315 (Remember to also install the *-devel packages!)
317 And remember to remove the cache with "rm -Rf .sconsign.dblite cache" so the
318 results above get rechecked.
322 # Check for C99 lrint() and lrintf() functions used to convert from
323 # float to integer more efficiently via float_cast.h. If not
324 # present the standard slower methods will be used instead. This
325 # might not be the best way of testing for these but it's the only
326 # way which seems to work properly. CheckFunc() fails due to
327 # argument count problems.
328 if env
.has_key( 'CFLAGS' ):
329 oldcf
= env
['CFLAGS']
332 oldcf
= env
.Append(CFLAGS
= '-std=c99')
333 if conf
.CheckLibWithHeader( "m", "math.h", "c", "lrint(3.2);" ):
337 if conf
.CheckLibWithHeader( "m", "math.h", "c", "lrintf(3.2);" ):
341 env
['HAVE_LRINT'] = HAVE_LRINT
;
342 env
['HAVE_LRINTF'] = HAVE_LRINTF
;
343 env
.Replace(CFLAGS
=oldcf
)
346 # Optional checks follow:
351 if conf
.CheckForApp( 'which pyuic4' ) and conf
.CheckForPyModule( 'dbus' ) and conf
.CheckForPyModule( 'PyQt4' ) and conf
.CheckForPyModule( 'dbus.mainloop.qt' ):
355 if conf
.CheckForApp( 'xdg-desktop-menu --help' ):
356 env
['XDG_TOOLS'] = True
359 I couldn't find the program 'xdg-desktop-menu'. Together with xdg-icon-resource
360 this is needed to add the fancy entry to your menu. But if the mixer will be
361 installed, you can start it by executing "ffado-mixer".
364 if not build_mixer
and not env
.GetOption('clean'):
366 I couldn't find all the prerequisites ('pyuic4' and the python-modules 'dbus'
367 and 'PyQt4', the packages could be named like dbus-python and PyQt) to build the
369 Therefor the qt4 mixer will not get installed.
373 # Optional pkg-config
381 name2
= pkg
.replace("+","").replace(".","").replace("-","").upper()
382 env
['%s_FLAGS' % name2
] = conf
.GetPKGFlags( pkg
, pkgs
[pkg
] )
384 if not env
['DBUS1_FLAGS'] or not env
['DBUSC1_FLAGS'] or not conf
.CheckForApp('which dbusxx-xml2cpp'):
385 env
['DBUS1_FLAGS'] = ""
386 env
['DBUSC1_FLAGS'] = ""
388 One of the dbus-headers, the dbus-c++-headers and/or the application
389 'dbusxx-xml2cpp' where not found. The dbus-server for ffado will therefore not
393 # Get the directory where dbus stores the service-files
394 env
['dbus_service_dir'] = conf
.GetPKGVariable( 'dbus-1', 'session_bus_services_dir' ).strip()
395 # this is required to indicate that the DBUS version we use has support
396 # for platform dependent threading init functions
397 # this is true for DBUS >= 0.96 or so. Since we require >= 1.0 it is
399 env
['DBUS1_FLAGS'] += " -DDBUS_HAS_THREADS_INIT_DEFAULT"
402 config_guess
= conf
.ConfigGuess()
406 if env
['DEBUG_BUILD']:
407 print "Doing a debug build"
408 env
.MergeFlags( "-Wall -g" )
410 env
.MergeFlags( "-O2" )
413 env
.MergeFlags( "-DDEBUG" )
415 env
.MergeFlags( "-DNDEBUG" )
418 print "Doing a PROFILE build"
419 env
.MergeFlags( "-Wall -g" )
422 env
.MergeFlags( "-Werror" )
425 if env
['ENABLE_ALL']:
426 env
['ENABLE_BEBOB'] = True
427 env
['ENABLE_FIREWORKS'] = True
428 env
['ENABLE_OXFORD'] = True
429 env
['ENABLE_MOTU'] = True
430 env
['ENABLE_DICE'] = True
431 env
['ENABLE_METRIC_HALO'] = True
432 env
['ENABLE_RME'] = True
433 env
['ENABLE_DIGIDESIGN'] = True
434 env
['ENABLE_BOUNCE'] = True
437 env
['BUILD_STATIC_LIB'] = False
438 if env
['BUILD_STATIC_TOOLS']:
439 print "Building static versions of the tools..."
440 env
['BUILD_STATIC_LIB'] = True
442 env
['build_base']="#/"
445 # Get the DESTDIR (if wanted) from the commandline
447 env
.destdir
= ARGUMENTS
.get( 'DESTDIR', "" )
450 # Uppercase variables are for usage in code, lowercase versions for usage in
451 # scons-files for installing.
453 env
['BINDIR'] = Template( env
['BINDIR'] ).safe_substitute( env
)
454 env
['LIBDIR'] = Template( env
['LIBDIR'] ).safe_substitute( env
)
455 env
['INCLUDEDIR'] = Template( env
['INCLUDEDIR'] ).safe_substitute( env
)
456 env
['SHAREDIR'] = Template( env
['SHAREDIR'] ).safe_substitute( env
)
457 env
['UDEVDIR'] = Template( env
['UDEVDIR'] ).safe_substitute( env
)
458 env
['prefix'] = Template( env
.destdir
+ env
['PREFIX'] ).safe_substitute( env
)
459 env
['bindir'] = Template( env
.destdir
+ env
['BINDIR'] ).safe_substitute( env
)
460 env
['libdir'] = Template( env
.destdir
+ env
['LIBDIR'] ).safe_substitute( env
)
461 env
['includedir'] = Template( env
.destdir
+ env
['INCLUDEDIR'] ).safe_substitute( env
)
462 env
['sharedir'] = Template( env
.destdir
+ env
['SHAREDIR'] ).safe_substitute( env
)
463 env
['mandir'] = Template( env
.destdir
+ env
['MANDIR'] ).safe_substitute( env
)
464 env
['pypkgdir'] = Template( env
.destdir
+ env
['PYPKGDIR'] ).safe_substitute( env
)
465 env
['udevdir'] = Template( env
.destdir
+ env
['UDEVDIR'] ).safe_substitute( env
)
466 env
['PYPKGDIR'] = Template( env
['PYPKGDIR'] ).safe_substitute( env
)
468 env
.Command( target
=env
['sharedir'], source
="", action
=Mkdir( env
['sharedir'] ) )
470 env
.Alias( "install", env
['libdir'] )
471 env
.Alias( "install", env
['includedir'] )
472 env
.Alias( "install", env
['sharedir'] )
473 env
.Alias( "install", env
['bindir'] )
474 env
.Alias( "install", env
['mandir'] )
476 env
.Alias( "install", env
['pypkgdir'] )
479 # shamelessly copied from the Ardour scons file
485 # guess at the platform, used to define compiler flags
491 config
= config_guess
.split ("-")
495 #=== Begin Revised CXXFLAGS =========================================
497 """Run a command without running a shell, return cmd's stdout
499 p
= Popen(cmd
, stdout
=PIPE
)
500 return p
.communicate()[0]
503 """generator which reads lines from Linux /proc/cpuinfo and splits them
504 into key:value tokens and yields (key, value) tuple.
506 f
= open('/proc/cpuinfo', 'r')
510 k
,v
= line
.split(':')
511 yield (k
.strip(), v
.strip())
515 class CpuInfo (object):
516 """Collects information about the CPU, mainly from /proc/cpuinfo
519 self
.sysname
, self
.hostname
, self
.release
, self
.version
, self
.machine
= os
.uname()
520 # general CPU architecture
521 self
.is_x86
= self
.machine
in ('i686', 'x86_64') or \
522 re
.match("i[3-5]86", self
.machine
) or False
523 self
.is_powerpc
= self
.machine
in ('ppc64', 'ppc', 'powerpc', 'powerpc64')
524 #!!! probably not comprehensive
525 self
.is_mips
= self
.machine
== 'mips'
526 #!!! not a comprehensive list. uname -m on one android phone reports 'armv71'
527 # I have no other arm devices I can check
528 self
.is_arm
= self
.machine
in ('armv71', )
533 elif self
.is_powerpc
:
538 # 64-bit (x86_64/AMD64/Intel64)
539 # Long Mode (x86-64: amd64, also known as Intel 64, i.e. 64-bit capable)
540 self
.is_64bit
= (self
.is_x86
and 'lm' in self
.x86_flags
) or \
541 (self
.is_powerpc
and '970' in self
.ppc_type
)
543 # Hardware virtualization capable: vmx (Intel), svm (AMD)
544 self
.has_hwvirt
= self
.is_x86
and (
545 (self
.is_amd
and 'svm' in self
.x86_flags
) or
546 (self
.is_intel
and 'vmx' in self
.x86_flags
))
548 # Physical Address Extensions (support for more than 4GB of RAM)
549 self
.has_pae
= self
.is_x86
and 'pae' in self
.x86_flags
552 def cpu_info_x86(self
):
553 "parse /proc/cpuinfo for x86 kernels"
554 for k
,v
in cpuinfo_kv():
557 if self
.cpu_count
> 1:
558 # assume all CPUs are identical features, no need to
561 elif k
== 'vendor_id': # AuthenticAMD, GenuineIntel
563 self
.is_amd
= v
== 'AuthenticAMD'
564 self
.is_intel
= v
== 'GenuineIntel'
566 self
.x86_flags
= v
.split()
567 elif k
== 'model name':
569 elif k
== 'cpu family':
574 def cpu_info_ppc(self
):
575 "parse /proc/cpuinfo for PowerPC kernels"
576 # http://en.wikipedia.org/wiki/List_of_PowerPC_processors
578 # PowerPC 740 and 750, 233-366 MHz
579 # 745/755, 300–466 MHz
582 # 7400/7410 350 - 550 MHz, uses AltiVec, a SIMD extension of the original PPC specs
583 # 7450 micro-architecture family up to 1.5 GHz and 256 kB on-chip L2 cache and improved Altivec
584 # 7447/7457 micro-architecture family up to 1.8 GHz with 512 kB on-chip L2 cache
585 # 7448 micro-architecture family (1.5 GHz) in 90 nm with 1MB L2 cache and slightly
586 # improved AltiVec (out of order instructions).
587 # 8640/8641/8640D/8641D with one or two e600 (Formerly known as G4) cores, 1MB L2 cache
590 # 970 (2003), 64-bit, derived from POWER4, enhanced with VMX, 512 kB L2 cache, 1.4 – 2 GHz
591 # 970FX (2004), manufactured at 90 nm, 1.8 - 2.7 GHz
592 # 970GX (2006), manufactured at 90 nm, 1MB L2 cache/core, 1.2 - 2.5 GHz
593 # 970MP (2005), dual core, 1 MB L2 cache/core, 1.6 - 2.5 GHz
594 for k
,v
in cpuinfo_kv():
598 self
.is_altivec_supported
= 'altivec' in v
599 ppc_type
, x
= v
.split(',')
600 self
.ppc_type
= ppc_type
.strip()
601 # older kernels might not have a 'processor' line
602 if self
.cpu_count
== 0:
606 def cpu_info_mips(self
):
607 "parse /proc/cpuinfo for MIPS kernels"
608 for k
,v
in cpuinfo_kv():
611 elif k
== 'cpu model':
612 self
.mips_cpu_model
= v
615 def is_userspace_32bit(cpuinfo
):
616 """Even if `uname -m` reports a 64-bit architecture, userspace could still
617 be 32-bit, such as Debian on powerpc64. This function tries to figure out
618 if userspace is 32-bit, i.e. we might need to pass '-m32' or '-m64' to gcc.
620 if not cpuinfo
.is_64bit
:
622 # note that having a 64-bit CPU means nothing for these purposes. You could
623 # run a completely 32-bit system on a 64-bit capable CPU.
625 # Debian ppc64 returns machine 'ppc64', but userspace might be 32-bit
626 # We'll make an educated guess by examining a known executable
628 if os
.path
.isfile(exe
):
629 #print 'Found %s' % exe
630 if os
.path
.islink(exe
):
631 real_exe
= os
.path
.join(os
.path
.dirname(exe
), os
.readlink(exe
))
632 #print '%s is a symlink to %s' % (exe, real_exe)
635 # presumably if a person is running this script, they should have
636 # a gcc toolchain installed...
637 x
= outputof('objdump', '-Wi', real_exe
)
638 # should emit a line that looks like this:
639 # /bin/mount: file format elf32-i386
641 # /bin/mount: file format elf64-x86-64
643 # /bin/mount: file format elf32-powerpc
644 for line
in x
.split('\n'):
646 if line
.startswith(real_exe
):
647 x
, fmt
= line
.rsplit(None, 1)
648 answer
= 'elf32' in fmt
651 print '!!! Not found %s' % exe
655 def cc_flags_x86(cpuinfo
, enable_optimizations
):
656 """add certain gcc -m flags based on CPU features
658 # See http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/i386-and-x86_002d64-Options.html
660 if cpuinfo
.machine
== 'i586':
661 cc_opts
.append('-march=i586')
662 elif cpuinfo
.machine
== 'i686':
663 cc_opts
.append('-march=i686')
665 if 'mmx' in cpuinfo
.x86_flags
:
666 cc_opts
.append('-mmmx')
668 # map from proc/cpuinfo flags to gcc options
670 ('sse', ('-mfpmath=sse', '-msse')),
672 ('ssse3', '-mssse3'),
674 ('sse4_1', '-msse4.1'),
675 ('sse4_2', '-msse4.2'),
676 ('sse4a', '-msse4a'),
677 ('3dnow', '-m3dnow'),
679 if enable_optimizations
:
680 for flag
, gccopt
in opt_flags
:
681 if flag
in cpuinfo
.x86_flags
:
682 if isinstance(gccopt
, (tuple, list)):
683 cc_opts
.extend(gccopt
)
685 cc_opts
.append(gccopt
)
689 def cc_flags_powerpc(cpuinfo
, enable_optimizations
):
690 """add certain gcc -m flags based on CPU model
693 if cpuinfo
.is_altivec_supported
:
694 cc_opts
.append ('-maltivec')
695 cc_opts
.append ('-mabi=altivec')
697 if re
.match('74[0145][0578]A?', cpuinfo
.ppc_type
) is not None:
698 cc_opts
.append ('-mcpu=7400')
699 cc_opts
.append ('-mtune=7400')
700 elif re
.match('750', cpuinfo
.ppc_type
) is not None:
701 cc_opts
.append ('-mcpu=750')
702 cc_opts
.append ('-mtune=750')
703 elif re
.match('PPC970', cpuinfo
.ppc_type
) is not None:
704 cc_opts
.append ('-mcpu=970')
705 cc_opts
.append ('-mtune=970')
706 elif re
.match('Cell Broadband Engine', cpuinfo
.ppc_type
) is not None:
707 cc_opts
.append('-mcpu=cell')
708 cc_opts
.append('-mtune=cell')
710 #=== End Revised CXXFLAGS =========================================
713 if env
['DIST_TARGET'] == 'auto':
714 if re
.search ("x86_64", config
[config_cpu
]) is not None:
715 env
['DIST_TARGET'] = 'x86_64'
716 elif re
.search("i[0-5]86", config
[config_cpu
]) is not None:
717 env
['DIST_TARGET'] = 'i386'
718 elif re
.search("i686", config
[config_cpu
]) is not None:
719 env
['DIST_TARGET'] = 'i686'
720 elif re
.search("powerpc64", config
[config_cpu
]) is not None:
721 env
['DIST_TARGET'] = 'powerpc64'
722 elif re
.search("powerpc", config
[config_cpu
]) is not None:
723 env
['DIST_TARGET'] = 'powerpc'
725 env
['DIST_TARGET'] = config
[config_cpu
]
726 print "Detected DIST_TARGET = " + env
['DIST_TARGET']
728 #=== Begin Revised CXXFLAGS =========================================
729 # comment on DIST_TARGET up top implies it can be used for cross-compiling
730 # but that's not true because even if it is not 'auto' the original
731 # script still reads /proc/cpuinfo to determine gcc arch flags.
732 # This script does the same as the original. Needs to be fixed someday.
735 opt_flags
.extend(cc_flags_x86(cpuinfo
, env
['ENABLE_OPTIMIZATIONS']))
736 if cpuinfo
.is_powerpc
:
737 opt_flags
.extend(cc_flags_powerpc(cpuinfo
, env
['ENABLE_OPTIMIZATIONS']))
738 if '-msse' in opt_flags
:
740 if '-msse2' in opt_flags
:
743 m32
= is_userspace_32bit(cpuinfo
)
744 print 'User space is %s' % (m32
and '32-bit' or '64-bit')
745 if cpuinfo
.is_powerpc
:
747 print "Doing a 32-bit PowerPC build for %s CPU" % cpuinfo
.ppc_type
748 machineflags
= { 'CXXFLAGS' : ['-m32'] }
750 print "Doing a 64-bit PowerPC build for %s CPU" % cpuinfo
.ppc_type
751 machineflags
= { 'CXXFLAGS' : ['-m64'] }
752 env
.MergeFlags( machineflags
)
755 print "Doing a 32-bit %s build for %s" % (cpuinfo
.machine
, cpuinfo
.model_name
)
756 machineflags
= { 'CXXFLAGS' : ['-m32'] }
758 print "Doing a 64-bit %s build for %s" % (cpuinfo
.machine
, cpuinfo
.model_name
)
759 machineflags
= { 'CXXFLAGS' : ['-m64'] }
761 env
.MergeFlags( machineflags
)
762 #=== End Revised CXXFLAGS =========================================
765 if needs_fPIC
or ( env
.has_key('COMPILE_FLAGS') and '-fPIC' in env
['COMPILE_FLAGS'] ):
766 env
.MergeFlags( "-fPIC" )
768 # end of processor-specific section
769 if env
['ENABLE_OPTIMIZATIONS']:
770 opt_flags
.extend (["-fomit-frame-pointer","-ffast-math","-funroll-loops"])
771 env
.MergeFlags( opt_flags
)
772 print "Doing an optimized build..."
774 env
['REVISION'] = os
.popen('svnversion .').read()[:-1]
775 # This may be as simple as '89' or as complex as '4123:4184M'.
776 # We'll just use the last bit.
777 env
['REVISION'] = env
['REVISION'].split(':')[-1]
779 # try to circumvent localized versions
780 if len(env
['REVISION']) >= 5 and env
['REVISION'][0:6] == 'export':
783 # avoid the 1.999.41- type of version for exported versions
784 if env
['REVISION'] != '':
785 env
['REVISIONSTRING'] = '-' + env
['REVISION']
787 env
['REVISIONSTRING'] = ''
789 env
['FFADO_API_VERSION'] = FFADO_API_VERSION
791 env
['PACKAGE'] = "libffado"
792 env
['VERSION'] = FFADO_VERSION
793 env
['LIBVERSION'] = "1.0.0"
795 env
['CONFIGDIR'] = "~/.ffado"
796 env
['CACHEDIR'] = "~/.ffado"
798 env
['USER_CONFIG_FILE'] = env
['CONFIGDIR'] + "/configuration"
799 env
['SYSTEM_CONFIG_FILE'] = env
['SHAREDIR'] + "/configuration"
801 env
['REGISTRATION_URL'] = "http://ffado.org/deviceregistration/register.php?action=register"
804 # To have the top_srcdir as the doxygen-script is used from auto*
806 env
['top_srcdir'] = env
.Dir( "." ).abspath
811 env
.ScanReplace( "config.h.in" )
812 env
.ScanReplace( "config_debug.h.in" )
813 env
.ScanReplace( "version.h.in" )
815 # ensure that the config.h is updated
816 env
.Depends( "config.h", "SConstruct" )
817 env
.Depends( "config.h", 'cache/options.cache' )
819 # update version.h whenever the version or SVN revision changes
820 env
.Depends( "version.h", env
.Value(env
['REVISION']))
821 env
.Depends( "version.h", env
.Value(env
['VERSION']))
823 env
.Depends( "libffado.pc", "SConstruct" )
824 pkgconfig
= env
.ScanReplace( "libffado.pc.in" )
825 env
.Install( env
['libdir'] + '/pkgconfig', pkgconfig
)
827 env
.Install( env
['sharedir'], 'configuration' )
829 subdirs
=['src','libffado','support','doc']
830 if env
['BUILD_TESTS']:
831 subdirs
.append('tests')
833 env
.SConscript( dirs
=subdirs
, exports
="env" )
835 if 'debian' in COMMAND_LINE_TARGETS
:
836 env
.SConscript("deb/SConscript", exports
="env")
838 # By default only src is built but all is cleaned
839 if not env
.GetOption('clean'):
842 if env
['BUILD_TESTS']:
846 # Deal with the DESTDIR vs. xdg-tools conflict (which is basicely that the
847 # xdg-tools can't deal with DESTDIR, so the packagers have to deal with this
850 if len(env
.destdir
) > 0:
851 if not len( ARGUMENTS
.get( "WILL_DEAL_WITH_XDG_MYSELF", "" ) ) > 0:
854 You are using the (packagers) option DESTDIR to install this package to a
855 different place than the real prefix. As the xdg-tools can't cope with
856 that, the .desktop-files are not installed by this build, you have to
857 deal with them your own.
858 (And you have to look into the SConstruct to learn how to disable this
863 def CleanAction( action
):
864 if env
.GetOption( "clean" ):
865 env
.Execute( action
)
867 if env
.has_key( 'XDG_TOOLS' ) and env
.has_key( 'PYUIC4' ):
868 if not env
.GetOption("clean"):
872 mixerdesktopaction
= env
.Action( "-xdg-desktop-menu %s support/xdg/ffado.org-ffadomixer.desktop" % action
)
873 mixericonaction
= env
.Action( "-xdg-icon-resource %s --size 64 --novendor --context apps support/xdg/hi64-apps-ffado.png ffado" % action
)
874 env
.Command( "__xdgstuff1", None, mixerdesktopaction
)
875 env
.Command( "__xdgstuff2", None, mixericonaction
)
876 env
.Alias( "install", ["__xdgstuff1", "__xdgstuff2" ] )
877 CleanAction( mixerdesktopaction
)
878 CleanAction( mixericonaction
)
881 # Create a tags-file for easier emacs/vim-source-browsing
882 # I don't know if the dependency is right...
884 findcommand
= "find . \( -path \"*.h\" -o -path \"*.cpp\" -o -path \"*.c\" \) \! -path \"*.svn*\" \! -path \"./doc*\" \! -path \"./cache*\""
885 env
.Command( "tags", "", findcommand
+ " |xargs ctags" )
886 env
.Command( "TAGS", "", findcommand
+ " |xargs etags" )
887 env
.AlwaysBuild( "tags", "TAGS" )
888 if 'NoCache' in dir(env
):
889 env
.NoCache( "tags", "TAGS" )
891 # Another convinience target
892 if env
.GetOption( "clean" ):
893 env
.Execute( "rm cache/objects -Rf" )