cannam@89
|
1 import os.path, copy, sys
|
cannam@89
|
2
|
cannam@89
|
3 def checkSymbol(conf, header, library=None, symbol=None, autoAdd=True, critical=False, pkgName=None):
|
cannam@89
|
4 """ Check for symbol in library, optionally look only for header.
|
cannam@89
|
5 @param conf: Configure instance.
|
cannam@89
|
6 @param header: The header file where the symbol is declared.
|
cannam@89
|
7 @param library: The library in which the symbol exists, if None it is taken to be the standard C library.
|
cannam@89
|
8 @param symbol: The symbol to look for, if None only the header will be looked up.
|
cannam@89
|
9 @param autoAdd: Automatically link with this library if check is positive.
|
cannam@89
|
10 @param critical: Raise on error?
|
cannam@89
|
11 @param pkgName: Optional name of pkg-config entry for library, to determine build parameters.
|
cannam@89
|
12 @return: True/False
|
cannam@89
|
13 """
|
cannam@89
|
14 origEnv = conf.env.Copy() # Copy unmodified environment so we can restore it upon error
|
cannam@89
|
15 env = conf.env
|
cannam@89
|
16 if library is None:
|
cannam@89
|
17 library = "c" # Standard library
|
cannam@89
|
18 autoAdd = False
|
cannam@89
|
19
|
cannam@89
|
20 if pkgName is not None:
|
cannam@89
|
21 origLibs = copy.copy(env.get("LIBS", None))
|
cannam@89
|
22
|
cannam@89
|
23 try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName)
|
cannam@89
|
24 except: pass
|
cannam@89
|
25 else:
|
cannam@89
|
26 # I see no other way of checking that the parsing succeeded, if it did add no more linking parameters
|
cannam@89
|
27 if env.get("LIBS", None) != origLibs:
|
cannam@89
|
28 autoAdd = False
|
cannam@89
|
29
|
cannam@89
|
30 try:
|
cannam@89
|
31 if not conf.CheckCHeader(header, include_quotes="<>"):
|
cannam@89
|
32 raise ConfigurationError("missing header %s" % header)
|
cannam@89
|
33 if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoAdd):
|
cannam@89
|
34 raise ConfigurationError("missing symbol %s in library %s" % (symbol, library))
|
cannam@89
|
35 except ConfigurationError:
|
cannam@89
|
36 conf.env = origEnv
|
cannam@89
|
37 if not critical:
|
cannam@89
|
38 return False
|
cannam@89
|
39 raise
|
cannam@89
|
40
|
cannam@89
|
41 return True
|
cannam@89
|
42
|
cannam@89
|
43 import SCons.Errors
|
cannam@89
|
44
|
cannam@89
|
45 # Import common variables
|
cannam@89
|
46
|
cannam@89
|
47 # Could use '#' to refer to top-level SConstruct directory, but looks like env.SConsignFile doesn't interpret this at least :(
|
cannam@89
|
48 sconsDir = os.path.abspath(os.path.join("build", "scons"))
|
cannam@89
|
49
|
cannam@89
|
50 try:
|
cannam@89
|
51 Import("Platform", "Posix", "ConfigurationError", "ApiVer")
|
cannam@89
|
52 except SCons.Errors.UserError:
|
cannam@89
|
53 # The common objects must be exported first
|
cannam@89
|
54 SConscript(os.path.join(sconsDir, "SConscript_common"))
|
cannam@89
|
55 Import("Platform", "Posix", "ConfigurationError", "ApiVer")
|
cannam@89
|
56
|
cannam@89
|
57 Import("env")
|
cannam@89
|
58
|
cannam@89
|
59 # This will be manipulated
|
cannam@89
|
60 env = env.Copy()
|
cannam@89
|
61
|
cannam@89
|
62 # We operate with a set of needed libraries and optional libraries, the latter stemming from host API implementations.
|
cannam@89
|
63 # For libraries of both types we record a set of values that is used to look for the library in question, during
|
cannam@89
|
64 # configuration. If the corresponding library for a host API implementation isn't found, the implementation is left out.
|
cannam@89
|
65 neededLibs = []
|
cannam@89
|
66 optionalImpls = {}
|
cannam@89
|
67 if Platform in Posix:
|
cannam@89
|
68 env.Append(CPPPATH=os.path.join("os", "unix"))
|
cannam@89
|
69 neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")]
|
cannam@89
|
70 if env["useALSA"]:
|
cannam@89
|
71 optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open")
|
cannam@89
|
72 if env["useJACK"]:
|
cannam@89
|
73 optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new")
|
cannam@89
|
74 if env["useOSS"]:
|
cannam@89
|
75 # TODO: It looks like the prefix for soundcard.h depends on the platform
|
cannam@89
|
76 optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None)
|
cannam@89
|
77 if Platform == 'netbsd':
|
cannam@89
|
78 optionalImpls["OSS"] = ("ossaudio", "sys/soundcard.h", "_oss_ioctl")
|
cannam@89
|
79 if env["useASIHPI"]:
|
cannam@89
|
80 optionalImpls["ASIHPI"] = ("hpi", "asihpi/hpi.h", "HPI_SubSysCreate")
|
cannam@89
|
81 if env["useCOREAUDIO"]:
|
cannam@89
|
82 optionalImpls["COREAUDIO"] = ("CoreAudio", "CoreAudio/CoreAudio.h", None)
|
cannam@89
|
83 else:
|
cannam@89
|
84 raise ConfigurationError("unknown platform %s" % Platform)
|
cannam@89
|
85
|
cannam@89
|
86 if Platform == "darwin":
|
cannam@89
|
87 env.Append(LINKFLAGS="-framework CoreFoundation -framework CoreServices -framework CoreAudio -framework AudioToolBox -framework AudioUnit")
|
cannam@89
|
88 elif Platform == "cygwin":
|
cannam@89
|
89 env.Append(LIBS=["winmm"])
|
cannam@89
|
90 elif Platform == "irix":
|
cannam@89
|
91 neededLibs += [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")]
|
cannam@89
|
92 env.Append(CPPDEFINES=["PA_USE_SGI"])
|
cannam@89
|
93
|
cannam@89
|
94 def CheckCTypeSize(context, tp):
|
cannam@89
|
95 """ Check size of C type.
|
cannam@89
|
96 @param context: A configuration context.
|
cannam@89
|
97 @param tp: The type to check.
|
cannam@89
|
98 @return: Size of type, in bytes.
|
cannam@89
|
99 """
|
cannam@89
|
100 context.Message("Checking the size of C type %s..." % tp)
|
cannam@89
|
101 ret = context.TryRun("""
|
cannam@89
|
102 #include <stdio.h>
|
cannam@89
|
103
|
cannam@89
|
104 int main() {
|
cannam@89
|
105 printf("%%d", sizeof(%s));
|
cannam@89
|
106 return 0;
|
cannam@89
|
107 }
|
cannam@89
|
108 """ % tp, ".c")
|
cannam@89
|
109 if not ret[0]:
|
cannam@89
|
110 context.Result(" Couldn't obtain size of type %s!" % tp)
|
cannam@89
|
111 return None
|
cannam@89
|
112
|
cannam@89
|
113 assert ret[1]
|
cannam@89
|
114 sz = int(ret[1])
|
cannam@89
|
115 context.Result("%d" % sz)
|
cannam@89
|
116 return sz
|
cannam@89
|
117
|
cannam@89
|
118 """
|
cannam@89
|
119 if sys.byteorder == "little":
|
cannam@89
|
120 env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"])
|
cannam@89
|
121 elif sys.byteorder == "big":
|
cannam@89
|
122 env.Append(CPPDEFINES=["PA_BIG_ENDIAN"])
|
cannam@89
|
123 else:
|
cannam@89
|
124 raise ConfigurationError("unknown byte order: %s" % sys.byteorder)
|
cannam@89
|
125 """
|
cannam@89
|
126 if env["enableDebugOutput"]:
|
cannam@89
|
127 env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"])
|
cannam@89
|
128
|
cannam@89
|
129 # Start configuration
|
cannam@89
|
130
|
cannam@89
|
131 # Use an absolute path for conf_dir, otherwise it gets created both relative to current directory and build directory
|
cannam@89
|
132 conf = env.Configure(log_file=os.path.join(sconsDir, "sconf.log"), custom_tests={"CheckCTypeSize": CheckCTypeSize},
|
cannam@89
|
133 conf_dir=os.path.join(sconsDir, ".sconf_temp"))
|
cannam@89
|
134 conf.env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")])
|
cannam@89
|
135 conf.env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")])
|
cannam@89
|
136 conf.env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")])
|
cannam@89
|
137 if checkSymbol(conf, "time.h", "rt", "clock_gettime"):
|
cannam@89
|
138 conf.env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"])
|
cannam@89
|
139 if checkSymbol(conf, "time.h", symbol="nanosleep"):
|
cannam@89
|
140 conf.env.Append(CPPDEFINES=["HAVE_NANOSLEEP"])
|
cannam@89
|
141 if conf.CheckCHeader("sys/soundcard.h"):
|
cannam@89
|
142 conf.env.Append(CPPDEFINES=["HAVE_SYS_SOUNDCARD_H"])
|
cannam@89
|
143 if conf.CheckCHeader("linux/soundcard.h"):
|
cannam@89
|
144 conf.env.Append(CPPDEFINES=["HAVE_LINUX_SOUNDCARD_H"])
|
cannam@89
|
145 if conf.CheckCHeader("machine/soundcard.h"):
|
cannam@89
|
146 conf.env.Append(CPPDEFINES=["HAVE_MACHINE_SOUNDCARD_H"])
|
cannam@89
|
147
|
cannam@89
|
148 # Look for needed libraries and link with them
|
cannam@89
|
149 for lib, hdr, sym in neededLibs:
|
cannam@89
|
150 checkSymbol(conf, hdr, lib, sym, critical=True)
|
cannam@89
|
151 # Look for host API libraries, if a library isn't found disable corresponding host API implementation.
|
cannam@89
|
152 for name, val in optionalImpls.items():
|
cannam@89
|
153 lib, hdr, sym = val
|
cannam@89
|
154 if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()):
|
cannam@89
|
155 conf.env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()])
|
cannam@89
|
156 else:
|
cannam@89
|
157 del optionalImpls[name]
|
cannam@89
|
158
|
cannam@89
|
159 # Configuration finished
|
cannam@89
|
160 env = conf.Finish()
|
cannam@89
|
161
|
cannam@89
|
162 # PA infrastructure
|
cannam@89
|
163 CommonSources = [os.path.join("common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \
|
cannam@89
|
164 pa_process.c pa_stream.c pa_trace.c pa_debugprint.c pa_ringbuffer.c".split()]
|
cannam@89
|
165 CommonSources.append(os.path.join("hostapi", "skeleton", "pa_hostapi_skeleton.c"))
|
cannam@89
|
166
|
cannam@89
|
167 # Host APIs implementations
|
cannam@89
|
168 ImplSources = []
|
cannam@89
|
169 if Platform in Posix:
|
cannam@89
|
170 ImplSources += [os.path.join("os", "unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()]
|
cannam@89
|
171
|
cannam@89
|
172 if "ALSA" in optionalImpls:
|
cannam@89
|
173 ImplSources.append(os.path.join("hostapi", "alsa", "pa_linux_alsa.c"))
|
cannam@89
|
174 if "JACK" in optionalImpls:
|
cannam@89
|
175 ImplSources.append(os.path.join("hostapi", "jack", "pa_jack.c"))
|
cannam@89
|
176 if "OSS" in optionalImpls:
|
cannam@89
|
177 ImplSources.append(os.path.join("hostapi", "oss", "pa_unix_oss.c"))
|
cannam@89
|
178 if "ASIHPI" in optionalImpls:
|
cannam@89
|
179 ImplSources.append(os.path.join("hostapi", "asihpi", "pa_linux_asihpi.c"))
|
cannam@89
|
180 if "COREAUDIO" in optionalImpls:
|
cannam@89
|
181 ImplSources.append([os.path.join("hostapi", "coreaudio", f) for f in """
|
cannam@89
|
182 pa_mac_core.c pa_mac_core_blocking.c pa_mac_core_utilities.c
|
cannam@89
|
183 """.split()])
|
cannam@89
|
184
|
cannam@89
|
185
|
cannam@89
|
186 sources = CommonSources + ImplSources
|
cannam@89
|
187
|
cannam@89
|
188 sharedLibEnv = env.Copy()
|
cannam@89
|
189 if Platform in Posix:
|
cannam@89
|
190 # Add soname to library, this is so a reference is made to the versioned library in programs linking against libportaudio.so
|
cannam@89
|
191 if Platform != 'darwin':
|
cannam@89
|
192 sharedLibEnv.AppendUnique(SHLINKFLAGS="-Wl,-soname=libportaudio.so.%d" % int(ApiVer.split(".")[0]))
|
cannam@89
|
193 sharedLib = sharedLibEnv.SharedLibrary(target="portaudio", source=sources)
|
cannam@89
|
194
|
cannam@89
|
195 staticLib = env.StaticLibrary(target="portaudio", source=sources)
|
cannam@89
|
196
|
cannam@89
|
197 if Platform in Posix:
|
cannam@89
|
198 prefix = env["prefix"]
|
cannam@89
|
199 includeDir = os.path.join(prefix, "include")
|
cannam@89
|
200 libDir = os.path.join(prefix, "lib")
|
cannam@89
|
201
|
cannam@89
|
202 testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \
|
cannam@89
|
203 "patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \
|
cannam@89
|
204 "patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \
|
cannam@89
|
205 "patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \
|
cannam@89
|
206 "patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", "patest_toomanysines", \
|
cannam@89
|
207 "patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat", \
|
cannam@89
|
208 "patest_sine_channelmaps",]
|
cannam@89
|
209
|
cannam@89
|
210 # The test directory ("bin") should be in the top-level PA directory
|
cannam@89
|
211 tests = [env.Program(target=os.path.join("#", "bin", name), source=[os.path.join("#", "test", name + ".c"),
|
cannam@89
|
212 staticLib]) for name in testNames]
|
cannam@89
|
213
|
cannam@89
|
214 # Detect host APIs
|
cannam@89
|
215 hostApis = []
|
cannam@89
|
216 for cppdef in env["CPPDEFINES"]:
|
cannam@89
|
217 if cppdef.startswith("PA_USE_"):
|
cannam@89
|
218 hostApis.append(cppdef[7:-2])
|
cannam@89
|
219
|
cannam@89
|
220 Return("sources", "sharedLib", "staticLib", "tests", "env", "hostApis")
|