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.
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
- src
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!