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

时间:2019-06-27 21:06:46

标签: python cmake visual-studio-2017 boost-python

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

在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在调试中链接到 'python37_d.lib' 而不是 'python37.lib' 引起的模式。

但是,正如我在linked issue中所述,officially provided Boost Python debug 库是与Python release 库链接的,而不是调试一个。因此,解决方案将是针对构建版本强制使用针对Python发布库的链接。不幸的是, ${Python_LIBRARIES} 会根据模式自动设置库,并且我不想在代码中显式指定python37.lib(因为我可以升级Python,但我不想因此必须更改我的CMake脚本。)

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

target_link_libraries(my_python_module optimized ${Python_LIBRARIES})

但是那也不起作用。因此,问题是:

是否有一种方法可以强制在调试模式 WITHOUT 中使用Python发布库,而不必明确设置它,而让Python CMake软件包自动执行它。明确地说,我的意思是:

target_link_libraries(my_python_module python37)

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

似乎kanstar评论中建议的set(Python_FIND_ABI "OFF" "ANY" "ANY")是正确的方法。但是,尽管Python_FIND_ABI在CMake master中,但尚未在latest version中发布(截至撰写本文时为v3.15.2)。

同时,有些解决方案取决于CMake版本。

CMake 3.12及更高版本

可以链接到FindPythonPython_LIBRARY_RELEASE,这并不意味着它是模块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的评论,我们可以扩展答案,以包括具有FindPythonLibs模块的早期CMake版本,该模块改为设置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()