Issue
I am trying to use cmake to build my own library. The code is finished by CUDA C/CXX. My CUDA code and CMake script are below:
The structure of the code:
.
├── include
│ └── Function.cuh
├── lib
│ ├── build
│ └── CMakeLists.txt
├── src
│ └── Function.cu
└── Test
├── bin
├── build
├── CMakeLists.txt
├── compileCode.sh
└── src
└── main.cu
8 directories, 6 files
The header file:
#pragma once
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cuda.h>
#include <cuda_runtime.h>
#include <curand.h>
#include <curand_kernel.h>
#include <device_launch_parameters.h>
#include <fstream>
#include <iostream>
#include <map>
#include <random>
#include <sstream>
#include <stdlib.h>
#include <sys/time.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <vector>
using namespace std;
__global__ void Function();
The source file:
#include "Function.cuh"
__global__ void Function()
{
int i = threadIdx.x + blockIdx.x * blockDim.x;
if (i > 2)
return;
printf("Function %d\n", i);
};
The user's interface, i.e. main.cu
:
#include "Function.cuh"
int main()
{
Function<<<1, 3>>>();
cudaDeviceSynchronize();
return 0;
};
The CMake file to build library
cmake_minimum_required (VERSION 3.7)
project (generate_lib)
enable_language(CUDA)
set (SCRIPT_ROOT $ENV{HOME}/Desktop/cuda_custom_lib_test)
include_directories(${SCRIPT_ROOT}/include)
file(GLOB_RECURSE SRC_CU_PATH ${SCRIPT_ROOT}/src/*.cu)
SET (CMAKE_VERBOSE_MAKEFILE TRUE)
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3057")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=1301")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3059")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -arch=sm_60 -std=c++17 -rdc=true")
add_library (CUDA_CUSTOM_LIB_TEST_shared SHARED ${SRC_CU_PATH})
add_library(CUDA_CUSTOM_LIB_TEST_static STATIC ${SRC_CU_PATH})
set_target_properties(CUDA_CUSTOM_LIB_TEST_shared PROPERTIES OUTPUT_NAME "cuda_custom_lib_test")
set_target_properties(CUDA_CUSTOM_LIB_TEST_static PROPERTIES OUTPUT_NAME "cuda_custom_lib_test")
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
TARGET_LINK_LIBRARIES( CUDA_CUSTOM_LIB_TEST_shared ${CUDA_LIBRARIES})
TARGET_LINK_LIBRARIES( CUDA_CUSTOM_LIB_TEST_static ${CUDA_LIBRARIES})
The CMake file to link the library to the main.cu file
cmake_minimum_required (VERSION 3.5)
project (MAIN_TEST)
enable_language(CUDA)
set (SCRIPT_ROOT $ENV{HOME}/Desktop/cuda_custom_lib_test)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ## bin is the EXECUTABLE_OUTPUT_PATH
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.cu)
include_directories(${SCRIPT_ROOT}/include)
find_library(LIBTEST libcuda_custom_lib_test.so HINTS ${SCRIPT_ROOT}/lib)
# find_library(LIBTEST libcuda_custom_lib_test.a HINTS ${SCRIPT_ROOT}/lib)
ADD_EXECUTABLE(main
${SRC_LIST}
)
TARGET_LINK_LIBRARIES( main ${CUDA_LIBRARIES})
TARGET_LINK_LIBRARIES( main ${LIBTEST})
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3057")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=1301")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3059")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -arch=sm_60 -std=c++17")
I indeed succeeded to build the library with the first CMakeLists.txt
. However, after linking the library with the second CMakeLists.txt
to the main.cu
file, the kernel function was not working, and nothing was printed out.
I also tried to link the libcuda_custom_lib_test.a
to the main.cu
file, and I got the follow error message:
/home/~/Desktop/cuda_custom_lib_test/lib/libcuda_custom_lib_test.a(Function.cu.o): In function `__sti____cudaRegisterAll()':
tmpxft_00002db8_00000000-5_Function.cudafe1.cpp:(.text+0xaac): undefined reference to `__cudaRegisterLinkedBinary_43_tmpxft_00002db8_00000000_6_Function_cpp1_ii_83310bf0'
collect2: error: ld returned 1 exit status
What is the problem with my CMakeLists?
Solution
With the first CMakeLists.txt
, the shared and static library can be built. Then, use NVCC
to compile the user's interface and link to static library. For example, one can go to the Test
library, then input
nvcc ./src/main.cu ../lib/libcuda_custom_lib_test.a -o ./bin/main -I ../include -arch=sm_60 -rdc=true
, then run the code with
./bin/main
, and finally get information on the terminal
~/Desktop/cuda_custom_lib_test/Test$ ./bin/main
Function 0
Function 1
Function 2
I am not sure why this method solves the problem. But the key is that, with the static library, one does not need to use -l
. Instead, just put the static library name (with path) behind the main.cu
.
Since NVCC
works well, I thought that we can use CMake to call NVCC
to do the same thing. But I got failed. I put the CMakeLists.txt
here. If someone can correct that, please comment.
cmake_minimum_required (VERSION 3.8)
project (MAIN_TEST)
find_package(CUDA)
set (SCRIPT_ROOT $ENV{HOME}/Desktop/cuda_custom_lib_test)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ## bin is the EXECUTABLE_OUTPUT_PATH
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.cu)
# set (SRC_LIST ${SRC_LIST} ${SCRIPT_ROOT}/lib/libcuda_custom_lib_test.a)
include_directories(${SCRIPT_ROOT}/include)
# find_library(LIBTEST libcuda_custom_lib_test.so HINTS ${SCRIPT_ROOT}/lib)
# find_library(LIBTEST libcuda_custom_lib_test.a HINTS ${SCRIPT_ROOT}/lib)
CUDA_ADD_EXECUTABLE(main
${SRC_LIST} ${SCRIPT_ROOT}/lib/libcuda_custom_lib_test.a
OPTIONS -arch=sm_60 -std=c++17 -rdc=true
)
# target_link_libraries(main ${SCRIPT_ROOT}/lib/libcuda_custom_lib_test.a)
# set(CMAKE_VERBOSE_MAKEFILE ON)
The error message is
[ 50%] Building NVCC (Device) object CMakeFiles/main.dir/src/main_generated_main.cu.o
Scanning dependencies of target main
[100%] Linking CXX executable ../bin/main
CMakeFiles/main.dir/src/main_generated_main.cu.o: In function `main':
/home/~/Desktop/cuda_custom_lib_test/Test/src/main.cu:5: undefined reference to `Function()'
CMakeFiles/main.dir/src/main_generated_main.cu.o: In function `__sti____cudaRegisterAll()':
/tmp/tmpxft_00004857_00000000-5_main.cudafe1.stub.c:18: undefined reference to `__cudaRegisterLinkedBinary_39_tmpxft_00004857_00000000_6_main_cpp1_ii_main'
collect2: error: ld returned 1 exit status
CMakeFiles/main.dir/build.make:79: recipe for target '../bin/main' failed
make[2]: *** [../bin/main] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/main.dir/all' failed
make[1]: *** [CMakeFiles/main.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
It is weird to see that the CMake insists on compiling the main.cu
into a CXX executable, while I did not intend to use g++
.
Answered By - Tingchang Yin Answer Checked By - David Goodson (WPSolving Volunteer)