从 CMake 在 Windows/Visual Studio 中以调试模式强制链接到 Python 发布库

Force linking against Python release library in debug mode in Windows/Visual Studio from CMake

我正在使用 Boost Python 为 C++ 库开发 Python 绑定,用于 Linux 和 Windows (Visual Studio)。

在 Windows 中,静态 Boost Python 库依赖于 Python(这是另一个线程的动机,here),所以,在我的 CMake 中我需要做的配置:

if((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") OR APPLE)
     target_link_libraries(my_python_module ${Boost_LIBRARIES})
elseif(WIN32 AND MSVC)
    add_definitions(/DBOOST_PYTHON_STATIC_LIB)
    target_link_libraries(my_python_module ${Boost_LIBRARIES}) #This includes the Boost Python library
    # Even though Boost Python library is included statically, in Windows it has a dependency to the Python library.
    target_link_libraries(my_python_module ${Python_LIBRARIES})
endif()

这在 Linux 中工作正常,但在 Windows 中,它仅在 Release 模式下有效,在 Debug 模式下无效,在这种情况下我总是得到:

LINK : fatal error LNK1104: Can't open file 'python37.lib'

经过一番扯扯,我注意到问题是由 CMake 指示 Visual Studio 到 link 而不是 'python37_d.lib' 而不是 'python37.lib' 在调试模式下。

然而,正如我在 linked issue, the officially provided Boost Python debug 库中所描述的那样,link 针对 Python release 库,不是调试库。因此,解决方案是强制 link 对 Python 发布库,无论构建类型如何。不幸的是,${Python_LIBRARIES} 会根据模式自动设置库,我不想在我的代码中明确指定 python37.lib(因为我可以升级 Python 而且我不想因此而更改我的 CMake 脚本)。

我发现了一些类似的问题 here and here,但这并不能反映我所面临的确切情况。基于这些,我尝试设置:

target_link_libraries(my_python_module optimized ${Python_LIBRARIES})

但这也没有用。所以,问题是:

有没有办法在调试模式下强制使用 Python 发布库 WITHOUT 必须显式设置它并离开 Python CMake包来自动执行它。通过明确我的意思是做:

target_link_libraries(my_python_module python37)

非常感谢您的帮助。

kanstar 评论中建议的 set(Python_FIND_ABI "OFF" "ANY" "ANY") 似乎是执行此操作的正确方法。但是,虽然 Python_FIND_ABI 在 CMake master, it hasn't been released yet in the latest version(撰写本文时为 v3.15.2)中。

同时,还有依赖于CMake版本的解决方案。

CMake 3.12 及以上版本

可以 link 反对 FindPython's Python_LIBRARY_RELEASE, which isn't meant to be part of the module's public interface,但变量设置正确。

cmake_minimum_required (VERSION 3.12)
find_package(Python ..<choose your COMPONENTS; refer to FindPython docs>..)
if(WIN32 AND MSVC)
  target_link_libraries(my_python_module ${Python_LIBRARY_RELEASE})
endif()

CMake 3.0.4 到 3.11

感谢@Phil 的评论,我们可以扩展答案以包括早期的 CMake 版本,这些版本具有 FindPythonLibs 模块,而不是设置 PYTHON_LIBRARY_RELEASE 变量。

cmake_minimum_required (VERSION 3.0)
find_package(PythonLibs ..<refer to FindPythonLibs docs>..)
if(WIN32 AND MSVC)
  target_link_libraries(my_python_module ${PYTHON_LIBRARY_RELEASE})
endif()