View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0014809CMakeCMakepublic2014-03-15 22:042016-06-10 14:31
ReporterNikolaus Demmel 
Assigned ToMatt McCormick 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionmoved 
PlatformDarwinOSMac OS XOS Version10.9
Product VersionCMake 2.8.12.1 
Target VersionFixed in Version 
Summary0014809: FindPythonLibs issue (at least on OS X). Should it use sysconfig?
DescriptionThis is an issue about the way that FindPythonLibs works. In particular on OS X it seems it is quite broken, as I will detail below. I believe this affects not just OS X 10.9, where I ran my tests, but OS X in general. Other systems like Linux seem to also have problems with this module, though I have not run any tests there. I testet this with cmake release 2.8.12.1, but I think the module has not changed significantly since.

There is already quite some discussion downstream at homebrew https://github.com/Homebrew/homebrew/issues/25118, [^] but I will try to summarize everything here:

It seems that currently FindPythonLibs will only find the correct library and headers for the 2.7 version of python that is supplied with OS X. Basically, it always returns `/System/Library/Frameworks/Python.framework/Headers` as headers, and one `/usr/lib/libpython2.7.dylib`, `/usr/lib/libpython2.6.dylib`, or `/usr/lib/libpython2.5.dylib`, depending on which version is searched for. These are the three version shipped with OS X. The homebrew installed versions 2.7 and 3.3 in `/usr/local` are never correctly found. Moreover there is some severe inconsitency. E.g. PYTHONLIBS_VERSION_STRING always returns 2.7.5, no matter what version was found / asked.

FindPythonInterp on the other hand seems always correctly identify the first suitable python executable according to PATH.

In my world, FindPythonLibs should try to find a python executable and ask it for the correct header and lib location (using distutil.sysconfig). However this could be quite a significant change to the current behaviour (in particular PATH would then influence FindPythonLibs), but I think this makes for much more reasonable results overall. If no (suitable) python executable is found, a fallback could be implemented. In my testing project there is a proof of concept implementation of this.

This is in some way related to frameworks. Currently FindPythonLibs uses CMakeFindFrameworks. One problem with homebrew installed pythons is, that their frameworks are in `/usr/local/Library/Frameworks`, which is not among the hardcoded list of framework locations in CMakeFindFrameworks. So a related issue is that there is no way to globally configure the locations where CMakeFindFrameworks looks. However, even if there are no extra pythons installed and we are only considering the ones provided by Apple, FindPythonLibs currently does not work for any version that is not 2.7. The framework issue is circumvented if FindPythonLibs askes the executable which headers / libs to use.

Also, this needs a proper fix and saying "Just supply `cmake -DPYTHON_LIBRARIES=... -DPYTHON_HEADERS=...`" is not a practical solution.
Steps To ReproduceHead over to https://github.com/NikolausDemmel/cmake_python_test [^] and follow the instructions. My output is also linked from there.
Additional InformationThis is just a more or less randomly ordered list of links I came across while looking into this. Some are more or less related. Some might be fixed long since, some might not be.

 - Homebrew issue: https://github.com/Homebrew/homebrew/issues/25118 [^]
 - Testing package: https://github.com/NikolausDemmel/cmake_python_test [^]
 - 2009 list post, saying that `-framework Python` should not be used: www.vtk.org/pipermail/vtk-developers/2009-December/006755.html
 - 2009 issue related to python and frameworks: www.cmake.org/pipermail/cmake/2009-November/033136.html
 - 2012 problem report, which is likely the same issue as this: http://cmake.3232098.n2.nabble.com/FindPythonLibs-Version-selection-on-OS-X-td7182880.html [^]
 - 2011 stackoverflow post about this issue: stackoverflow.com/questions/7660001/cmake-finds-wrong-python-libs
 - 2012 related issue on freebsd: lists.freebsd.org/pipermail/freebsd-python/2012-May/004084.html
 - homebrew issue about this from 2 years ago: https://github.com/Homebrew/homebrew/issues/10393, [^] suggesting among others that there are custom fixes flying around like the following: https://github.com/Homebrew/homebrew/blob/51d054c/Library/Formula/vtk.rb#L31-49, [^] or https://github.com/Homebrew/homebrew/blob/51d054c/Library/Formula/opencv.rb#L50-73 [^]
 
As for other related CMake tickets:

 - There is some recent activity around FindPythonInterp and FindPythonLibs consistency, however IMHO this will not solve out issue here: http://www.itk.org/Bug/view.php?id=13794 [^]
 - Another issue marked as duplicate of the above, however I think it will also not be fixed by the above: http://www.itk.org/Bug/view.php?id=10077 [^]
 - Something about CMAKE_PREFIX_PATH: http://www.itk.org/Bug/view.php?id=12133 [^]
 - An issue indicating that something similar had already been suggested as far back as 2006, but never went anywhere: http://www.itk.org/Bug/view.php?id=2257 [^]
TagsNo tags attached.
Attached Files

 Relationships
related to 0014810closedKitware Robot Make CMakeFindFrameworks module configurable 

  Notes
(0035416)
Brad King (manager)
2014-03-17 09:00

W.r.t. the relationship with issue 0014810, the FindPythonLibs module should be refactored to avoid using the CMakeFindFrameworks module altogether.
(0035484)
Matthew McCormick (reporter)
2014-03-24 11:57

Please try with CMake master.

<quote>
- There is some recent activity around FindPythonInterp and FindPythonLibs consistency, however IMHO this will not solve out issue here: http://www.itk.org/Bug/view.php?id=13794 [^] [^]
</quote>

Why does it not address this issue?
(0035550)
Nikolaus Demmel (reporter)
2014-03-28 08:33

@brad.king: thanks, for the note on CMakeFindFrameworks. To me the relation between some of the functionality of built-ins and modules in CMake is not transparent.

@mccormic: AFAICT the changes in 0013794 do not change the way the libraries and header files are actually found, but rather only the different version strings looked up by default. In my tests, I in particular try the case where I pass the exact desired version string to FindPythonLibs, and the result is wrong for most cases.

I just tried with master, and the results are much the same. Are all proposed changes from 0013794 merge into master?
(0035558)
Matthew McCormick (reporter)
2014-03-28 14:08

Thanks for the information.

Yes, master has the changes from 0013794. Could a gist with the results from master please be created? I do not have a Mac OS 10.9 to test on.
(0035618)
Nikolaus Demmel (reporter)
2014-04-02 06:32
edited on: 2014-04-02 06:35

I added the output for my test scripts for CMake master on my machine to the gist:
https://gist.github.com/NikolausDemmel/9392464#file-findpythonlibs-master [^]

I would be surprised if the results are signigicantly different on other OS X versions. Just to reiterate, the main problem lies with finding the homebrew python version ("brewed") over the one provided by apple ("system") and it also manifests when looking for older versions like 2.6 or 2.5 (both provided by apple). Finding the brewed python 3 is also problematic.

(0035852)
Nikolaus Demmel (reporter)
2014-05-12 13:12

I have rewritten the FindPythonLibs module to look for an interpreter, check its version and use distutils.sysconfig to determine library and header paths.

It does probably not cover many corner cases and I only tested it locally (OS X Mavericks), and not thoroughly at all.

However, it does seem to cover all cases from my test modules.

Maybe people can have a look at it: https://github.com/NikolausDemmel/CMake/pull/2 [^]

On OS X you can also install it with Homebrew: `brew install nikolausdemmel/devel/cmake`.
(0035853)
Brad King (manager)
2014-05-12 13:15

Re 0014809:0035852: The FindPythonLibs module must be able to work when cross-compiling. In this case the interpreter might not be able to run on the host system.
(0035854)
Nikolaus Demmel (reporter)
2014-05-12 13:20

@brad.king: I understand that. But maybe it can be somehow detected if it is desirable to find python libs from the interpreter or the current way.

For me it is impossible to know what the semantics of the module should be in all possible scenarios, so I can only provide a suggestion+implementation of how I would want it to work for some of the scenarios that I understand at this point.

I'm not saying this is by any means ready to replace the current module.
(0035855)
Nikolaus Demmel (reporter)
2014-05-12 13:59

My goal is to determine changing the module's semantics to the suggest one is acceptable in principle, assuming that all cases are covered (e.g. reverting to current behaviour for cross compilation etc...).

This more or less working module (at least for some cases) is supposed to be a proof of concept that can be evaluated.
(0035856)
Brad King (manager)
2014-05-12 14:05

Re 0014809:0035855: Using the interpreter when it can run is a reasonable proposal. However, I'd like to know why the current approach cannot work.

Your goal is to prefer the homebrew python over the Apple one. What about your environment is supposed to tell CMake to prefer one over the other? Why does that work for finding the interpreter and not the libs?
(0035857)
Nikolaus Demmel (reporter)
2014-05-12 14:40

There are multiple issues: the most prominent one is as you say using brewed python over system python. That gets configured via the user's PATH variable (first 'python' executable) and gets picked up by PythonInterp.

However, even without homebrew the current FindPythonLib fails for anything but python 2.7 (or rather the most recent one installed by apple), at least on Mavericks.

I find using the user's PATH a reasonable point of configuration for choosing the python version. If executing the interpreter does not work (cross compilation), another fallback could be heuristics based on the executable path.

Do you have an alternative point of configuration in mind for selecting the right python version?
(0035858)
Brad King (manager)
2014-05-12 14:49

If you set CMAKE_PREFIX_PATH in your environment then CMake will prefer the given prefixes first. That is one way to tell CMake to prefer homebrew over system packages.

PATH tells the shell. CMAKE_PREFIX_PATH tells CMake.
(0035859)
Nikolaus Demmel (reporter)
2014-05-12 15:04

requiring homebrew users to set an environment variable sounds reasonable to me, something like setting CMAKE_PREFIX_PATH to /use/local.

I'm not sure how well it would work, esp. in the light of Frameworks. Certainly not without fixing the current implementation of the module. I don't know how to implement this generically without heuristics based on the current module.

And there is still the possible discrepancy with PythonInterp (which listens to PATH).
(0035860)
Brad King (manager)
2014-05-12 16:31

Re 0014809:0035859: I'm saying that CMAKE_PREFIX_PATH is a current feature that should already work. All the find_* commands prefer the named prefixes over everything else unless they are told at their invocation site not to do so. This includes find_program, so for FindPythonInterp the CMAKE_PREFIX_PATH should be used before PATH.
(0035861)
Nikolaus Demmel (reporter)
2014-05-12 18:49

Aha, interesting. Setting CMAKE_PREFIX_PATH to /usr/local does seem to indeed cause FindPythonInterp to find the homebrew python even if it is not on PATH. That's good.

Note that if FindPythonLibs is changed to rely on finding the interpreter and querying it for it's header/libs (whenever that is possible) this means that it is configurable by both CMAKE_PREFIX_PATH and PATH, where the former takes precedence as it should.

Setting CMAKE_PREFIX_PATH to /usr/local does not seem to have much of an effect on the result of FindPythonLibs with the current module implementation though. Does someone have the ressources/skills to look into this more? A first step would be to make sure FindPythonLibs works on vanilla OS X (no homebrew) for all versions (2.5, 2.6, 2.7). The second step would be making sure a custom install (including homebrew) can be picked up either from PATH, from CMAKE_PREFIX_PATH, or both.

I still believe looking for the interpreter is more reliable, if available. Are there scenarios where there is a python lib installed, but no interpreter? (regardless of whether it can be executed)
(0035862)
Matthew McCormick (reporter)
2014-05-12 19:22

> Are there scenarios where there is a python lib installed, but no interpreter?

Yes, last time we tried to call FindPythonInterp in FindPythonLibs, it broke Fedora builds:

  https://bugzilla.redhat.com/show_bug.cgi?id=1072964 [^]

The have both 2.7 libraries and 3.X libraries, but only the python3 interpreter.
(0035863)
Nikolaus Demmel (reporter)
2014-05-12 19:29

From that bug report it is hard to tell what was really going on. Note that my proof of concept does not invoke FindPythonInterp, but rather uses similar logic and call find_program multiple times until a suitable version is found.

With that a fallback that uses find_library and find_path on some default directories seems like a reasonable addition when no suitable interpreter is found.

Is there some form of automated testing done for this module such that different setups/OS can be tested with reasonable effort?
(0035864)
Matthew McCormick (reporter)
2014-05-12 19:53

Tests / reproducible environments here would be very nice :-)
(0035866)
Nikolaus Demmel (reporter)
2014-05-13 07:04

What should be the next steps here?
(0035867)
Brad King (manager)
2014-05-13 08:33

Re 0014809:0035861: The problem for FindPythonLibs is that find_library searches for frameworks first by default on OS X, and then non-frameworks. Since they are two different paradigms, that distinction is the highest priority setting. The CMAKE_FIND_FRAMEWORK variable can be set to LAST or NEVER to tell CMake to prefer normal libraries as explained in the find_library docs:

 http://www.cmake.org/cmake/help/v3.0/command/find_library.html [^]
(0036254)
David Brooks (reporter)
2014-06-26 00:55

FindPythonLibs under OS/X appears to correctly find a homebrew Python if ~/Library/Frameworks contains a symbolic link to the homebrew Python framework.

Should homebrew (optionally) maintain this link?
(0036257)
Nikolaus Demmel (reporter)
2014-06-26 06:32

As noted in the homebrew thread, homebrew makes a promise to not modify files outside of the homebrew prefix (/usr/local usually). Moreover, creating such a link is a workaround only for the current python version (2.7). The module will still break if you look for other versions.
(0039008)
Wenzel Jakob (reporter)
2015-07-01 17:44

I am having the same issue with Brew and CMake 3.2.3. With a brewed version of Python 3.4, the following CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6)
find_package(PythonLibs 3 REQUIRED)

fails with

Make Error at /Applications/CMake.app/Contents/share/cmake-3.2/Modules/FindPackageHandleStandardArgs.cmake:138 (message):
  Could NOT find PythonLibs: Found unsuitable version "2.7.6", but required
  is at least "3" (found PYTHON_LIBRARY-NOTFOUND)

I've searched for a solution for a long time -- I am surprised that this is still broken!
(0039009)
Wenzel Jakob (reporter)
2015-07-01 18:03

A follow-up:

The above CMake command also fails when the official Python 3.4.x .pkg file from python.org [1] is installed, rather than the custom brew build.

It appears that find_package(PythonLib) support for Python 3.x is generally broken on OSX.

[1] https://www.python.org/downloads/release/python-343/ [^]
(0039013)
Matthew McCormick (reporter)
2015-07-02 11:36

Here is a patch that will address the python.org test case given above:

  http://www.cmake.org/gitweb?p=stage/cmake.git;a=commit;h=462a59e01b45060ba5ad8a03d89fc96654dfe529 [^]
(0039017)
Nikolaus Demmel (reporter)
2015-07-05 11:15

@Wenzel Jakob: I personally use a custom homebrew formula for cmake to be found at

    https://github.com/NikolausDemmel/homebrew-devel/blob/master/cmake.rb [^]

It applies a patch to FindPythonLibs to use the sysconfig to locate the libaries matching the python executable. See also:

    https://github.com/NikolausDemmel/CMake/pull/5 [^]

I don't update it often these days though.
(0039026)
Brad King (manager)
2015-07-07 09:48

The patch linked in 0014809:0039013 has been revised and merged as:

 FindPythonLibs: Find the python.org libraries
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=02fd0356 [^]
(0039027)
Brad King (manager)
2015-07-07 09:49

Re 0014809:0039017: One problem with using sysconfig is that when cross-compiling one may not be able to run the python executable. It could be added as an optional step when the executable can run.

Ideally we should have a combined module that finds both the executable and libraries together. See discussion here:

 FindPython.cmake alternative for FindPythonInterp.cmake and FindPythonLibs.cmake
 http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/13528/focus=13535 [^]
(0039029)
Nikolaus Demmel (reporter)
2015-07-07 18:10
edited on: 2015-07-07 18:11

> One problem with using sysconfig is that when cross-compiling one may not be able to run the python executable. It could be added as an optional step when the executable can run.

Agreed.

> Ideally we should have a combined module that finds both the executable and libraries together. See discussion here:

Absolutely.

Unfortunately I have 0 ressources to work on this currently and my customized variant installed via homebrew works well for my current needs.

(0039236)
Jean-Christophe Fillion-Robin (reporter)
2015-08-04 21:11

Here is a comment from Pat Marion related to use of FindPythonLibs.cmake with HomeBrew.

Copied from https://github.com/commontk/PythonQt/issues/24#issuecomment-127639573 [^]

8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----
I think the issue is with CMake's FindPythonLibs.cmake script. It finds the correct Python interpreter but not the correct lib and headers. In order to correctly find homebrew python on mac, I use cmake code like this:

(note, this isn't totally general, but it works well enough for me for python 2.7):

if(APPLE)
  find_program(PYTHON_CONFIG_EXECUTABLE python-config)
  if (NOT PYTHON_CONFIG_EXECUTABLE)
    message(SEND_ERROR "python-config executable not found, but python is required.")
  endif()
  # using "python-config --prefix" so that cmake always uses the python that is
  # in the user's path, this is a fix for homebrew on Mac:
  # https://github.com/Homebrew/homebrew/issues/25118 [^]
  execute_process(COMMAND ${PYTHON_CONFIG_EXECUTABLE} --prefix OUTPUT_VARIABLE python_prefix OUTPUT_STRIP_TRAILING_WHITESPACE)
  set(PYTHON_INCLUDE_DIR ${python_prefix}/include/python2.7)
  set(PYTHON_LIBRARY ${python_prefix}/lib/libpython2.7${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()

find_package(PythonLibs 2.7 REQUIRED)
8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----
(0039238)
Wenzel Jakob (reporter)
2015-08-05 05:06
edited on: 2015-08-05 05:06

Hi Jean-Christophe,

the main issue here is about finding an arbitrary brewed Python version in a portable way (especially 3.x, since only 2.7 is available by default on OSX). It's obviously always possible with some custom lines of code, but it would be nice if CMake would just pick it up on its own using the default FindPackage syntax.

Wenzel

(0039267)
Dave Yost (reporter)
2015-08-11 21:14

I have the same problem when trying to find the boost I want, which is in
 /usr/local/boost/1.57.0/
or the clang clang I want, in
 /usr/local/llvm/3.6.2/

It seems to me that if all of the path environment variables are set right so that a package can be found, then cmake should be able to find the package and work properly. This is not the case. For example
 CPATH=/usr/local/boost/1.57.0/include
should be enough to tell cmake were to find boost. That is, cmake should look first at CPATH when looking for a package.

On CentOS, where the installed compiler is ancient, we have to use a more recent, non-system, compiler install to get our work done. (See the clang example above.) But because of this bug the llvm sources simply won't build in this situation.
(0039955)
David Brooks (reporter)
2015-12-04 18:00

Replacing the start of FindPythonLibs.cmake with the following works with CMake 3.4.0 and finds the appropriate library when the version of Python is changed using pyenv. Tested under OS/X with HomeBrew.

# Use the executable's path as a hint
set(_Python_LIBRARY_PATH_HINT)
if(PYTHON_EXECUTABLE)
  execute_process(
    COMMAND ${PYTHON_EXECUTABLE} -c "if True:
        from distutils import sysconfig
        from os.path import sep
        print(sysconfig.PREFIX)
        "
    OUTPUT_VARIABLE _Python_PREFIX
    OUTPUT_STRIP_TRAILING_WHITESPACE)
  if(_Python_PREFIX)
    if(WIN32)
      set(_Python_LIBRARY_PATH_HINT ${_Python_PREFIX}/libs)
    else()
      set(_Python_LIBRARY_PATH_HINT ${_Python_PREFIX}/lib)
    endif()
  endif()
  unset(_Python_PREFIX)
endif()
(0042507)
Kitware Robot (administrator)
2016-06-10 14:29

Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.

 Issue History
Date Modified Username Field Change
2014-03-15 22:04 Nikolaus Demmel New Issue
2014-03-17 08:58 Brad King Assigned To => Matt McCormick
2014-03-17 08:58 Brad King Status new => assigned
2014-03-17 08:58 Brad King Relationship added related to 0014810
2014-03-17 09:00 Brad King Note Added: 0035416
2014-03-24 11:57 Matthew McCormick Note Added: 0035484
2014-03-28 08:33 Nikolaus Demmel Note Added: 0035550
2014-03-28 14:08 Matthew McCormick Note Added: 0035558
2014-04-02 06:32 Nikolaus Demmel Note Added: 0035618
2014-04-02 06:35 Nikolaus Demmel Note Edited: 0035618
2014-05-12 13:12 Nikolaus Demmel Note Added: 0035852
2014-05-12 13:15 Brad King Note Added: 0035853
2014-05-12 13:20 Nikolaus Demmel Note Added: 0035854
2014-05-12 13:59 Nikolaus Demmel Note Added: 0035855
2014-05-12 14:05 Brad King Note Added: 0035856
2014-05-12 14:40 Nikolaus Demmel Note Added: 0035857
2014-05-12 14:49 Brad King Note Added: 0035858
2014-05-12 15:04 Nikolaus Demmel Note Added: 0035859
2014-05-12 16:31 Brad King Note Added: 0035860
2014-05-12 18:49 Nikolaus Demmel Note Added: 0035861
2014-05-12 19:22 Matthew McCormick Note Added: 0035862
2014-05-12 19:29 Nikolaus Demmel Note Added: 0035863
2014-05-12 19:53 Matthew McCormick Note Added: 0035864
2014-05-13 07:04 Nikolaus Demmel Note Added: 0035866
2014-05-13 08:33 Brad King Note Added: 0035867
2014-06-26 00:55 David Brooks Note Added: 0036254
2014-06-26 06:32 Nikolaus Demmel Note Added: 0036257
2015-07-01 17:44 Wenzel Jakob Note Added: 0039008
2015-07-01 18:03 Wenzel Jakob Note Added: 0039009
2015-07-02 11:36 Matthew McCormick Note Added: 0039013
2015-07-05 11:15 Nikolaus Demmel Note Added: 0039017
2015-07-07 09:48 Brad King Note Added: 0039026
2015-07-07 09:49 Brad King Note Added: 0039027
2015-07-07 18:10 Nikolaus Demmel Note Added: 0039029
2015-07-07 18:11 Nikolaus Demmel Note Edited: 0039029
2015-08-04 21:11 Jean-Christophe Fillion-Robin Note Added: 0039236
2015-08-05 05:06 Wenzel Jakob Note Added: 0039238
2015-08-05 05:06 Wenzel Jakob Note Edited: 0039238
2015-08-11 21:14 Dave Yost Note Added: 0039267
2015-12-04 18:00 David Brooks Note Added: 0039955
2016-06-10 14:29 Kitware Robot Note Added: 0042507
2016-06-10 14:29 Kitware Robot Status assigned => resolved
2016-06-10 14:29 Kitware Robot Resolution open => moved
2016-06-10 14:31 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team