gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

SConscript (9449B)


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