Spaces:
Runtime error
Runtime error
| import os.path, copy, sys | |
| def checkSymbol(conf, header, library=None, symbol=None, autoAdd=True, critical=False, pkgName=None): | |
| """ Check for symbol in library, optionally look only for header. | |
| @param conf: Configure instance. | |
| @param header: The header file where the symbol is declared. | |
| @param library: The library in which the symbol exists, if None it is taken to be the standard C library. | |
| @param symbol: The symbol to look for, if None only the header will be looked up. | |
| @param autoAdd: Automatically link with this library if check is positive. | |
| @param critical: Raise on error? | |
| @param pkgName: Optional name of pkg-config entry for library, to determine build parameters. | |
| @return: True/False | |
| """ | |
| origEnv = conf.env.Copy() # Copy unmodified environment so we can restore it upon error | |
| env = conf.env | |
| if library is None: | |
| library = "c" # Standard library | |
| autoAdd = False | |
| if pkgName is not None: | |
| origLibs = copy.copy(env.get("LIBS", None)) | |
| try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName) | |
| except: pass | |
| else: | |
| # I see no other way of checking that the parsing succeeded, if it did add no more linking parameters | |
| if env.get("LIBS", None) != origLibs: | |
| autoAdd = False | |
| try: | |
| if not conf.CheckCHeader(header, include_quotes="<>"): | |
| raise ConfigurationError("missing header %s" % header) | |
| if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoAdd): | |
| raise ConfigurationError("missing symbol %s in library %s" % (symbol, library)) | |
| except ConfigurationError: | |
| conf.env = origEnv | |
| if not critical: | |
| return False | |
| raise | |
| return True | |
| import SCons.Errors | |
| # Import common variables | |
| # Could use '#' to refer to top-level SConstruct directory, but looks like env.SConsignFile doesn't interpret this at least :( | |
| sconsDir = os.path.abspath(os.path.join("build", "scons")) | |
| try: | |
| Import("Platform", "Posix", "ConfigurationError", "ApiVer") | |
| except SCons.Errors.UserError: | |
| # The common objects must be exported first | |
| SConscript(os.path.join(sconsDir, "SConscript_common")) | |
| Import("Platform", "Posix", "ConfigurationError", "ApiVer") | |
| Import("env") | |
| # This will be manipulated | |
| env = env.Copy() | |
| # We operate with a set of needed libraries and optional libraries, the latter stemming from host API implementations. | |
| # For libraries of both types we record a set of values that is used to look for the library in question, during | |
| # configuration. If the corresponding library for a host API implementation isn't found, the implementation is left out. | |
| neededLibs = [] | |
| optionalImpls = {} | |
| if Platform in Posix: | |
| env.Append(CPPPATH=os.path.join("os", "unix")) | |
| neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")] | |
| if env["useALSA"]: | |
| optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open") | |
| if env["useJACK"]: | |
| optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new") | |
| if env["useOSS"]: | |
| # TODO: It looks like the prefix for soundcard.h depends on the platform | |
| optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None) | |
| if Platform == 'netbsd': | |
| optionalImpls["OSS"] = ("ossaudio", "sys/soundcard.h", "_oss_ioctl") | |
| if env["useASIHPI"]: | |
| optionalImpls["ASIHPI"] = ("hpi", "asihpi/hpi.h", "HPI_SubSysCreate") | |
| if env["useCOREAUDIO"]: | |
| optionalImpls["COREAUDIO"] = ("CoreAudio", "CoreAudio/CoreAudio.h", None) | |
| else: | |
| raise ConfigurationError("unknown platform %s" % Platform) | |
| if Platform == "darwin": | |
| env.Append(LINKFLAGS="-framework CoreFoundation -framework CoreServices -framework CoreAudio -framework AudioToolBox -framework AudioUnit") | |
| elif Platform == "cygwin": | |
| env.Append(LIBS=["winmm"]) | |
| elif Platform == "irix": | |
| neededLibs += [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")] | |
| env.Append(CPPDEFINES=["PA_USE_SGI"]) | |
| def CheckCTypeSize(context, tp): | |
| """ Check size of C type. | |
| @param context: A configuration context. | |
| @param tp: The type to check. | |
| @return: Size of type, in bytes. | |
| """ | |
| context.Message("Checking the size of C type %s..." % tp) | |
| ret = context.TryRun(""" | |
| #include <stdio.h> | |
| int main() { | |
| printf("%%d", sizeof(%s)); | |
| return 0; | |
| } | |
| """ % tp, ".c") | |
| if not ret[0]: | |
| context.Result(" Couldn't obtain size of type %s!" % tp) | |
| return None | |
| assert ret[1] | |
| sz = int(ret[1]) | |
| context.Result("%d" % sz) | |
| return sz | |
| """ | |
| if sys.byteorder == "little": | |
| env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"]) | |
| elif sys.byteorder == "big": | |
| env.Append(CPPDEFINES=["PA_BIG_ENDIAN"]) | |
| else: | |
| raise ConfigurationError("unknown byte order: %s" % sys.byteorder) | |
| """ | |
| if env["enableDebugOutput"]: | |
| env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"]) | |
| # Start configuration | |
| # Use an absolute path for conf_dir, otherwise it gets created both relative to current directory and build directory | |
| conf = env.Configure(log_file=os.path.join(sconsDir, "sconf.log"), custom_tests={"CheckCTypeSize": CheckCTypeSize}, | |
| conf_dir=os.path.join(sconsDir, ".sconf_temp")) | |
| conf.env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")]) | |
| conf.env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")]) | |
| conf.env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")]) | |
| if checkSymbol(conf, "time.h", "rt", "clock_gettime"): | |
| conf.env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"]) | |
| if checkSymbol(conf, "time.h", symbol="nanosleep"): | |
| conf.env.Append(CPPDEFINES=["HAVE_NANOSLEEP"]) | |
| if conf.CheckCHeader("sys/soundcard.h"): | |
| conf.env.Append(CPPDEFINES=["HAVE_SYS_SOUNDCARD_H"]) | |
| if conf.CheckCHeader("linux/soundcard.h"): | |
| conf.env.Append(CPPDEFINES=["HAVE_LINUX_SOUNDCARD_H"]) | |
| if conf.CheckCHeader("machine/soundcard.h"): | |
| conf.env.Append(CPPDEFINES=["HAVE_MACHINE_SOUNDCARD_H"]) | |
| # Look for needed libraries and link with them | |
| for lib, hdr, sym in neededLibs: | |
| checkSymbol(conf, hdr, lib, sym, critical=True) | |
| # Look for host API libraries, if a library isn't found disable corresponding host API implementation. | |
| for name, val in optionalImpls.items(): | |
| lib, hdr, sym = val | |
| if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()): | |
| conf.env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()]) | |
| else: | |
| del optionalImpls[name] | |
| # Configuration finished | |
| env = conf.Finish() | |
| # PA infrastructure | |
| CommonSources = [os.path.join("common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \ | |
| pa_process.c pa_stream.c pa_trace.c pa_debugprint.c pa_ringbuffer.c".split()] | |
| CommonSources.append(os.path.join("hostapi", "skeleton", "pa_hostapi_skeleton.c")) | |
| # Host APIs implementations | |
| ImplSources = [] | |
| if Platform in Posix: | |
| ImplSources += [os.path.join("os", "unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()] | |
| if "ALSA" in optionalImpls: | |
| ImplSources.append(os.path.join("hostapi", "alsa", "pa_linux_alsa.c")) | |
| if "JACK" in optionalImpls: | |
| ImplSources.append(os.path.join("hostapi", "jack", "pa_jack.c")) | |
| if "OSS" in optionalImpls: | |
| ImplSources.append(os.path.join("hostapi", "oss", "pa_unix_oss.c")) | |
| if "ASIHPI" in optionalImpls: | |
| ImplSources.append(os.path.join("hostapi", "asihpi", "pa_linux_asihpi.c")) | |
| if "COREAUDIO" in optionalImpls: | |
| ImplSources.append([os.path.join("hostapi", "coreaudio", f) for f in """ | |
| pa_mac_core.c pa_mac_core_blocking.c pa_mac_core_utilities.c | |
| """.split()]) | |
| sources = CommonSources + ImplSources | |
| sharedLibEnv = env.Copy() | |
| if Platform in Posix: | |
| # Add soname to library, this is so a reference is made to the versioned library in programs linking against libportaudio.so | |
| if Platform != 'darwin': | |
| sharedLibEnv.AppendUnique(SHLINKFLAGS="-Wl,-soname=libportaudio.so.%d" % int(ApiVer.split(".")[0])) | |
| sharedLib = sharedLibEnv.SharedLibrary(target="portaudio", source=sources) | |
| staticLib = env.StaticLibrary(target="portaudio", source=sources) | |
| if Platform in Posix: | |
| prefix = env["prefix"] | |
| includeDir = os.path.join(prefix, "include") | |
| libDir = os.path.join(prefix, "lib") | |
| testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \ | |
| "patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \ | |
| "patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \ | |
| "patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \ | |
| "patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", "patest_toomanysines", \ | |
| "patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat", \ | |
| "patest_sine_channelmaps",] | |
| # The test directory ("bin") should be in the top-level PA directory | |
| tests = [env.Program(target=os.path.join("#", "bin", name), source=[os.path.join("#", "test", name + ".c"), | |
| staticLib]) for name in testNames] | |
| # Detect host APIs | |
| hostApis = [] | |
| for cppdef in env["CPPDEFINES"]: | |
| if cppdef.startswith("PA_USE_"): | |
| hostApis.append(cppdef[7:-2]) | |
| Return("sources", "sharedLib", "staticLib", "tests", "env", "hostApis") | |