如何将 Boost 库与 CMake 链接(如果 boost 位于非标准位置,则在集群上)?



当我尝试在集群上构建一个简单的 Boost 测试程序时,我遇到了一个奇怪的问题。 在我的机器上,一切正常。

首先是示例:

//main.cpp
#include <iostream>
#include <string>
#include "boost/program_options.hpp"
namespace po = boost::program_options;
int main( int argc , char* argv[] ) {
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("greet", po::value<std::string>()->default_value("World"), "the greeting")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
std::cout << "Hello, " << vm["greet"].as<std::string>() << "!" << std::endl;
return 0;
}

还有CMakeList.txt

cmake_minimum_required(VERSION 3.5)
project(boost_test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(Boost COMPONENTS program_options)
set(SOURCE_FILES main.cpp)
if(Boost_FOUND)
add_executable(boost_test ${SOURCE_FILES})
target_include_directories(boost_test PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(boost_test PRIVATE ${Boost_LIBRARIES})
endif(Boost_FOUND)

我使用像 cmake 一样

cmake -G "Unix Makefiles" /path/to/code
make

我得到的错误是链接期间未定义的引用错误:

Linking CXX executable boost_test
CMakeFiles/boost_test.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x6d): undefined reference to `boost::program_options::options_description::options_description(std::string const&, unsigned int, unsigned int)'
CMakeFiles/boost_test.dir/main.cpp.o: In function `boost::program_options::variables_map::operator[](std::string const&) const':
main.cpp:(.text._ZNK5boost15program_options13variables_mapixERKSs[_ZNK5boost15program_options13variables_mapixERKSs]+0x1f): undefined reference to `boost::program_options::abstract_variables_map::operator[](std::string const&) const'

等等...

所以我想也许 boost 的安装不正确,我试图自己编写一个制作文件。

boost-test-1: ../code/main.cpp
g++ ../code/main.cpp -o boost-test-1 -lboost_program_options
boost-test-2: ../code/main.cpp
g++ ../code/main.cpp -o boost-test-2 /some/fancy/cluster/path/certainly/non/standard/Boost/lib/libboost_program_options.so

构建程序的两种方法都可以正常工作。但是cmake所做的基本上是以下几点:首先,构建一个目标文件,其次将目标文件和库链接在一起,然后失败。

boost-test-3: ../code/main.cpp
/usr/bin/c++    -I/some/fancy/cluster/path/certainly/non/standard/Boost/include  -std=c++11   -o main.cpp.o -c ../code/main.cpp
/usr/bin/c++    -std=c++11   main.cpp.o  -o boost-test-3 /some/fancy/cluster/path/certainly/non/standard/Boost/lib/libboost_program_options.so

如前所述,在我的计算机上,所有描述的构建程序的方法都有效,但在集群上,cmake 方式不幸失败了。问题是我有另一个使用 cmake 的更大项目,我正在寻找一种在该特定集群上构建它的方法。

您知道什么可能导致问题以及如何解决问题吗? 谢谢!


更新:这是构建过程的整个输出。我缩短了 cmake 的路径,并将 boost 缩短为"path/to/cmake"和"path/to/boost",使其更短、更易读,但它与上面描述的路径相同。

$ cmake -G "Unix Makefiles" ../code/
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Boost version: 1.61.0
-- Found the following Boost libraries:
--   program_options
-- Boost include directories (Boost_INCLUDE_DIRS): /path/to/Boost/include
-- Link directories for Boost libraries (Boost_LIBRARY_DIRS): /path/to/Boost/lib
-- Boost component libraries to be linked (Boost_LIBRARIES): /path/to/Boost/lib/libboost_program_options.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/test/build
$ make VERBOSE=1
/path/to/CMake/bin/cmake -H/home/test/code -B/home/test/build --check-build-system CMakeFiles/Makefile.cmake 0
/path/to/CMake/bin/cmake -E cmake_progress_start /home/test/build/CMakeFiles /home/test/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory `/home/test/build'
make -f CMakeFiles/boost_test.dir/build.make CMakeFiles/boost_test.dir/depend
make[2]: Entering directory `/home/test/build'
cd /home/test/build && /path/to/CMake/bin/cmake -E cmake_depends "Unix Makefiles" /home/test/code /home/test/code /home/test/build /home/test/build /home/test/build/CMakeFiles/boost_test.dir/DependInfo.cmake --color=
Dependee "/home/test/build/CMakeFiles/boost_test.dir/DependInfo.cmake" is newer than depender "/home/test/build/CMakeFiles/boost_test.dir/depend.internal".
Dependee "/home/test/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/test/build/CMakeFiles/boost_test.dir/depend.internal".
Scanning dependencies of target boost_test
make[2]: Leaving directory `/home/test/build'
make -f CMakeFiles/boost_test.dir/build.make CMakeFiles/boost_test.dir/build
make[2]: Entering directory `/home/test/build'
[ 50%] Building CXX object CMakeFiles/boost_test.dir/main.cpp.o
/usr/bin/c++    -I/path/to/Boost/include  -std=c++11   -o CMakeFiles/boost_test.dir/main.cpp.o -c /home/test/code/main.cpp
[100%] Linking CXX executable boost_test
/path/to/CMake/bin/cmake -E cmake_link_script CMakeFiles/boost_test.dir/link.txt --verbose=1
/usr/bin/c++    -std=c++11   CMakeFiles/boost_test.dir/main.cpp.o  -o boost_test /path/to/Boost/lib/libboost_program_options.so 
CMakeFiles/boost_test.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x6d): undefined reference to `boost::program_options::options_description::options_description(std::string const&, unsigned int, unsigned int)'
CMakeFiles/boost_test.dir/main.cpp.o: In function `boost::program_options::variables_map::operator[](std::string const&) const':
main.cpp:(.text._ZNK5boost15program_options13variables_mapixERKSs[_ZNK5boost15program_options13variables_mapixERKSs]+0x1f): undefined reference to `boost::program_options::abstract_variables_map::operator[](std::string const&) const'
CMakeFiles/boost_test.dir/main.cpp.o: In function `boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*)':
main.cpp:(.text._ZN5boost15program_options25basic_command_line_parserIcEC2EiPKPKc[_ZN5boost15program_options25basic_command_line_parserIcEC5EiPKPKc]+0x76): undefined reference to `boost::program_options::detail::cmdline::cmdline(std::vector<std::string, std::allocator<std::string> > const&)'
CMakeFiles/boost_test.dir/main.cpp.o: In function `boost::program_options::basic_command_line_parser<char>::extra_parser(boost::function1<std::pair<std::string, std::string>, std::string const&>)':
main.cpp:(.text._ZN5boost15program_options25basic_command_line_parserIcE12extra_parserENS_9function1ISt4pairISsSsERKSsEE[_ZN5boost15program_options25basic_command_line_parserIcE12extra_parserENS_9function1ISt4pairISsSsERKSsEE]+0x33): undefined reference to `boost::program_options::detail::cmdline::set_additional_parser(boost::function1<std::pair<std::string, std::string>, std::string const&>)'
CMakeFiles/boost_test.dir/main.cpp.o: In function `std::vector<std::string, std::allocator<std::string> > boost::program_options::to_internal<std::string>(std::vector<std::string, std::allocator<std::string> > const&)':
main.cpp:(.text._ZN5boost15program_options11to_internalISsEESt6vectorISsSaISsEERKS2_IT_SaIS5_EE[_ZN5boost15program_options11to_internalISsEESt6vectorISsSaISsEERKS2_IT_SaIS5_EE]+0x46): undefined reference to `boost::program_options::to_internal(std::string const&)'
CMakeFiles/boost_test.dir/main.cpp.o:(.rodata._ZTVN5boost15program_options11typed_valueISscEE[_ZTVN5boost15program_options11typed_valueISscEE]+0x40): undefined reference to `boost::program_options::value_semantic_codecvt_helper<char>::parse(boost::any&, std::vector<std::string, std::allocator<std::string> > const&, bool) const'
CMakeFiles/boost_test.dir/main.cpp.o: In function `boost::program_options::typed_value<std::string, char>::name() const':
main.cpp:(.text._ZNK5boost15program_options11typed_valueISscE4nameEv[_ZNK5boost15program_options11typed_valueISscE4nameEv]+0x32): undefined reference to `boost::program_options::arg'
CMakeFiles/boost_test.dir/main.cpp.o: In function `boost::program_options::typed_value<std::string, char>::xparse(boost::any&, std::vector<std::string, std::allocator<std::string> > const&) const':
main.cpp:(.text._ZNK5boost15program_options11typed_valueISscE6xparseERNS_3anyERKSt6vectorISsSaISsEE[_ZNK5boost15program_options11typed_valueISscE6xparseERNS_3anyERKSt6vectorISsSaISsEE]+0x7a): undefined reference to `boost::program_options::validate(boost::any&, std::vector<std::string, std::allocator<std::string> > const&, std::string*, int)'
collect2: error: ld returned 1 exit status
make[2]: *** [boost_test] Error 1
make[2]: Leaving directory `/home/test/build'
make[1]: *** [CMakeFiles/boost_test.dir/all] Error 2
make[1]: Leaving directory `/home/test/build'
make: *** [all] Error 2

谢谢Amadeus,Someprogrammerdude和Tsyvarev在这里带领我朝着正确的方向前进:)

事实上,这是一个编译器问题:集群上的默认编译器是 gcc-4.8.5,它无法处理最新的 Boost 版本。因此,我们为 gcc-5.4 加载了一个模块,但/usr/bin/gcc 仍然是 gcc-4.8.5。当我们将 cmake 的 cxx 编译器设置为 gcc-5.4 时,构建过程仍然失败,因为我们也使用 CUDA,默认情况下主机代码不会转发到 cxx 编译器,而是转发到 c 编译器,它仍然是 gcc-4.8.5。因此,将CUDA_HOST_COMPILER设置为CMAKE_CXX_COMPILER后,它现在可以正常工作。

最新更新