Finding the correct Python framework with cmake - python

I am using the macports version of python on a Snow Leopard computer, and using cmake to build a cross-platform extension to it. I search for the python interpreter and libraries on the system using the following commands in CMakeLists.txt
include(FindPythonInterp)
include(FindPythonLibs )
However, while cmake identified the correct interpreter in /opt/local/bin, it tries to link against the wrong framework - namely the system Python framework.
-- Found PythonInterp: /opt/local/bin/python2.6
-- Found PythonLibs: -framework Python
And this causes the following runtime error
Fatal Python error: Interpreter not initialized (version mismatch?)
As soon as I replace -framework Python with /opt/local/Library/Frameworks/Python.framework/Python things seem to work as expected.
How can I make cmake link against the correct Python framework found in
/opt/local/Library/Frameworks/Python.framework/Python
rather than the system one in
/System/Library/Frameworks/Python.framework/Python
?

Adding the following in ~/.bash_profile
export DYLD_FRAMEWORK_PATH=/opt/local/Library/Frameworks
fixes the problem at least temporarily. Apparently, this inconsistency between the python interpreter and the python framework used by cmake is a bug that should be hopefully fixed in the new version.

I am not intimately familiar with CMake, but with the Apple version of gcc/ld, you can pass the -F flag to specify a new framework search path. For example, -F/opt/local/Library/Frameworks will search in MacPorts' frameworks directory. If you can specify such a flag using CMake, it may solve your problem.

Related

CMake doesn't find locally built Python

I'd like to include a locally built version of Python into a CMake project. However, I don't manage to point it to the right direction (at least not fully). Here is my stripped down CMake file:
cmake_minimum_required(VERSION 3.16)
project(Question)
set(PYTHON_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/Python-3.6.10)
set(PYTHON_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/Python-3.6.10/Include)
set(PYTHON_LIBRARIES ${CMAKE_CURRENT_LIST_DIR}/Python-3.6.10)
set(PYTHON_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/Python-3.6.10/Include)
set(Python3_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/Python-3.6.10)
set(Python3_FIND_STRATEGY "LOCATION")
find_package(Python3 3.6 EXACT COMPONENTS Development REQUIRED)
I tried different combinations of the flags and variables given here. The closest I could get, was the error message
Could NOT find Python3 (missing: Python3_INCLUDE_DIRS Development) (found suitable exact version "3.6")
It seems to find Python but there is still something missing. Do I need to compile Python with special parameters? I didn't install the compiled Python with the altinstall script, because I don't see the point in it, when I just want to use it for one purpose.
I'm using CMake 3.16.3 - if I don't request an exact version, Python 3.8, that is installed on my system, is found without any problems.
Thanks and best regards!

Cmake GUI could not find boost (missing: system python3) (found version "1.72.0"), on Windows 10

I am trying to install PyOpenPose on Windows 10, using Cmake GUI. It requires OpenCV so I downloaded the prebuild OpenCV for Windows. Then I cmake the repository, import the OpenCV directory, everything is ok, until it required Boost. I downloaded the latest Boost version 1.72.0 and copy it to C:\boost\boost_1_72_0, since the installation manual tells me to do that to get CMake to detect the Boost. But its detection was like this:
By reading it I guessed Cmake has detected the Boost but it could not detect the python, the missing is system python3 and the Boost 1.72.0 has been found. So I add a DPYTHON_EXECUTABLE and set its path to C:\Users\abc\AppData\Local\Programs\Python\Python38\python.exe but the problem still remains.
Those DBOOST_LIBRARYDIR and DBOOST_ROOT were added by me. Cmake exports the same errors even without those arguments.
So that I am stuck here.

is compiled python file under debian is compatible with ubuntu

I'm using nuitka to compile my python codes. I use --module option to import my code inside other python files:
nuitka --module --recurse-none file.py
Output: file.so
If I don't need to import the code and just need to run on terminal, I'm following regular compiling process:
nuitka --recurse-none file.py
Output: file.exe
I'm compiling these files under Debian and they work without a problem under Debian. When I move these files to an Ubuntu system, I sometimes get Segmentation Fault errors. Is it because a compiled python code under Debian is not compatible with Ubuntu or am I doing a personal mistake (like missing library etc.)
As answered by abarnert, if you want to make your executable independent from the specific python installation on your device, you need to use the --standalone option.
You can check that info in the Nuitka Manual
Dynamic Linking
From the docs,
It translates the Python into a C level program that then uses "libpython" to execute in the same way as CPython does.
Do you have libpython installed and pointing to the same version as the one you are compiling from? Example, on arch:
$ whereis libpython
libpython: /usr/lib/libpython3.so
Shows I have libpython installed and belonging to python 3.x (notice 3 at end of path).
Static linking.
The other way to do is I guess as suggested by others, i.e, using --standalone option. This should avoid the need of libpython
I'm kind of suspicious that you have your hint right in your question. *.exe is generally a Windows executable, while *.so is a UNIX/Linux reloadable module. Without delving into the manual very far, I notice that in one example you have --module and you get, sure enough, a Linux module. In the other case, you don't. And you don't.

I have 2 versions of python installed, but cmake is using older version. How do I force cmake to use the newer version?

I have 2 versions of python installed, but cmake is using older version. How do I force cmake to use the newer version?
You may try either of these depending on what you need:
For CMake >= 3.12
According to the changelog:
New "FindPython3" and "FindPython2" modules, as well as a new
"FindPython" module, have been added to provide a new way to locate
python environments.
find_package(Python COMPONENTS Interpreter Development)
Docs:
This module looks preferably for version 3 of Python. If not found,
version 2 is searched. To manage concurrent versions 3 and 2 of
Python, use FindPython3 and FindPython2 modules rather than this one.
For CMake < 3.12
Docs:
find_package(PythonInterp 2.7 REQUIRED)
find_package(PythonLibs 2.7 REQUIRED)
Try to add -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python2.7
It might be a path problem?
Also could specify the path to your python library,use your version that you want:
cmake -DPYTHON_LIBRARIES=/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib .
I had a similar problem, and resolved it using Paul's answer as a hint. I needed to use python2.7 to compile an older library, but cmake keeps picking up my python3.2 libraries (and executable).
First, I ran cmake with default options, then edited the CMakeCache.txt file which it generated. I did it this way primarily because I didn't know the proper -D... incantations to cause cmake to get the python library and include paths, etc right in the first place.
In my CmakeCache.txt, I found lines like this
Path to a program
PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python
Path to a directory
PYTHON_INCLUDE_DIR:PATH=/usr/include/python3.2
Path to a library
PYTHON_LIBRARY:FILEPATH=/usr/lib/libpython3.2.so
And replaced every occurrence of python3.2 with python2.7. I also had to rename the PYTHON_EXECUTABLE to use python2.7, since python is a symlink to python3.2 on my system.
Then I reran cmake. Because it prefers its cached values to actually looking for the libraries, this should work in all cases. At least, it did in mine.
I use anaconda(python 2.7.8) as well as python 2.7.6.
I tried -DPYTHON_EXECUTABLE:FILEPATH=$ANACONDA_HOME/bin, but version 1.4 found (weird:).
My solution is changing it to PYTHON_EXECUTABLE:
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TIFF=ON \
-DPYTHON_LIBRARY=$ANACONDA_HOME/lib/libpython2.7.so \
-DPYTHON_INCLUDE_DIR=$ANACONDA_HOME/include/python2.7/ \
-DPYTHON_EXECUTABLE=$ANACONDA_HOME/bin/python
My use case was a rather large project in which C++ classes were made available to Python scripts via Boost.Python. After having fought the various quirks of CMake's Python interpreter and library detection, I finally gave up and rolled my own. My approach is based on a slightly after-edited version of the python-config script that is sometimes (but not always!) put into a newly created virtual environment (see this SO post on pyvenv for these issues, but I digress). This script is invoked by a small CMake snippet pyconfig.cmake. Both are freely available from the GitHub repo cmake-python-config.
Warning: The scripts assume that you have a Python 3 interpreter in your PATH. Detection of Python 2 is not attempted. The scripts do not attempt to find all installed versions of Python3 either.

Building 64bit libpython27.a using cygwin, dlltool

I'm trying to build a python extension DLL on a 64bit Win7 machine using cygwin (as cygwin only run as 32bit process, this is actually cross-compiling).
I created libpython27.a myself from python27.dll using dlltool (as explained, for example, here), but the build fail during the linker phase saying
skipping incompatible c:\Python27\libs/libpython27.a when searching for -lpython27
This is exactly the error reported here (where the guy ended up moving to MSVC compiler...).
More info:
- Active Python 2.7.2, win64, x64
- latest version of cygwin, using the /usr/bin/x86_64-w64-mingw32-g++.exe compiler
Does anyone know if this is supported?
Is there way to use dlltool which I miss here?
(I did found here the guidance to use
dlltool --as-flags=--64 -m i386:x86-64 -k -l libpython27.a -d python.def
but when doing so I got "invalid bfd target" error from dlltool)
Thanks!
Update: I believe it can be done because Enthought python contains such a file. I would like to create one for the more common distributions which don't contain it.
The problem is that you are using the 32 bit dlltool. Probably in C:\MinGW\bin instead of C:\MinGW64\bin. You can change your path, or run the 64 bit tool specifically as such:
C:\MinGW64\bin\dlltool -v --dllname python27.dll --def python27.def --output-lib libpython27.a
I'm not sure how helpful you find this, but at the bottom of the page you linked to there's a link to here - Where it says:
Do not use MinGW-w64. As you will notice, the MinGW import library for
Python (e.g. libpython27.a) is omitted from the AMD64 version of
Python. This is deliberate. Do not try to make one using dlltool.
There is no official MinGW-w64 release yet, it is still in "beta" and
considered unstable, although you can get a 64-bit build from e.g.
TDM-GCC. There have also been issues with the mingw runtime
conflicting with the MSVC runtime; this can happen from places you
don't expect, such as inside runtime libraries for g++ or gfortran. To
stay on the safe side, avoid MinGW-w64 for now.

Categories