2017-02-24 138 views
0

我想在集群上构建我的项目,所以我对环境没有任何影响(即没有sudo)。在我的本地机器上,我可以使它工作。Cmake链接多个版本的boost/Cmake独立编译的源文件

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

我已经通过使用g ++ 6.2.0作为标准编译器并通过其他gcc与-ccbin /路径/到/ GCC-4.x的。

因此,我的代码编译得很好,但问题是它也使用boost库,它需要是群集上的新版本才能与我在本地使用的gcc 6.2.0一起工作。这也不是问题本身,因为链接正确的工作,但是这样做时,nvcc仍然链接一个较旧版本的boost(这是与gcc-4.x兼容),从而导致有多个提升链接库的版本。在运行时,无论何时使用旧的boost库的函数,都会导致分段错误。

因此,一个解决方案,我在想会是第一个编译的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) 

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

+0

也许我错过了一些在这里完全明显的东西,但为什么你试图将任何主机代码与nvcc连接? – talonmies

+0

有没有办法用cmake构建一个可执行文件,它允许使用nvcc编译一部分,使用gcc/g ++编译一部分? – mimre

回答

2

为了提高CMake的文件我建议使用由升压发现脚本而不是手动设置提供的变量(将然而,最有可能不是这个问题本身有帮助,但在总体上是好的):

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代码,其余C之间的接口使用升压++码。

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

+0

我试图用这种方式来构建项目,而且看起来应该是这样的方式。我唯一的问题是,cuda_add_library使用与add_exectuable调用相同的编译标志,这对我来说很奇怪。 – mimre

+0

嗡嗡声,我其实并没有将Cuda与CMake一起使用,但是我会假设它默认使用相同的标志,也许还有一些Cuda特有的附加标志。你可以通过使用'set_target_properties(isosurfaces_cuda COMPILE_FLAGS“附加标志)'来稍微改变Cuda库的编译标志',但那只会增加额外的标志,我认为。因此,如果你想为Cuda和App设置不同的标志,你也可以在应用中使用'set_target_properties',并将默认的CXX标志设置为只有两个共享的基本集合。 – axalis

+0

谢谢,你的帖子终于帮了我。 我把cuda部分分隔成一个库,然后在CMakeLists.txt中的任何位置玩弄我设置的标志,并删除了一些标志。最终我得到了它的工作。我不完全知道如何/为什么,但它的工作原理。 – mimre