【问题标题】:Cmake links multiple versions of boost/Cmake separate compilation of source filesCmake链接多个版本的boost/Cmake分别编译源文件
【发布时间】:2017-02-24 16:14:59
【问题描述】:

我正在尝试在集群上构建我的项目,所以我对环境没有任何影响(即没有 sudo)。在我的本地机器上,我可以让它工作。

这里的问题: 我的项目包含 cuda 文件以及 c++ 代码。后者需要一个需要 gcc/g++ >6 的库(也许 >5 也可以,afaik std=c++14)。另一方面,从 cuda 7.5 开始,cuda 代码需要 gcc

我已经通过使用 g++ 6.2.0 作为标准编译器完成了这个问题,并使用 -ccbin /path/to/gcc-4.x 传递了另一个 gcc。

所以我的代码编译得很好,但问题是它还使用了 boost 库,它需要是集群上的更新版本才能与我本地使用的 gcc 6.2.0 一起使用。这本身也不是问题,因为链接正确的确实有效,但是这样做时,nvcc 仍然链接旧版本的 boost(与 gcc-4.x 兼容)和从而导致链接了多个boost库版本。每当使用旧的 bo​​ost 库的函数时,这都会导致运行时出现分段错误。

所以我考虑的一个解决方案是首先编译 c++ 文件,然后只编译 cuda 文件,有点像一个简单的 makefile 目标:

foo: foo-class.o
  nvcc foo-class.o foo.cu -o foo 

我目前不确定这是否能解决问题以及是否可以通过 cmake 来解决,但如果不是这样,是否有可能处理双重链接?

我的当前外观的最小 cmake 文件示例:

cmake_minimum_required(VERSION 3.2)

project(foo)

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(LINKER_FLAGS "-lboost_program_options -lboost_regex -lSDL2 -lSDL2main -lboost_system -lboost_filesystem")
set(ADDITIONAL_FLAGS "-g -Wno-error=switch")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 ${LINKER_FLAGS} ${ADDITIONAL_FLAGS}")

set(SOURCE_FILES
    runtime/main.cpp
    foo.cpp)

set(CUDA_FILES cuda/food.cu)

set(CUDA_ADDITIONAL_FLAGS "-ccbin /usr/bin/gcc --Wno-deprecated-gpu-targets")
set(CUDA_SDK_ROOT_DIR "/afs/crc.nd.edu/x86_64_linux/c/cuda/8.0/")
find_package(CUDA QUIET REQUIRED)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
set(CUDA_NVCC_FLAGS -g ${CUDA_ADDITIONAL_FLAGS})

FIND_PACKAGE(Boost COMPONENTS program_options filesystem system regex REQUIRED)

cuda_add_executable(isosurfaces ${SOURCE_FILES} ${CUDA_FILES})


include_directories(~/lib/include)
include_directories(${BOOST_ROOT}/incldue)

target_link_libraries(foo ~/lib/lib/libThorSerialize17.so)

感谢您的帮助,我真的很感激。

【问题讨论】:

  • 也许我在这里遗漏了一些完全明显的东西,但是你为什么要尝试将任何主机代码与 nvcc 链接呢?
  • 有没有办法用cmake构建一个可执行文件,允许一部分用nvcc编译,一部分用gcc/g++编译?

标签: c++ boost cuda cmake


【解决方案1】:

为了改进 CMake 文件,我建议使用 Boost 查找脚本提供的变量,而不是手动设置(但这很可能对问题本身没有帮助,但总的来说很好):

find_package(Threads)
# set(Boost_USE_STATIC_LIBS ON) # uncomment to try with static libs
FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options filesystem system regex)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})

target_link_libraries(isosurfaces
    ${Boost_LIBRARIES}
    ${CUDA_LIBRARIES}
    ${CMAKE_THREAD_LIBS_INIT}
)

# remove -lboost_program_options -lboost_regex -lboost_system -lboost_filesystem
# from LINKER_FLAGS as provided better by ${Boost_LIBRARIES}

关于不同版本的 Boost 本身的问题(如果您出于某种原因确实需要在 Cuda 代码中使用 Boost),恐怕很难在单个可执行文件的范围内工作。但是,您可以将其中一个模块(Cuda 或应用程序代码)分离到一个单独的共享库。这样它可以相对简单地工作,因为共享库可以使用与应用程序的其余部分不同的 Boost 版本(您可以尝试使用静态或共享 Boost 库,即Boost_USE_STATIC_LIBS 已打开/关闭)。

例如,从 Cuda 代码创建一个共享库,您可以这样做:

cuda_add_library(isosurfaces_cuda ${CUDA_FILES} SHARED)
add_executable(isosurfaces ${SOURCE_FILES})
target_link_libraries(isosurfaces
    isosurfaces_cuda
    ${Boost_LIBRARIES}
    ${CUDA_LIBRARIES}
    ${CMAKE_THREAD_LIBS_INIT}
)

那么它可能会起作用,前提是您不在 Cuda 代码和剩余 C++ 代码之间的接口中使用 Boost。

它还可以帮助使用可见性属性并默认隐藏所有符号,这样 Boost 库符号就不会从 Cuda 共享库中导出(或者相反,如果库是从剩余的 C++ 创建的代码)。为此,可以使用“-fvisibility=hidden”编译器标志和“-Wl,--exclude-libs=ALL -Wl,--discard-all”链接器标志。

【讨论】:

  • 我正在尝试以这种方式构建项目,看起来应该是这样。我唯一的问题是 cuda_add_library 使用与 add_exectuable 调用相同的编译标志,这对我来说很奇怪。
  • 嗯,我实际上还没有将 Cuda 与 CMake 一起使用,但我认为默认情况下它使用相同的标志,可能还有一些用于 Cuda 细节的附加标志。您可以使用set_target_properties(isosurfaces_cuda COMPILE_FLAGS "additional flags") 在一定程度上更改 Cuda 库编译标志,但我认为这只会添加额外的标志。因此,如果您希望 Cuda 和 App 使用不同的标志,您也可以为应用使用 set_target_properties,并将默认 CXX 标志设置为仅由两者共享的一些基本设置。
  • 谢谢您,您的帖子最终帮助了我。我将 cuda 部分分离到一个库中,然后在 CMakeLists.txt 中设置标志并删除了一些标志..最终我让它工作了。我不完全知道如何/为什么,但它有效。
猜你喜欢
  • 1970-01-01
  • 2011-03-11
  • 2019-03-15
  • 1970-01-01
  • 2019-06-14
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多