强制CMake/VisualStudio使用Boost.Python的静态库

6
我目前正在Windows平台上(使用Intel编译器)尝试构建一个在UNIX上使用CMake编译非常成功的大型项目。以下是我遇到问题的简化示例。
运行以下使用Boost.Python的简单代码示例:
#include <iostream>
#include <Python.h>
#include <boost/python.hpp>

int main()
{
    std::string python_home = "C:\\softs\\python\\2.7.9\\64";
    char* python_home_char = new char[python_home.length() + 1];
    strcpy(python_home_char, python_home.c_str());
    Py_SetPythonHome(python_home_char);
    Py_Initialize();

    boost::python::object pyobj_main = boost::python::import("__main__");
    boost::python::object glob = pyobj_main.attr("__dict__");
    boost::python::exec("print \"Hello from Python\"", glob, glob);

    Py_Finalize();

    return 0;
}

执行代码时,我遇到了以下错误信息:
“程序无法启动,因为您的计算机缺少boost_python-iw-mt-1_57.dll文件。尝试重新安装程序以解决此问题。”
请注意,如果我删除代码末尾的3行 boost :: python :: *** ,则不会出现错误。此外,如果我使用Boost.Thread编译以下示例(在我看来,它也使用库(而不是仅头文件),对吗?),则不会出现任何错误。
#include <iostream>
#include <boost/thread.hpp>

boost::mutex mutex_hello;
void hello(unsigned long int thread_number)
{
    boost::mutex::scoped_lock lock_hello(mutex_hello);
    std::cout << "Hello from thread " << thread_number << std::endl;
}

int main()
{
    boost::thread_group group;
    for(unsigned long int i = 0; i < 9; ++i)
        group.create_thread(boost::bind(hello, i + 1));
    group.join_all();

    return 0;
}

实际上,我不想使用共享库,我希望我的可执行文件尽可能地静态

我使用以下CMake文件构建此代码:

cmake_minimum_required(VERSION 2.8.9)

# Project
project(TestBoost)
enable_language(C)
enable_language(CXX)
enable_language(Fortran)

# Compiler info
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
    set(CompilerName "${CMAKE_CXX_COMPILER_ID}")
    set(CompilerVersion "${CMAKE_CXX_COMPILER_VERSION}")
    if(CMAKE_CL_64)
        set(CompilerArch "64")
    else()
        set(CompilerArch "32")
    endif()
endif()
string(TOLOWER "${CompilerName}" CompilerName)
if("${CompilerVersion}" MATCHES "([0-9]+\\.[0-9]+\\.[0-9]+)\\..*")
    string(REGEX REPLACE "([0-9]+\\.[0-9]+\\.[0-9]+)\\..*" "\\1" CompilerVersion "${CompilerVersion}")
endif()

# Libs
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})

# Intel
if(CompilerName STREQUAL "intel")
    string(REGEX REPLACE "(.*)/bin/.*" "\\1" IntelPath "${CMAKE_C_COMPILER}")
    if(CompilerArch STREQUAL "32")
        set(IntelArchStr "ia32")
    elseif(CompilerArch STREQUAL "64")
        set(IntelArchStr "intel64")
    endif()
    set(Compiler_LIBRARY_DIRS "${IntelPath}/compiler/lib/${IntelArchStr}")
endif()

# Boost
set(BOOST_ROOT "C:/softs/boost/1.57.0/${CompilerArch}/${CompilerName}/${CompilerVersion}")
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_NO_SYSTEM_PATHS ON)
set(Boost_ADDITIONAL_VERSIONS "1.57.0" "1.57")
find_package(Boost 1.57.0 REQUIRED COMPONENTS thread system filesystem python)

# Python
set(PythonPath C:/softs/python/2.7.9/${CompilerArch})
set(Python_INCLUDE_DIRS ${PythonPath}/include)
set(Python_LIBRARY_DIRS ${PythonPath}/libs)
set(Python_LIBRARIES python27)

# Executable
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${Python_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS} ${Python_LIBRARY_DIRS} ${Compiler_LIBRARY_DIRS})
add_executable(test_boost test_boost.cpp)
target_link_libraries(test_boost ${Boost_LIBRARIES} ${Python_LIBRARIES})

我使用初始条目 CMAKE_GENERATOR_TOOLSET 设置为 Intel C++ Compiler XE 14.0 并将英特尔编译器指定为本机编译器来运行此 CMake 脚本。在运行 CMake 时,我没有任何错误或警告(请参见下面的日志)。这会生成一个名为 TestBoost.sln 的文件。在 Visual Studio Professional 2013 中加载后,我将编译类型更改为 Release,并修改目标 test_boost 的链接器选项以添加 /NODEFAULTLIB:LIBCMT(这是由于 CMake 中的错误而进行的解决方法)。然后我编译,没有任何错误。
CMake 日志如下:
The C compiler identification is Intel 14.0.4.20140805
The CXX compiler identification is Intel 14.0.4.20140805
Check for working C compiler using: Visual Studio 12 2013 Win64
Check for working C compiler using: Visual Studio 12 2013 Win64 -- works
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working CXX compiler using: Visual Studio 12 2013 Win64
Check for working CXX compiler using: Visual Studio 12 2013 Win64 -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
The Fortran compiler identification is Intel
Check for working Fortran compiler using: Visual Studio 12 2013 Win64
Check for working Fortran compiler using: Visual Studio 12 2013 Win64  -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Determine Intel Fortran Compiler Implicit Link Path
Determine Intel Fortran Compiler Implicit Link Path -- done
Checking whether C:/Program Files (x86)/Intel/Composer XE 2013 SP1/bin/intel64/icl.exe supports Fortran 90
Checking whether C:/Program Files (x86)/Intel/Composer XE 2013 SP1/bin/intel64/icl.exe supports Fortran 90 -- yes
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:515 ] _boost_TEST_VERSIONS = 1.57.0;1.57
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:517 ] Boost_USE_MULTITHREADED = TRUE
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:519 ] Boost_USE_STATIC_LIBS = ON
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:521 ] Boost_USE_STATIC_RUNTIME = 
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:523 ] Boost_ADDITIONAL_VERSIONS = 1.57.0;1.57
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:525 ] Boost_NO_SYSTEM_PATHS = ON
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:577 ] Declared as CMake or Environmental Variables:
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:579 ]   BOOST_ROOT = C:/softs/boost/1.57.0/64/intel/14.0.4
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:581 ]   BOOST_INCLUDEDIR = 
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:583 ]   BOOST_LIBRARYDIR = 
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:585 ] _boost_TEST_VERSIONS = 1.57.0;1.57
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:654 ] Include debugging info:
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:656 ]   _boost_INCLUDE_SEARCH_DIRS = C:/softs/boost/1.57.0/64/intel/14.0.4/include;C:/softs/boost/1.57.0/64/intel/14.0.4;NO_CMAKE_SYSTEM_PATH
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:658 ]   _boost_PATH_SUFFIXES = boost-1_57_0;boost_1_57_0;boost/boost-1_57_0;boost/boost_1_57_0;boost-1_57;boost_1_57;boost/boost-1_57;boost/boost_1_57
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:678 ] location of version.hpp: C:/softs/boost/1.57.0/64/intel/14.0.4/include/boost-1_57/boost/version.hpp
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:702 ] version.hpp reveals boost 1.57.0
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:787 ] guessed _boost_COMPILER = -iw
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:797 ] _boost_MULTITHREADED = -mt
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:840 ] _boost_RELEASE_ABI_TAG = -
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:842 ] _boost_DEBUG_ABI_TAG = -gd
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:890 ] _boost_LIBRARY_SEARCH_DIRS = C:/softs/boost/1.57.0/64/intel/14.0.4/lib;C:/softs/boost/1.57.0/64/intel/14.0.4/stage/lib;C:/softs/boost/1.57.0/64/intel/14.0.4/include/boost-1_57/lib;C:/softs/boost/1.57.0/64/intel/14.0.4/include/boost-1_57/../lib;C:/softs/boost/1.57.0/64/intel/14.0.4/include/boost-1_57/stage/lib;NO_CMAKE_SYSTEM_PATH
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1001 ] Searching for THREAD_LIBRARY_RELEASE: libboost_thread-iw-mt-1_57;libboost_thread-iw-mt;libboost_thread-mt-1_57;libboost_thread-mt;libboost_thread;libboost_thread-iw-mt-s-1_57;libboost_thread-iw-mt-s;libboost_thread-mt-s-1_57;libboost_thread-mt-s
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1037 ] Searching for THREAD_LIBRARY_DEBUG: libboost_thread-iw-mt-gd-1_57;libboost_thread-iw-mt-gd;libboost_thread-mt-gd-1_57;libboost_thread-mt-gd;libboost_thread-mt;libboost_thread;libboost_thread-iw-mt-s-gd-1_57;libboost_thread-iw-mt-s-gd;libboost_thread-mt-s-gd-1_57;libboost_thread-mt-s-gd
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1001 ] Searching for SYSTEM_LIBRARY_RELEASE: libboost_system-iw-mt-1_57;libboost_system-iw-mt;libboost_system-mt-1_57;libboost_system-mt;libboost_system;libboost_system-iw-mt-s-1_57;libboost_system-iw-mt-s;libboost_system-mt-s-1_57;libboost_system-mt-s
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1037 ] Searching for SYSTEM_LIBRARY_DEBUG: libboost_system-iw-mt-gd-1_57;libboost_system-iw-mt-gd;libboost_system-mt-gd-1_57;libboost_system-mt-gd;libboost_system-mt;libboost_system;libboost_system-iw-mt-s-gd-1_57;libboost_system-iw-mt-s-gd;libboost_system-mt-s-gd-1_57;libboost_system-mt-s-gd
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1001 ] Searching for FILESYSTEM_LIBRARY_RELEASE: libboost_filesystem-iw-mt-1_57;libboost_filesystem-iw-mt;libboost_filesystem-mt-1_57;libboost_filesystem-mt;libboost_filesystem;libboost_filesystem-iw-mt-s-1_57;libboost_filesystem-iw-mt-s;libboost_filesystem-mt-s-1_57;libboost_filesystem-mt-s
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1037 ] Searching for FILESYSTEM_LIBRARY_DEBUG: libboost_filesystem-iw-mt-gd-1_57;libboost_filesystem-iw-mt-gd;libboost_filesystem-mt-gd-1_57;libboost_filesystem-mt-gd;libboost_filesystem-mt;libboost_filesystem;libboost_filesystem-iw-mt-s-gd-1_57;libboost_filesystem-iw-mt-s-gd;libboost_filesystem-mt-s-gd-1_57;libboost_filesystem-mt-s-gd
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1001 ] Searching for PYTHON_LIBRARY_RELEASE: libboost_python-iw-mt-1_57;libboost_python-iw-mt;libboost_python-mt-1_57;libboost_python-mt;libboost_python;libboost_python-iw-mt-s-1_57;libboost_python-iw-mt-s;libboost_python-mt-s-1_57;libboost_python-mt-s
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1037 ] Searching for PYTHON_LIBRARY_DEBUG: libboost_python-iw-mt-gd-1_57;libboost_python-iw-mt-gd;libboost_python-mt-gd-1_57;libboost_python-mt-gd;libboost_python-mt;libboost_python;libboost_python-iw-mt-s-gd-1_57;libboost_python-iw-mt-s-gd;libboost_python-mt-s-gd-1_57;libboost_python-mt-s-gd
[ C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/FindBoost.cmake:1088 ] Boost_FOUND = 1
Boost version: 1.57.0
Found the following Boost libraries:
  thread
  system
  filesystem
  python
Configuring done

我如何强制编译只使用静态库?我认为这可以通过CMake文件中的选项实现。此外,使用线程的示例也可以正常工作... 也许是Boost.Python安装出了问题?


在Visual Studio中,如果您查看C++/代码生成,它是设置为多线程还是多线程DLL?问题是,如果您更改此设置,除非您拥有Python库的源代码并且也可以更改其代码生成,否则可能会导致与Python库不兼容的情况。 - cup
1
首先,显而易见的问题是:您是否实际上在 C:/softs/boost/1.57.0/ 上拥有 Boost 的静态版本?您可以使用 Boost_DEBUG=ON 在 CMake 运行期间“调试”,以查看 find_package(Boost) 找到了什么... - André
1
你使用“静态”和“共享”库这两个词非常开放 :) 话虽如此,如果你同时拥有boost的静态和共享版本,但仍然无法链接,则可能在target_link_libraries中提供lib文件的完整路径会有所帮助。关于\MT,你需要对所有链接CRT的依赖项进行相同的更改。 - mainactual
1
我没有可以测试的环境,但是定义BOOST_PYTHON_STATIC_LIB是否可以解决问题(可以通过CMake中的add_definitions()或在包含boost.python.hpp之前的#define来实现)? Boost.Python是Boost_USE_STATIC_LIBS变量的一个例外,默认配置是自动链接到动态库。 - Tanner Sansbury
@TannerSansbury:它起作用了!非常感谢!请将您的解决方案添加为响应以获得赏金。 - Caduchon
显示剩余5条评论
2个回答

15

在使用Boost.Python时,默认配置是动态链接。若要强制进行静态链接,请在编译中定义BOOST_PYTHON_STATIC_LIB。可考虑以下方法:

  • 在CMake中添加add_definitions(-DBOOST_PYTHON_STATIC_LIB)
  • 在包含boost/python.hpp之前,添加#define BOOST_PYTHON_STATIC_LIB
  • boost/config/user.hpp中添加#define BOOST_PYTHON_STATIC_LIB

对于CMake变量Boost_USE_STATIC_LIBS,Boost.Python是一个例外。FindBoost 文档指出:

在Visual Studio和Borland编译器上,Boost头文件请求自动链接到相应的库。[...] Boost自动链接通常会请求静态库,但也有一些例外情况(比如Boost.Python)。

遗憾的是,BOOST_PYTHON_STATIC_LIB选项既不在Boost用户可设置选项,也不在选择Boost.Python库二进制文件Boost.Python配置信息文档中列出。


针对你的示例代码,还有以下一些建议:

  • 根据Boost.Python的嵌入文档,不要调用Py_Finalize()。在Py_Finalize()期间,一些内部Boost.Python对象将保持活动状态,并仅在Boost.Python卸载时尝试删除,导致这些对象尝试使用不存在的解释器进行删除。
  • 不要直接包含python.h。如果必须包含,请考虑包含boost/python/detail/wrap_python.hpp
  • python.h(或Boost.Python文件)之前不要包含任何系统头文件。Python强制执行此限制(请参见此处)。

后两个建议记录在#include问题部分。


-2

就像我所说的,我不想使用共享库,而只想使用静态库。我的问题标题是错误的,我已经更正了它。 - Caduchon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接