#setup.py
from distutils.core import setup, Extension
from sysconfig import get_python_version

import sys
import os

@USING_PGI_COMPILER_TRUE@using_pgi=True
@USING_PGI_COMPILER_FALSE@using_pgi=False
@BUILD_MINGW_TRUE@mingw = 1
@BUILD_MINGW_FALSE@mingw = 0

# TODO temporary workaround for mingw + cmake
# When running with mingw-cmake, the path of the form C:/msys64/xyz
# needs to be transformed to C:\msys64/xyz.
def get_escaped_path(path):
  if mingw:
    return path.replace(":/", ":\\")
  else:
    return path

# NRNPYTHON_DEFINES which were enabled at configure time
extern_defines = "@NRNPYTHON_DEFINES@"
nrnpython_exec = get_escaped_path("@NRNPYTHON_EXEC@")
nrnpython_pyver = "@NRNPYTHON_PYVER@"
nrnpython_pyver10 = "nrnpython"
use_libnrnpython_majorminor = @USE_LIBNRNPYTHON_MAJORMINOR@
nrn_srcdir = get_escaped_path(os.path.relpath("@NRN_SRCDIR@"))
build_rx3d = @BUILD_RX3D@
ivlibdir = get_escaped_path("@IV_LIBDIR@")
if ivlibdir == "" :
    ivlibdir = '.'

destdir = os.getenv("DESTDIR")
if not destdir:
  destdir = ""

# install into build directory and then copy to install prefix
instdir = destdir + get_escaped_path(os.path.relpath("@CMAKE_BINARY_DIR@"))

if nrn_srcdir[0] != '/' :
  if mingw:
    nrn_srcdir = nrn_srcdir

if "@BUILD_NRNPYTHON_DYNAMIC_TRUE@" == "":
  # can do all the setup.py without re-configure.
  nrnpython_pyver = get_python_version()
  nrnpython_exec = sys.executable
  nrnpython_pyver10 = "nrnpython" + str(sys.version_info[0])
  if use_libnrnpython_majorminor == 1:
    nrnpython_pyver10 = "nrnpython" + str(sys.version_info[0]) + str(sys.version_info[1])

else:
  if nrnpython_pyver!=get_python_version():
    print ("Error:")
    print ("NEURON configure time python: "+nrnpython_exec+"  "+ nrnpython_pyver)
    print ("Python presently executing setup.py: "+sys.executable+"   "+ get_python_version())
    print ("These do not match, and they should!")
    sys.exit(1)


ldefs = extern_defines.split('-D')

# if using MPI then at least for linking need special paths and libraries
import os
c_compiler_path = get_escaped_path("@CC@")
cxx_compiler_path = get_escaped_path("@CXX@")

# setup.py tries to compile C++ code with the C compiler. This works with
# gcc and intel but fails with at least PGI compiler. Hence, use C++ compiler
# if PGI compiler is used.
os.environ['CC'] = cxx_compiler_path if using_pgi else c_compiler_path
os.environ["CXX"] = cxx_compiler_path

if using_pgi:
  # Spack installed Python includes patches that require setting LDSHARED
  # and LDCXXSHARED environmental variables to ensure the PGI/NVIDIA linker
  # is used as well as the compiler. Otherwise GCC is used and it chokes on
  # PGI/NVIDIA-specific compiler flags.
  os.environ["LDSHARED"] = os.environ['CC'] + " -shared"
  os.environ["LDCXXSHARED"] = os.environ["CXX"] + " -shared"

# apparently we do not need the following
#################################
## following http://code.google.com/p/maroonmpi/wiki/Installation
## hack into distutils to replace the compiler in "linker_so" with mpicxx_bin
#
#import distutils
#import distutils.unixccompiler
#
#class MPI_UnixCCompiler(distutils.unixccompiler.UnixCCompiler):
#    __set_executable = distutils.unixccompiler.UnixCCompiler.set_executable
#
#    def set_executable(self,key,value):
#	print "MPI_UnixCCompiler ", key, " | ", value
#        if key == 'linker_so' and type(value) == str:
#            value = mpicxx_bin + ' ' + ' '.join(value.split()[1:])
#
#        return self.__set_executable(key,value)
#    
#distutils.unixccompiler.UnixCCompiler = MPI_UnixCCompiler
#################################

#include_dirs for hoc module
include_dirs = [nrn_srcdir+'/src/nrnpython', nrn_srcdir+'/src/oc', '../oc', nrn_srcdir+'/src/nrnmpi']
#include dirs for all modules

include_dirs_common = []

#not needed with clang,clang++ and on my beta catalina does not
#work anyway with /Library/Developer/CommandLineTools/usr/bin/cc
#for the ctng module
#@MAC_DARWIN_TRUE@include_dirs_common.append("@CMAKE_OSX_SYSROOT@/usr/include")

defines = []

libdirs = [destdir + get_escaped_path("@NRN_LIBDIR@"),
  ivlibdir
]

# prepare rpath flags for neuron and iv libs directories
rpath_prefix_flag='-Wl,-R'
extra_link_args = [@NRN_LINK_FLAGS_COMMA_SEPARATED_STRINGS@]
@MAC_DARWIN_FALSE@extra_link_args += [rpath_prefix_flag+lib_path for lib_path in libdirs]
@MAC_DARWIN_TRUE@extra_link_args.append("-Wl,-rpath,@loader_path/../../")
@MAC_DARWIN_TRUE@extra_link_args.append("-Wl,-rpath,%s" % ivlibdir)

# as neuron module will be built during make, add build/lib
# directory for linking. Note that build/lib shouldn't be
# added to rpath to avoid issues with dlopen.
libdirs.append(destdir + get_escaped_path(os.path.relpath("@CMAKE_BINARY_DIR@/lib")))

@MAC_DARWIN_FALSE@readline="readline@READLINE_SOSUFFIX@"
@MAC_DARWIN_TRUE@readline="readline@READLINE_SOSUFFIX@"

pgi_compiler_flags = "-noswitcherror"

libs = [@BUILD_NRNPYTHON_DYNAMIC_TRUE@nrnpython_pyver10,
"nrniv"
]
if "@IVHINES@" != "":
    libs.append("@IVHINES@")

extra_compile_args = [@NRN_COMPILE_FLAGS_COMMA_SEPARATED_STRINGS@]

if using_pgi:
  extra_link_args.append(pgi_compiler_flags)
  extra_compile_args.append(pgi_compiler_flags)

hoc_module = Extension(
    "neuron.hoc",
    ["inithoc.cpp"],
    library_dirs=libdirs,
    extra_link_args=extra_link_args,
    #extra_objects = [],
    extra_compile_args = extra_compile_args,
    libraries = libs ,
    include_dirs = include_dirs+include_dirs_common,
    define_macros=defines
    )

# specify that the data_files paths are relative to same place as python files
# from http://stackoverflow.com/questions/1612733/including-non-python-files-with-setup-py
from distutils.command.install import INSTALL_SCHEMES
for scheme in list(INSTALL_SCHEMES.values()):
    scheme['data'] = scheme['purelib']

ext_modules = [hoc_module]

# The rx3d extensions are built using the setup.py.in in
# nrn/share/lib/python/neuron/rxd/geometry3d which contains Cython pyx files
# These files on Windows have to be compiled with the msvc compiler to avoid
# issues with hypot, a #define, and some DL_IMPORT statements. At least for
# Python3.5, the module must be built with the msvc toolchain to prevent a
# crash, possibly due to incompatible c runtime libraries. The following
# section is left here with the idea that someday the entire build on windows
# may be done with the msvc toolchain. Note, although the extensions are not
# built here, the python files are copied because of the call to setup here.

if build_rx3d:
  try:
    import numpy
    # TODO: do we need to use os.path.join?
    src_path = nrn_srcdir + '/share/lib/python/neuron/rxd/geometry3d/'
    build_path = '../../share/lib/python/neuron/rxd/geometry3d/'
    include_dirs = [nrn_srcdir + '/share/lib/python/neuron/rxd/geometry3d', '.', numpy.get_include()]
    include_dirs += include_dirs_common
    extra_compile_args=["-O@NRN_RX3D_OPT_LEVEL@"] + extra_compile_args
    define_macros = []
    if mingw:
      #Avoid undefined __imp_Py_InitModule4 and hypot problem
      define_macros.append(("MS_WIN64", None))
    ext_modules=[hoc_module,
                   Extension("neuron.rxd.geometry3d.graphicsPrimitives",
                             sources=[build_path + "graphicsPrimitives.cpp"],
                             extra_compile_args = extra_compile_args,
                             extra_link_args=extra_link_args,
                             define_macros = define_macros,
                             include_dirs=include_dirs),
                   Extension("neuron.rxd.geometry3d.ctng",
                             sources=[build_path + "ctng.cpp"],
                             extra_compile_args = extra_compile_args,
                             extra_link_args=extra_link_args,
                             define_macros = define_macros,
                             include_dirs=include_dirs),
                   Extension("neuron.rxd.geometry3d.surfaces",
                             sources=[build_path + "surfaces.cpp", nrn_srcdir + "/src/nrnpython/rxd_marching_cubes.cpp", nrn_srcdir + "/src/nrnpython/rxd_llgramarea.cpp"],
                             define_macros = define_macros,
                             extra_compile_args = extra_compile_args,
                             extra_link_args=extra_link_args,
                             include_dirs=include_dirs)]
  except:
    pass

packages=['neuron','neuron.neuroml','neuron.tests', 'neuron.rxd', 'neuron.crxd', 'neuron.gui2']
if build_rx3d:
  packages +=['neuron.rxd.geometry3d']

pkg_dir = os.path.relpath("@CMAKE_BINARY_DIR@") + '/share/nrn/lib/python'

setup(name="NEURON", version="@PACKAGE_VERSION@",
      description = "NEURON bindings for python",
      package_dir = {'': pkg_dir},
      packages=packages,
      data_files = [('neuron', [nrn_srcdir + '/share/lib/python/neuron/help_data.dat'])],
      ext_modules=ext_modules
)

