#!/usr/bin/env python # # Setup script for the Python bindings to NEST (PyNEST) # # This file is part of NEST. # # Copyright (C) 2004 The NEST Initiative # # NEST 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. # # NEST 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 NEST. If not, see <http://www.gnu.org/licenses/>. # # Author: Jochen Martin Eppler # Date: 05/04/2007 # # Rewritten to make use of Python's distutils package, 01/31/08 # Sven Schrader, Jochen Martin Eppler # import sys, os from string import split from sys import exit import distutils.sysconfig as sysc cxx = '@CXX@' sources = ['@PKGSRCDIR@/pynest/pynestkernel.cpp', '@PKGSRCDIR@/pynest/pydatum.cpp', '@PKGSRCDIR@/pynest/datumtopythonconverter.cpp', '@PKGSRCDIR@/pynest/pynestpycsa.cpp'] # -fpermissive needed for ndarrayobject.h # to compile due to comma terminated enumerations pre_cxxflags = '@AM_CXXFLAGS@ @PYNEST_CXXFLAGS@' pre_includes = [ '@PKGSRCDIR@/libnestutil', '@PKGSRCDIR@/librandom', '@PKGSRCDIR@/sli', '@PKGSRCDIR@/nestkernel', '@PKGBUILDDIR@/libnestutil', '@PKGBUILDDIR@/nest', '@MUSIC_INCLUDE@', '@MPI_INCLUDE@', '@GSL_CFLAGS@', '@INCLTDL@'] pre_ldflags = [ '-L@PKGBUILDDIR@/nestkernel/.libs', '-L@PKGBUILDDIR@/librandom/.libs', '-L@PKGBUILDDIR@/sli/.libs', '@LINKED_USER_MODULES@', '@LINKED_MODULES@', '-lnest', '-lrandom', '-lsli', '@KOMP_LIBS@', '@SLI_LIBS@', '@GSL_LIBS@', '@MUSIC_LIBS@', '@MPI_LIBS@', '-lpthread', '@LIBLTDL@', '@LIBADD_DL@'] include_dirs = [] library_dirs = [] libraries = [] define_macros = [] setup_flags = [] extra_objects = [] cxxflags = [] extra_link_args = ['@OPENMP_CXXFLAGS@'] runtime_library_dirs = [] for incs in pre_includes : for inc in incs.split(' '): if len(inc) > 1: if '-i' in inc.lower(): include_dirs.append(inc.replace('-I', '').replace('-i','')) else: include_dirs.append(inc) for libs in pre_ldflags : for lib in libs.split(' '): if len(lib) > 1: if lib[1] == 'L' : library_dirs.append(lib.replace('-L', '')) if lib[1] == 'l' : libraries.append(lib.replace('-l', '')) # read the libtool .la file and extract name and path if lib.endswith('.la'): filename=lib.replace('$(top_builddir)','@PKGBUILDDIR@') try: fp = open(filename, 'r') dlname='' libdir='' line = fp.readline() while line: # dlname: library name if len(line) > 7 and line.startswith('dlname=') and dlname=='': dlname = line[8:-2] # old_library: library name (static module) if len(line) > 12 and line.startswith('old_library=') and dlname=='': dlname = line[13:-2] # ...and its directory if len(line) > 7 and line.startswith('libdir='): libdir = line[8:-2] line = fp.readline() fp.close() # hard-code library path to avoid setting environment if libdir: runtime_library_dirs += [libdir] # full location of the object file if dlname: extra_objects += [ os.path.dirname(filename) + '/.libs/' + dlname ] except: print 'Could not parse file', filename for flag in pre_cxxflags.strip().split(' '): if len(flag) > 1: cxxflags += [flag] if 'build' in sys.argv : setup_flags += ['--build-base=@PKGBUILDDIR@/pynest/build'] # look for numpy libs and change flags/macros accordingly # this dependency cannot be detected by distutils automatically # HAVE_NUMPY must be set both in build and install mode try: import numpy if 'arrayobject.h' in os.listdir(numpy.__path__[0]+ '/core/include/numpy'): include_dirs += [ numpy.__path__[0] + '/core/include'] define_macros += [('HAVE_NUMPY', None)] else: print '*** No numpy headers installed ***' except ImportError: print '*** No numpy package installed ***' if 'clean' in sys.argv : # 'make clean' does not work properly; python bug 510186 print '*** running clean, ignore warnings about nonexistent directories ***' sys.argv = sys.argv + setup_flags # Change the compiler and linker: # replace first argumemnt with compiler-variable 'cxx' vars = sysc.get_config_vars() for key in ['CC','LDSHARED', 'CXX', 'LINKCC']: value = vars[key].split() value[0] = cxx vars[key] = ' '.join(value) # the following compiler options are not accepted by newer g++ versions for opt in ["-Wstrict-prototypes", "-Wno-long-double", "-no-cpp-precomp"]: vars["CFLAGS"]=sysc.get_config_var("CFLAGS").replace(opt, "") # from here, it's distutils' way from distutils.core import setup, Extension # an empty string is also interpreted as a library to link against. if extra_link_args == ['']: extra_link_args = [] extdict = {'include_dirs' : include_dirs, 'libraries' : libraries, 'library_dirs' : library_dirs, 'sources' : sources, 'extra_compile_args' : cxxflags, 'extra_link_args' : extra_link_args, 'define_macros' : define_macros, 'extra_objects' : extra_objects} # set linker-path correctly when using mpicc. # distutils sets wrong parameters there. See Python bugs #445902, #1254718 if runtime_library_dirs != [] : if 'mpi' in cxx.lower() or cxx.lower()[-3:] in ('gcc', 'g++') : extdict['extra_link_args'] += ['-Wl,-rpath,' + dir for dir in runtime_library_dirs] else : extdict['runtime_library_dirs'] = runtime_library_dirs setup(name = 'PyNEST', version = '@SLI_VERSION@', description = 'PyNEST provides Python bindings for NEST', author = 'The NEST Initiative', url = 'http://www.nest-initiative.org', packages = ['nest', 'nest.tests'], package_dir = {'nest': '@PKGSRCDIR@/pynest/nest'}, package_data = {'nest': ['pynest-init.sli']}, ext_modules = [Extension('nest.pynestkernel', **extdict)])