setup.py.in 10.2 KB
#############################################################################
# Disutils setup file for gammalib Python extension module                  #
# ------------------------------------------------------------------------- #
# Copyright (C) 2011-2017 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
import shutil

# Define package name
pkg_name = 'gammalib'

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

# Detect execution mode
is_build = True
if (len(sys.argv) >= 2):
    if (sys.argv[1] == 'install'):
        is_build = False
if is_build:
    print('Python extension module building:')
else:
    print('Python extension module installation:')

# Set prefix
prefix = '@prefix@'
if (len(sys.argv) >= 3):
    if (sys.argv[2].find('--prefix') != -1):
        start  = sys.argv[2].find('=') + 1
        prefix = sys.argv[2][start:]

# 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('Removed following option(s) from LDSHARED: '+ldshared_rm)
    # Set LDSHARED
    cvars['LDSHARED'] = ldshared_new

# 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            = ['gamma']

# 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('Link cfitsio into Python module.')
    libraries.append('cfitsio')

# Add readline library only if available
if '@WITH_READLINE_TRUE@' != '#':
    print('Link readline into Python module.')
    libraries.append('@LIB_READLINE@')
    libraries.append('@LIB_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('Include multi-wavelength interface in gammalib Python module.')
    inst_modules.append('mwl')
if '@WITH_INST_CTA_TRUE@' != '#':
    print('Include CTA instrument interface in gammalib Python module.')
    inst_modules.append('cta')
if '@WITH_INST_LAT_TRUE@' != '#':
    print('Include Fermi/LAT instrument interface in gammalib Python module.')
    inst_modules.append('lat')
if '@WITH_INST_COM_TRUE@' != '#':
    print('Include COMPTEL instrument interface in gammalib Python module.')
    inst_modules.append('com')

# 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    = []

# Optionally add link flag for El Capitan post-processing of modules
if '@IS_ELCAPITAN_TRUE@' != '#':
    extra_link_args.append('-headerpad_max_install_names')

# Loop over all core modules
for module in core_modules:

    # In case that wrappers were not built then copy the module wrapper files
    # from the source to the build directory. Only do this if the build
    # directory differs from the source directory
    if '@BUILD_WRAPPERS_FALSE@' != '#' and is_build and \
       '@srcdir@' != '@builddir@':
        py_file  = pkg_name+'/'+module+'.py'
        cpp_file = pkg_name+'/'+module+'_wrap.cpp'
        os.system('cp %s %s' % ('@srcdir@/'+cpp_file, '@builddir@/'+cpp_file))
        os.system('cp %s %s' % ('@srcdir@/'+py_file,  '@builddir@/'+py_file))

    # 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:

    # Set include directories for module
    include_inst_dirs = include_dirs
    include_inst_dirs.append('@top_srcdir@/inst/'+module+'/include')

    # Add SWIG files to install_files
    install_files.extend(glob.glob('@top_srcdir@/inst/'+module+'/pyext/*.i'))

    # In case that wrappers were not built then copy the module wrapper files
    # from the source to the build directory. Only do this if the build
    # directory differs from the source directory
    if '@BUILD_WRAPPERS_FALSE@' != '#' and is_build and \
       '@srcdir@' != '@builddir@':
        py_file  = pkg_name+'/'+module+'.py'
        cpp_file = pkg_name+'/'+module+'_wrap.cpp'
        os.system('cp %s %s' % ('@srcdir@/'+cpp_file, '@builddir@/'+cpp_file))
        os.system('cp %s %s' % ('@srcdir@/'+py_file,  '@builddir@/'+py_file))

    # Define module
    ext_module = Extension('_'+module, [pkg_name+'/'+module+'_wrap.cpp'], \
                           include_dirs=include_inst_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 data files to install.
data_files=[(prefix+'/share/gammalib/swig', install_files)]

# Setup
setup(name='@PACKAGE_NAME@',
      version='@PACKAGE_VERSION@',
      description='gammalib Python module',
      author='Juergen Knoedlseder',
      author_email='@PACKAGE_BUGREPORT@',
      maintainer='Juergen Knoedlseder',
      maintainer_email='@PACKAGE_BUGREPORT@',
      url='http://cta.irap.omp.eu/gammalib/',
      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. The shared wrapper libraries are copied into the
# build/gammalib directory and this directory is appended to the PYTHONPATH
# so that shared libraries can be accessed during unit testing. This kluge
# is needed since the name of the build directory where the shared libraries
# reside is not known when building the Makefile.
if is_build:

    # Remove existing build/gammalib directory
    try:
        os.remove('build/gammalib')
        print('Removed "build/gammalib" directory.')
    except:
        pass

    # Create build/gammalib directory
    try:
        os.mkdir('build/gammalib')
        print('Created "build/gammalib" directory.')
    except (OSError):
        print('Directory "build/gammalib" exists already.')
    except:
        print('ERROR: Failed to create directory "build/gammalib".')
        raise

    # Copy over shared libraries from lib.*/gammalib folder
    files = glob.glob('build/lib.*/gammalib/_*.so')
    for file in files:
        dst = os.path.join('build/gammalib', os.path.basename(file))
        shutil.copy2(file, dst)
        print('Copied %s -> %s' % (file, dst))
    print('Copied shared libraries into "build/gammalib" directory.')