setup.py.in 10.2 KB
#############################################################################
# Disutils setup file for gammalib Python extension module                  #
# ------------------------------------------------------------------------- #
# Copyright (C) 2011-2012 Juergen Knoedlseder                               #
# ------------------------------------------------------------------------- #
#                                                                           #
#  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 3 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, see <http://www.gnu.org/licenses/>.    #
#                                                                           #
#############################################################################

from distutils.core import setup, Extension
from distutils import sysconfig
import glob
import os
import sys
import re

# Define package name
pkg_name = 'gammalib'

# Define core modules
core_modules = ['app', 'fits', 'linalg', 'model', 'numerics', \
                'obs', 'opt', 'sky', 'support', 'test', 'xml']

# Detect execution mode
is_unit_test = False
if (len(sys.argv) >= 3):
	if (sys.argv[2] == '--inplace'):
		print@PYTHON_OPEN@"This build is for unit testing."@PYTHON_CLOSE@
		is_unit_test = True

# Darwin MacPorts kluge: Remove -L/opt/local/lib path from LDSHARED as this
# overrides the GammaLib settings. Otherwise, MacPorts libraries would be
# used instead of the libraries selected by GammaLib
if sys.platform.lower().startswith("darwin"):
	
	# Get configuration variables
	cvars = sysconfig.get_config_vars()
	
	# Extract LDSHARED
	ldshared_old = cvars.get('LDSHARED')
	ldshared_new = ''
	ldshared_rm  = ''
	for option in ldshared_old.split(' '):
		if option.lstrip().find('-L/opt/local/lib') != 0:
			ldshared_new += option + ' '
		else:
			ldshared_rm += option + ' '
	if (len(ldshared_rm) > 0):
		print@PYTHON_OPEN@"Removed following option(s) from LDSHARED: "+ldshared_rm@PYTHON_CLOSE@
	
	# Set LDSHARED
	cvars['LDSHARED'] = ldshared_new

# Set GammaLib library name. If we're about to make the test build then
# create a symbolic link to the static library to enforce static linking.
# This is required on some system (such as Mac OS X) to avoid problems
# with finding the shared library during unit testing.
libgamma='gamma'
#if is_unit_test:
if is_unit_test and sys.platform.lower().startswith("darwin"):
	
	# Remove any existing symbolic link to libgamma.a. This will
	# prevent any exception in creating the symbolic link due to
	# an already existing link.
	try:
		os.remove('../src/.libs/libgamma_python.a')
		print@PYTHON_OPEN@"Removed ../src/.libs/libgamma_python.a"@PYTHON_CLOSE@
	except:
		pass
	
	# Now create a symbolic link and set the library name to this
	# symbolic link
	try:
		os.symlink('libgamma.a', '../src/.libs/libgamma_python.a')
		print@PYTHON_OPEN@"Created ../src/.libs/libgamma_python.a"@PYTHON_CLOSE@
		libgamma='gamma_python'
	except:
		print@PYTHON_OPEN@"WARNING: Failed to create symbolic link to static library. Link dynamically."@PYTHON_CLOSE@

# Set default include directories, install files, library paths and libraries
include_dirs         = ['@top_srcdir@/include']
install_files        = glob.glob('@top_srcdir@/pyext/*.i')
library_dirs         = ['../src/.libs']
runtime_library_dirs = ['../src/.libs']
libraries            = [libgamma]

# Add install directory to runtime library path
if os.path.exists('@prefix@/lib'):
	runtime_library_dirs.append('@prefix@/lib')

# Add cfitsio library only if available
if '@WITH_CFITSIO_TRUE@' != '#':
	print@PYTHON_OPEN@"Link cfitsio into Python bindings."@PYTHON_CLOSE@
	libraries.append('cfitsio')

# Add readline library only if available
if '@WITH_READLINE_TRUE@' != '#':
	print@PYTHON_OPEN@"Link readline into Python bindings."@PYTHON_CLOSE@
	libraries.append('readline')
	libraries.append('ncurses')

# Add extra libraries
extra_libs = ('@PYTHON_EXTRA_LIBS@').split(',')
for extra_lib in extra_libs:
	if len(extra_lib) > 0:
		libraries.append(extra_lib)

# Get extra library paths (for cfitsio, readline, ncurses)
extra_lib_paths = ('@LDFLAGS@').split(' ')
for extra_lib_path in extra_lib_paths:
	if extra_lib_path.lstrip().find('-L') == 0:
		dir = extra_lib_path.lstrip().lstrip('-L')
		if len(dir) > 0:
			library_dirs.append(dir)
			runtime_library_dirs.append(dir)

# Get extra include directories
extra_inc_paths = ('@CPPFLAGS@').split(' ')
for extra_inc_path in extra_inc_paths:
	if extra_inc_path.lstrip().find('-I') == 0:
		dir = extra_inc_path.lstrip().lstrip('-I')
		if len(dir) > 0:
			include_dirs.append(dir)

# Add definitions for instrument specific modules
inst_modules = []
if '@WITH_INST_MWL_TRUE@' != '#':
	print@PYTHON_OPEN@"Include multi-wavelength interface in gammalib Python bindings."@PYTHON_CLOSE@
	inst_modules.append('mwl')
if '@WITH_INST_CTA_TRUE@' != '#':
	print@PYTHON_OPEN@"Include CTA instrument interface in gammalib Python bindings."@PYTHON_CLOSE@
	inst_modules.append('cta')
if '@WITH_INST_LAT_TRUE@' != '#':
	print@PYTHON_OPEN@"Include Fermi/LAT instrument interface in gammalib Python bindings."@PYTHON_CLOSE@
	inst_modules.append('lat')

# Set extension definition for core modules
all_modules = []
ext_modules = []
py_modules  = []

# Optionally enable OpenMP
if '@OPENMP_TRUE@' != '#':
	extra_compile_args = ['@OPENMP_CXXFLAGS@']
	extra_link_args    = ['@OPENMP_CXXFLAGS@']
else:
	extra_compile_args = []
	extra_link_args    = []

# Loop over all core modules
for module in core_modules:
	
	# Define module
	ext_module = Extension('_'+module, [pkg_name+'/'+module+'_wrap.cpp'], \
	                       include_dirs=include_dirs, \
                           libraries=libraries,
                           library_dirs=library_dirs,
                           runtime_library_dirs=runtime_library_dirs,
                           extra_compile_args=extra_compile_args,
                           extra_link_args=extra_link_args)
	all_modules.append(module)
	ext_modules.append(ext_module)
	py_modules.append(pkg_name+'.'+module)

# Set extension definition for instrument dependent modules
for module in inst_modules:

	# Define paths
	pyext_path   = '@top_srcdir@/inst/'+module+'/pyext'
	include_path = '@top_srcdir@/inst/'+module+'/include'
	
	# Set include directories for module
	include_inst_dirs = include_dirs
	include_inst_dirs.append(include_path)
	
	# Add SWIG files to install_files
	install_files.extend(glob.glob(pyext_path+'/*.i'))
	
	# Define module
	ext_module = Extension('_'+module, [pkg_name+'/'+module+'_wrap.cpp'], \
                           include_dirs=include_dirs, \
                           libraries=libraries,
                           library_dirs=library_dirs,
                           runtime_library_dirs=runtime_library_dirs,
                           extra_compile_args=extra_compile_args,
                           extra_link_args=extra_link_args)
	all_modules.append(module)
	ext_modules.append(ext_module)
	py_modules.append(pkg_name+'.'+module)

# Create gammalib/__init__.py file
file = open(pkg_name+'/__init__.py', 'w')
file.write('# This file is created automatically by setup.py\n')
file.write('# Please do not modify, unless you exactly know what you do.\n')
for module in all_modules:
	file.write('from gammalib.'+module+' import *\n')
file.close()

# Post-process swig files. This post-processing is needed to transform
# "import XXX" statements into "from XXX import *" statements. Furthermore,
# the module information is stripped from all base classes, e.g.
# "gammalib.obs.GRoi" becomes "GRoi".
for module in all_modules:

	# Set file names
	filename = pkg_name+"/"+module+".py"
	origname = pkg_name+"/"+module+".py.orig"

	# Rename original file (for safety)
	os.rename(filename,origname)

	# Open files
	infile  = open(origname, 'r')
	outfile = open(filename, 'w')

	# Initialize reformulation statistics
	n_import = 0
	n_class  = 0

	# Loop over all lines of input file
	for line in infile:

		# Reformulate import statements
		if line.find("import gammalib.") != -1:
			pos      = line.find("gammalib.")
			name     = line[pos:].rstrip('\n').strip(' ')
			line     = "from "+name+" import *\n"
			n_import = n_import + 1

		# Reformulate base class declarations
		elif re.search("gammalib.+.G+", line):
			start   = line.find("gammalib.")
			pos     = line[start:].find("G")+start
			pre     = line[0:start]
			post    = line[pos:]
			line    = pre+post
			n_class = n_class + 1

		# Write line
		outfile.write(line)

	# Close files
	infile.close()
	outfile.close()

	# Dump reformulation statistics for actual module
	if n_import > 0 or n_class > 0:
		print@PYTHON_OPEN@module+".py reformulation: "+str(n_import)+ \
		      " imports, "+str(n_class)+" base class declarations."@PYTHON_CLOSE@

# Set data files to install. Do not install data files in unit testing mode.
if is_unit_test:
	data_files=[]
else:
	data_files=[('@prefix@/share/gammalib/swig', install_files)]

# Setup
setup(name='@PACKAGE_NAME@',
      version='@PACKAGE_VERSION@',
      description='gammalib Python bindings',
      author='Juergen Knoedlseder',
      author_email='@PACKAGE_BUGREPORT@',
      maintainer='Juergen Knoedlseder',
      maintainer_email='@PACKAGE_BUGREPORT@',
      url='http://gammalib.sourceforge.net/',
      packages=[pkg_name],
      ext_package=pkg_name,
      ext_modules=ext_modules,
      py_modules=py_modules,
      data_files=data_files,
      license="GNU GPL v3",
      long_description="Versatile toolbox for the analysis of astronomical gamma-ray data",
      platforms=["Linux", "Solaris", "Mac OS-X", "Unix", "BSD"],
	  )

# Post-processing