# Copyright (c) 2009 John Glover, National University of Ireland, Maynooth # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import os, sys import distutils.sysconfig # location of msys (windows only) # by default, it installs to C:/msys/1.0 msys_path = "C:/msys/1.0" def get_platform(): if sys.platform[:5] == "linux": return "linux" elif sys.platform[:3] == "win": return "win32" elif sys.platform[:6] == "darwin": return "darwin" else: return "unsupported" def get_version(): return sys.version[:3] # check that the current platform is supported if get_platform() == "unsupported": print "Error: Cannot build on this platform. " print " Only Linux, Mac OS X and Windows are currently supported." exit(1) # environment if get_platform() == 'win32': # can only build with mingw on windows env = Environment(ENV=os.environ, tools=['mingw']) else: env = Environment(ENV=os.environ) # set default installation directories default_install_dir = "" if get_platform() == "win32": default_install_dir = "C:/msys/1.0/local" man_prefix = "C:/msys/1.0/local/man/man1" else: default_install_dir = "/usr/local" man_prefix = "/usr/share/man/man1" # command-line options vars = Variables(["variables.cache"]) vars.AddVariables( ("prefix", "Installation directory", default_install_dir), ("libpath", "Additional directory to search for libraries", ""), ("cpath", "Additional directory to search for C header files", ""), BoolVariable('debug', 'Compile extension modules with debug symbols', False), BoolVariable('sndobj', 'Build and install the SndObj module', True), BoolVariable('sms', 'Build and install the SMS module', True), BoolVariable('loris', 'Build and install the loris module', True), BoolVariable('mq', 'Build and install the McAulay-Quatieri module', True), BoolVariable('hmm', 'Build and install the HMM partial tracking module', True), BoolVariable('lp', 'Build and install the LP partial tracking module', True) ) vars.Update(env) vars.Save("variables.cache", env) Help(vars.GenerateHelpText(env)) # set library and header directories if get_platform() == "linux": env.Append(LIBPATH=["/usr/local/lib", "/usr/lib"]) env.Append(CPPPATH=["/usr/local/include", "/usr/include"]) elif get_platform() == "darwin": env.Append(LIBPATH=["/opt/local/lib", "/usr/local/lib", "/usr/lib"]) env.Append(CPPPATH=["/opt/local/include", "/usr/local/include", "/usr/include"]) elif get_platform() == "win32": env.Append(LIBPATH=["/usr/local/lib", "/usr/lib", "C:/msys/1.0/local/lib", "C:/msys/1.0/lib", "C:/Python26/libs"]) env.Append(CPPPATH=["/usr/local/include", "/usr/include", "C:/msys/1.0/local/include", "C:/msys/1.0/include", "C:/Python26/include"]) # add paths specified at the command line env.Append(LIBPATH = env["libpath"]) env.Append(CPPPATH = env["cpath"]) conf = Configure(env) # set python library and include directories python_lib_path = [] python_inc_path = [] # linux if get_platform() == "linux": python_inc_path = ["/usr/include/python" + get_version()] # os x elif get_platform() == "darwin": python_inc_path = ["/Library/Frameworks/Python.framework/Headers", "/System/Library/Frameworks/Python.framework/Headers"] # windows elif get_platform() == "win32": python_lib = "python%c%c"% (get_version()[0], get_version()[2]) python_inc_path = ["c:\\Python%c%c\include" % (get_version()[0], get_version()[2])] python_lib_path.append("c:\\Python%c%c\libs" % (get_version()[0], get_version()[2])) # check for python if not conf.CheckHeader("Python.h", language="C"): for i in python_inc_path: pythonh = conf.CheckHeader("%s/Python.h" % i, language="C") if pythonh: break if not pythonh: print "Python headers are missing. Cannot build simpl." exit(1) # check for swig if not "swig" in env["TOOLS"]: print "Error: Swig was not found." exit(1) # check for numpy try: import numpy try: numpy_include = numpy.get_include() except AttributeError: numpy_include = numpy.get_numpy_include() except ImportError: print "Numpy was not found. Cannot build simpl." exit(1) env.Append(CPPPATH = numpy_include) # check if we need debug symbols if env['debug']: env.Append(CCFLAGS = "-g -O0") env = conf.Finish() # get python installation directory python_install_dir = os.path.join(distutils.sysconfig.get_python_lib(), "simpl") env.Alias('install', python_install_dir) # sndobj module if env["sndobj"]: sndobj_env = env.Clone() sndobj_env.Append(SWIGFLAGS = ["-python", "-c++"]) for lib_path in python_lib_path: sndobj_env.Append(LIBPATH = lib_path) for inc_path in python_inc_path: sndobj_env.Append(CPPPATH = inc_path) sndobj_env.Append(CPPPATH = "sndobj") sndobj_env.Append(CPPPATH = "sndobj/rfftw") # get sources sndobj_sources = Glob("sndobj/*.cpp", strings=True) sndobj_sources.append(Glob("sndobj/rfftw/*.c", strings=True)) # remove wrapper file from source list if it exists, otherwise it will be added twice if "sndobj/sndobj_wrap.cpp" in sndobj_sources: sndobj_sources.remove("sndobj/sndobj_wrap.cpp") # create the python wrapper using SWIG python_wrapper = sndobj_env.SharedObject("sndobj/sndobj.i") sndobj_sources.append(python_wrapper) # copy the generated .py file to the root directory Command("simplsndobj.py", "sndobj/simplsndobj.py", Copy("$TARGET", "$SOURCE")) # build the module if get_platform() == "win32": sndobj_env.Append(LIBS = [python_lib]) sndobj_env.SharedLibrary("simplsndobj", sndobj_sources, SHLIBPREFIX="_", SHLIBSUFFIX=".pyd") elif get_platform() == "darwin": sndobj_env.Append(LIBS = ["python" + get_version()]) sndobj_env.Prepend(LINKFLAGS=["-framework", "python"]) sndobj_env.LoadableModule("_simplsndobj.so", sndobj_sources) else: # linux sndobj_env.Append(LIBS = ["python" + get_version()]) sndobj_env.SharedLibrary("simplsndobj", sndobj_sources, SHLIBPREFIX="_") # sms module if env["sms"]: sms_env = env.Clone() # look for additional libraries sms_conf = Configure(sms_env) # check for libmath if not sms_conf.CheckLibWithHeader('m','math.h','c'): print "libmath could not be found. Cannot build the SMS module." exit(1) # if using windows, assume default gsl paths # this is because env.ParseConfig calls gsl-config using the # windows shell rather than the msys shell, and gsl-config # is a shell script so it will not run using the windows shell # TODO: is there a way to get env.ParseConfig to call the msys # shell instead? Might be useful, although would introduce # another dependency, msys. if get_platform() == 'win32': # check for libgsl if not sms_conf.CheckLibWithHeader('gsl', 'gsl_sys.h', 'c'): print "libgsl (GNU Scientific Library) could not be found. Cannot build the SMS module." exit(1) if not sms_conf.CheckLibWithHeader('gslcblas', 'gsl_cblas.h', 'c'): print "libgsl (GNU Scientific Library) could not be found. Cannot build the SMS module." exit(1) # if not using windows, call gsl-config else: sms_env.ParseConfig("gsl-config --cflags --libs") sms_env = sms_conf.Finish() sms_env.Append(SWIGFLAGS = ["-python"]) for lib_path in python_lib_path: sms_env.Append(LIBPATH = lib_path) for inc_path in python_inc_path: sms_env.Append(CPPPATH = inc_path) sms_env.Append(CPPPATH = "sms") sms_env.Append(CPPPATH = "sms/SFMT") if not env['debug']: sms_env.Append(CCFLAGS = "-O2 -funroll-loops -fomit-frame-pointer -Wall -W") sms_env.Append(CCFLAGS = "-Wno-unused -Wno-parentheses -Wno-switch -fno-strict-aliasing") sms_env.Append(CCFLAGS = "-DMERSENNE_TWISTER") # get sources sms_sources = Glob("sms/*.c", strings=True) # remove wrapper file from source list if it exists, otherwise it may be added twice if "sms/sms_wrap.c" in sms_sources: sms_sources.remove("sms/sms_wrap.c") # create the python wrapper using SWIG python_wrapper = sms_env.SharedObject("sms/sms.i") sms_sources.append(python_wrapper) # copy the generated .py file to the simpl directory Command("simplsms.py", "sms/simplsms.py", Copy("$TARGET", "$SOURCE")) # build the module if get_platform() == "win32": sms_env.Append(LIBS = [python_lib]) sms_env.SharedLibrary("simplsms", sms_sources, SHLIBPREFIX="_", SHLIBSUFFIX=".pyd") elif get_platform() == "darwin": sms_env.Append(LIBS = ["python" + get_version()]) sms_env.Prepend(LINKFLAGS=["-framework", "python"]) sms_env.LoadableModule("_simplsms.so", sms_sources) else: # linux sms_env.Append(LIBS = ["python" + get_version()]) sms_env.SharedLibrary("simplsms", sms_sources, SHLIBPREFIX="_") # install the python modules python_modules = Glob("*.py", strings=True) if get_platform() == "win32": modules = Glob("*.pyd", strings=True) else: modules = Glob("*.so", strings=True) modules.extend(python_modules) for module in modules: env.InstallAs(os.path.join(python_install_dir, module), module)