############################################################################# # Disutils setup file for gammalib Python extension module # # ------------------------------------------------------------------------- # # Copyright (C) 2011-2016 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 . # # # ############################################################################# 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', '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:') # 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: # 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) # Build list of class names classes = [] casts = [] for module in all_modules: # Set file names filename = pkg_name+'/'+module+'.py' infile = open(filename, 'r') # Loop over all lines of input file for line in infile: # Search class names if line.find('class G') != -1: pos = line.find('(') name = line[6:pos] classes.append(name) # Search casts elif line.find('def cast_') != -1: pos = line.find('(') name = line[4:pos] casts.append(name) # Close file infile.close() # Sort classes.sort() casts.sort() # Build names string names = "" n_names = 0 for name in classes: if n_names > 0: names += ", " names += "'"+name+"'" n_names += 1 for name in casts: if n_names > 0: names += ", " names += "'"+name+"'" n_names += 1 # Create gammalib/__init__.py file (build only) if is_build: 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') file.write('__all__ = [') file.write(names) file.write(']\n') for module in all_modules: file.write('from gammalib.'+module+' import *\n') # Remove useless and annoying `*_swigregister` entries from the namespace # see https://cta-redmine.irap.omp.eu/issues/832 file.write(""" bad_entries = [entry for entry in list(locals()) if entry.endswith('_swigregister')] for entry in bad_entries: del locals()[entry] del gammalib.gammalib """) # Add test function # see https://cta-redmine.irap.omp.eu/issues/1486 file.write(""" def test(): from gammalib.tests import test_python test_python.test(installed=True) """) # Add version file.write("\n__version__ = '@PACKAGE_VERSION@'\n") # Close file file.close() # 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. A symbolic link is created to the directory containing the # shared wrapper libraries so that we can add this directory to the PYTHONPATH # for testing. if is_build: try: os.chdir('build') os.remove('gammalib') print('Removed symbolic link build/gammalib.') except: pass try: path = glob.glob('lib.*/gammalib') os.symlink(path[0], 'gammalib') print('Created symbolic link build/gammalib.') except: print('WARNING: Failed to create symbolic link build/gammalib.')