Skip to content
This repository was archived by the owner on Apr 11, 2022. It is now read-only.

Commit ae3a745

Browse files
committed
Bug fix for python library detection, use pybind11 module
which has worked very well. See: pybind/pybind11#207
1 parent e2c73c5 commit ae3a745

File tree

2 files changed

+204
-1
lines changed

2 files changed

+204
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ endif()
109109
# enable python support (interpreter needed to make hocusr.h from neuron.h, prefer Python 3)
110110
find_package(PythonInterp REQUIRED)
111111
if (NRN_ENABLE_PYTHON)
112-
find_package(PythonLibs ${PYTHON_VERSION_MAJOR} REQUIRED)
112+
find_package(PythonLibsNew ${PYTHON_VERSION_MAJOR} REQUIRED)
113113
set(USE_PYTHON 1)
114114
else()
115115
set(USE_PYTHON 0)

cmake/modules/FindPythonLibsNew.cmake

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# =============================================================================
2+
# Find libraries corresponding to Python interpreter
3+
# =============================================================================
4+
# Using this module from Pybind11, see: github.com/pybind/pybind11/pull/207
5+
#
6+
# - Find python libraries
7+
# This module finds the libraries corresponding to the Python interpreter
8+
# FindPythonInterp provides.
9+
# This code sets the following variables:
10+
#
11+
# PYTHONLIBS_FOUND - have the Python libs been found
12+
# PYTHON_PREFIX - path to the Python installation
13+
# PYTHON_LIBRARIES - path to the python library
14+
# PYTHON_INCLUDE_DIRS - path to where Python.h is found
15+
# PYTHON_MODULE_EXTENSION - lib extension, e.g. '.so' or '.pyd'
16+
# PYTHON_MODULE_PREFIX - lib name prefix: usually an empty string
17+
# PYTHON_SITE_PACKAGES - path to installation site-packages
18+
# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build
19+
#
20+
# Thanks to talljimbo for the patch adding the 'LDVERSION' config
21+
# variable usage.
22+
23+
#=============================================================================
24+
# Copyright 2001-2009 Kitware, Inc.
25+
# Copyright 2012 Continuum Analytics, Inc.
26+
#
27+
# All rights reserved.
28+
#
29+
# Redistribution and use in source and binary forms, with or without
30+
# modification, are permitted provided that the following conditions
31+
# are met:
32+
#
33+
# * Redistributions of source code must retain the above copyright
34+
# notice, this list of conditions and the following disclaimer.
35+
#
36+
# * Redistributions in binary form must reproduce the above copyright
37+
# notice, this list of conditions and the following disclaimer in the
38+
# documentation and/or other materials provided with the distribution.
39+
#
40+
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
41+
# nor the names of their contributors may be used to endorse or promote
42+
# products derived from this software without specific prior written
43+
# permission.
44+
#
45+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48+
# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
49+
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
55+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56+
#=============================================================================
57+
58+
# Checking for the extension makes sure that `LibsNew` was found and not just `Libs`.
59+
if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION)
60+
return()
61+
endif()
62+
63+
# Use the Python interpreter to find the libs.
64+
if(PythonLibsNew_FIND_REQUIRED)
65+
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED)
66+
else()
67+
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION})
68+
endif()
69+
70+
if(NOT PYTHONINTERP_FOUND)
71+
set(PYTHONLIBS_FOUND FALSE)
72+
return()
73+
endif()
74+
75+
# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
76+
# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
77+
# way to detect a CPython debug interpreter.
78+
#
79+
# The library suffix is from the config var LDVERSION sometimes, otherwise
80+
# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
81+
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
82+
"from distutils import sysconfig as s;import sys;import struct;
83+
print('.'.join(str(v) for v in sys.version_info));
84+
print(sys.prefix);
85+
print(s.get_python_inc(plat_specific=True));
86+
print(s.get_python_lib(plat_specific=True));
87+
print(s.get_config_var('SO'));
88+
print(hasattr(sys, 'gettotalrefcount')+0);
89+
print(struct.calcsize('@P'));
90+
print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION'));
91+
print(s.get_config_var('LIBDIR') or '');
92+
print(s.get_config_var('MULTIARCH') or '');
93+
"
94+
RESULT_VARIABLE _PYTHON_SUCCESS
95+
OUTPUT_VARIABLE _PYTHON_VALUES
96+
ERROR_VARIABLE _PYTHON_ERROR_VALUE)
97+
98+
if(NOT _PYTHON_SUCCESS MATCHES 0)
99+
if(PythonLibsNew_FIND_REQUIRED)
100+
message(FATAL_ERROR
101+
"Python config failure:\n${_PYTHON_ERROR_VALUE}")
102+
endif()
103+
set(PYTHONLIBS_FOUND FALSE)
104+
return()
105+
endif()
106+
107+
# Convert the process output into a list
108+
if(WIN32)
109+
string(REGEX REPLACE "\\\\" "/" _PYTHON_VALUES ${_PYTHON_VALUES})
110+
endif()
111+
string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES})
112+
string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES})
113+
list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST)
114+
list(GET _PYTHON_VALUES 1 PYTHON_PREFIX)
115+
list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR)
116+
list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES)
117+
list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION)
118+
list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG)
119+
list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P)
120+
list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX)
121+
list(GET _PYTHON_VALUES 8 PYTHON_LIBDIR)
122+
list(GET _PYTHON_VALUES 9 PYTHON_MULTIARCH)
123+
124+
# Make sure the Python has the same pointer-size as the chosen compiler
125+
# Skip if CMAKE_SIZEOF_VOID_P is not defined
126+
if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}"))
127+
if(PythonLibsNew_FIND_REQUIRED)
128+
math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8")
129+
math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8")
130+
message(FATAL_ERROR
131+
"Python config failure: Python is ${_PYTHON_BITS}-bit, "
132+
"chosen compiler is ${_CMAKE_BITS}-bit")
133+
endif()
134+
set(PYTHONLIBS_FOUND FALSE)
135+
return()
136+
endif()
137+
138+
# The built-in FindPython didn't always give the version numbers
139+
string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST})
140+
list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
141+
list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
142+
list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
143+
144+
# Make sure all directory separators are '/'
145+
string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX})
146+
string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR})
147+
string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES})
148+
149+
if(CMAKE_HOST_WIN32)
150+
set(PYTHON_LIBRARY
151+
"${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
152+
153+
# when run in a venv, PYTHON_PREFIX points to it. But the libraries remain in the
154+
# original python installation. They may be found relative to PYTHON_INCLUDE_DIR.
155+
if(NOT EXISTS "${PYTHON_LIBRARY}")
156+
get_filename_component(_PYTHON_ROOT ${PYTHON_INCLUDE_DIR} DIRECTORY)
157+
set(PYTHON_LIBRARY
158+
"${_PYTHON_ROOT}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
159+
endif()
160+
161+
# raise an error if the python libs are still not found.
162+
if(NOT EXISTS "${PYTHON_LIBRARY}")
163+
message(FATAL_ERROR "Python libraries not found")
164+
endif()
165+
166+
else()
167+
if(PYTHON_MULTIARCH)
168+
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}")
169+
else()
170+
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}")
171+
endif()
172+
#message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}")
173+
# Probably this needs to be more involved. It would be nice if the config
174+
# information the python interpreter itself gave us were more complete.
175+
find_library(PYTHON_LIBRARY
176+
NAMES "python${PYTHON_LIBRARY_SUFFIX}"
177+
PATHS ${_PYTHON_LIBS_SEARCH}
178+
NO_DEFAULT_PATH)
179+
180+
# If all else fails, just set the name/version and let the linker figure out the path.
181+
if(NOT PYTHON_LIBRARY)
182+
set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX})
183+
endif()
184+
endif()
185+
186+
MARK_AS_ADVANCED(
187+
PYTHON_LIBRARY
188+
PYTHON_INCLUDE_DIR
189+
)
190+
191+
# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
192+
# cache entries because they are meant to specify the location of a single
193+
# library. We now set the variables listed by the documentation for this
194+
# module.
195+
SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
196+
SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
197+
SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
198+
199+
find_package_message(PYTHON
200+
"Found PythonLibs: ${PYTHON_LIBRARY}"
201+
"${PYTHON_EXECUTABLE}${PYTHON_VERSION}")
202+
203+
set(PYTHONLIBS_FOUND TRUE)

0 commit comments

Comments
 (0)