2017-02-24 106 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