CMake script for CUDA 6.0 with C++11

2019-05-27 03:03发布

I am working on a 64-bit Mac OSX 10.9 for my CUDA 6.0 + Boost 1.55.0 + OpenCV 2.4.9 project, compiled using a makefile, but since I will eventually test it on 64-bit Windows 8.1, I thought I'd get acquainted with CMake. Since I am using C++11, I am generating object files for the C++ code with clang++ (version 5.1 (clang-503.0.40), which g++ now links to in mavericks) and CUDA code with nvcc separately, then linking the object files together for the final executable in my makefile.

I have no idea how to do this in CMake though. I tried compiling the CUDA code as a static library (using both CMake built-ins and FindCUDA.cmake utilities) and then linking it, but that did not work. I have not been able to find a solution online which takes C++11 into account.

Here is my CMake script so far:

cmake_minimum_required(VERSION 2.8)

project(pupil_tracker)

include_directories(include)
include_directories(include/cuda)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-gencode arch=compute_20, code=sm_20)
#set(CUDA_HOST_COMPILER clang++) # Fails with 'invalid argument '-std=c++11' not allowed with 'C/ObjC''

find_package(Boost COMPONENTS system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}) # So CMake finds FindOpenCV.cmake
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

CUDA_ADD_LIBRARY(cuda_obj STATIC src/cuda/Tools.cu) # Doesn't seem to work

add_executable(main src/main.cpp src/CenteredHaarFeature.cpp src/PupilTracker.cpp src/Tools.cpp)

target_link_libraries(main ${Boost_LIBRARIES})
target_link_libraries(main ${CUDA_LIBRARIES})
target_link_libraries(main ${OpenCV_LIBS})
target_link_libraries(main ${cuda_obj})

install(TARGETS main DESTINATION ../bin)

If all fails, I'll have to try and set up a MSVC project on my Windows machine to do the same.

1条回答
小情绪 Triste *
2楼-- · 2019-05-27 03:17

The CMAKE_CXX_FLAGS can interfere with the NVCC compilation so you have to be careful about where you put them.

I recreated your setup with a really simple example using only the CUDA library. After rearranging and editing a few of the CMake commands I was able to compile and run the program.

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)

project(pupil_tracker)

include_directories(include)
include_directories(include/cuda)

# removed a space and added C++11 functionality (note the double '--' for NVCC)
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-gencode arch=compute_20,code=sm_20;--std=c++11)
set(CUDA_HOST_COMPILER clang++) # shouldn't fail anymore

# didn't test with Boost
# find_package(Boost COMPONENTS system filesystem REQUIRED)
# include_directories(${Boost_INCLUDE_DIR})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})

# didn't test with OpenCV
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}) # So CMake finds FindOpenCV.cmake
# find_package(OpenCV REQUIRED)
# include_directories(${OpenCV_INCLUDE_DIRS})

CUDA_ADD_LIBRARY(cuda_obj STATIC src/cuda/Tools.cu) # works for me now

# moved the CXX flags to after the cuda_add_library call
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_executable(main src/main.cpp src/Tools.cpp) # only used one c++ class for this test

# target_link_libraries(main ${Boost_LIBRARIES})
target_link_libraries(main ${CUDA_LIBRARIES})
# target_link_libraries(main ${OpenCV_LIBS})
target_link_libraries(main cuda_obj) # changed ${cuda_obj} to cuda_obj

install(TARGETS main DESTINATION ../bin)

The project directory setup can be inferred from the CMake file but for clarification it looks like:

ProjectDir:

  • CMakeLists.txt
  • include
    • Tools.hpp
    • cuda
      • Tools.cuh
  • src
    • main.cpp
    • Tools.cpp
    • cuda
      • Tools.cu

Tools.cuh:

#ifndef TOOLS_CUH
#define TOOLS_CUH

extern "C"
{
    void do_cuda_stuff();
}

#endif

Tools.cu:

#include <cuda_runtime.h>
#include <stdio.h>

extern "C"
{
    __global__
    void do_cuda_stuff_kernel()
    {
        int idx = blockIdx.x * blockDim.x + threadIdx.x;
        printf("Hello from thread %d!\n", idx);
    }

    void do_cuda_stuff()
    {
        // 2 blocks, 3 threads each
        do_cuda_stuff_kernel<<<2, 3>>>();
        cudaDeviceSynchronize(); // to print results
    }
}

Tools.hpp:

#ifndef TOOLS_HPP
#define TOOLS_HPP

class Tools
{
public:
    int execute();
};

#endif

Tools.cpp:

#include "Tools.hpp"
#include "Tools.cuh"

int Tools::execute()
{
    do_cuda_stuff();
    return 0;
}

main.cpp:

#include "Tools.hpp"

int main(void)
{
    Tools tools;
    return tools.execute();
}

Output:

Hello from thread 3!
Hello from thread 4!
Hello from thread 5!
Hello from thread 0!
Hello from thread 1!
Hello from thread 2!

I'm currently using CUDA 7.5 and OSX 10.10 but I think the biggest issue was the placement of the CMAKE_CXX_FLAGS variable. Hope this helps! Cheers!

查看更多
登录 后发表回答