Ubuntu 16.04 woes and CUDA 8 to 7.5... T_T

So I thought I’d try to officially change from the CUDA 8 RC to the real CUDA 8. So I downloaded the .run file and proceeded to somehow just destroy my system. I think it was because I said “yes” to letting it configure x-server stuff. Huge. Mistake.

Basically, after spending all day on this, I’ve cleared and purged everything multiple times, finally got my display working and solved an infinite login loop.

The only issue is, I’m having CMake issues now.

I kind of just gave up with how Nvidia wants us to install CUDA. The local method takes too long to download the files and the network method just doesn’t seem to do anything. I can’t ever locate the package using apt-get.

But there is the Ubuntu package nvidia-cuda-toolkit which I’ve installed successfully! I have nvcc back and all that happiness but now when I try to compile my project using CMake, I keep getting undefined references to cudaCreateStream and other basic CUDA functions like that.

What’s interesting is that Ubuntu’s nvidia-cuda-toolkit doesn’t actually install to /usr/local/cuda so I have no idea where anything is or if CMake is even looking there.

I can use nvcc to compile a stand-alone “Hello, world!” file with a cudaDeviceSynchronize() but I’m wondering how do I fix CMake to compile?

Here’s my CMakeLists.txt:

cmake_minimum_required(VERSION 3.2)

project(regulus)
find_package(CUDA REQUIRED)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORCE_INLINES")
set(CMAKE_CXX_STANDARD 11)
set(CUDA_HOST_COMPILATION_CPP ON)
set(CUDA_SEPARABLE_COMPILATION ON)



set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter")

# Pass options to NVCC
list(APPEND
    CUDA_NVCC_FLAGS
    ${CUDA_NVCC_FLAGS};
    -gencode arch=compute_50,code=sm_50
    -std=c++11 
    -O3
    --expt-extended-lambda
    )

cuda_add_executable(
  regulus
  
  main.cu

  include/domain.hpp
  include/timer.hpp
  include/mesher.hpp
  include/array.hpp
  include/globals.hpp
  include/stack-vector.hpp
  
  include/math/math.hpp
  include/math/point.hpp
  include/math/matrix.hpp
  include/math/equals.hpp
  include/math/tetra.hpp
  include/math/rand-int-range.hpp
  
  include/lib/calc-ta-and-pa.hpp
  include/lib/nominate.hpp
  include/lib/fract-locations.hpp
  include/lib/fracture.hpp
  include/lib/redistribute-pts.hpp
  include/lib/get-assoc-size.hpp
  include/lib/mark-nominated-tetra.hpp
  
  tests/test-suite.hpp
  
  src/point.cu
  src/peano.cu
  src/nominate.cu
  src/fract-locations.cu
  src/fracture.cu
  src/get-assoc-size.cu
  src/rand-int-range.cu
  src/mark-nominated-tetra.cu
  
  tests/test-suite.cu
  tests/domain-tests.cu
  tests/mesher-tests.cu
  tests/math-tests.cu
  tests/matrix-tests.cu
  tests/array-tests.cu
  tests/tetra-tests.cu
  tests/nomination-tests.cu
  tests/fract-location-tests.cu
  tests/fracture-tests.cu
  tests/redistribute-pts-tests.cu
  tests/stack-vector-tests.cu
  tests/get-assoc-size-tests.cu
  )

target_link_libraries(
  regulus
  cudart
  cudadevrt
  )

And here’s my linking errors:

[  4%] Building NVCC intermediate link file CMakeFiles/regulus.dir/regulus_intermediate_link.o
nvlink error   : Undefined reference to 'cudaEventDestroy' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaGetErrorString' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaStreamDestroy' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaGetParameterBuffer' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaLaunchDevice' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaDeviceSynchronize' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaEventCreateWithFlags' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
nvlink error   : Undefined reference to 'cudaEventRecord' in '/home/christian/cuda/regulus/build/CMakeFiles/regulus.dir/src/./regulus_generated_nominate.cu.o'
CMakeFiles/regulus.dir/build.make:13928: recipe for target 'CMakeFiles/regulus.dir/regulus_intermediate_link.o' failed
make[2]: *** [CMakeFiles/regulus.dir/regulus_intermediate_link.o] Error 255
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/regulus.dir/all' failed
make[1]: *** [CMakeFiles/regulus.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

The missing symbols suggest the build hasn’t linked in the CUDA runtime library. Either it cannot locate the library (check for -L switches in the compiler command line specifying library locations), or the library is not specified correctly and the build doesn’t even try to link it in. The latter seems more likely because I would expect an error along the lines of “can’t find library” in the former case.

Sorry, I can’t tell you how to adjust the CMake configuration to make this work. I have a long-standing personal policy of refusing to have my time wasted by this build obfuscation tool. But there are plenty of enthusiastic CMake users around who should be able to give you pointers.

As a first step, you might want to double-check that a CUDA runtime library (libcudart) is actually present on your system, and that it is the correct version.

Well, a huge clue is that even cudaDeviceSynchronize is undefined when I use CMake. I was able to compile some code earlier that did with just pure nvcc calls and it worked out fine. So basically, tomorrow I’m going to attempt to port my project to a pure Makefile project without CMake because I’m not wasting my time trying to figure it out lol.

If you were able to successfully build simple CUDA projects without CMake, that is a pretty good indication that you have a functional CUDA installation, and that the issue here is one of CMake configuration. For small projects, a simple makefile should require no more lines than the CMake configuration you showed above, so proceeding without CMake definitely seems like the way to :-)

Lol yup, I have a successful installation of CUDA!

Okay, so the Ubuntu package nvidia-cuda-toolkit does things like an actual package instead of putting the entire CUDA bundle in /usr/local/cuda-${version}. The CUDA headers and Thrust are actually ins /usr/include and in /usr/lib there’s nvidia-cuda-toolkit/ which contains the binaries and whatnot.

The Makefile method works! I was able to successfully compile and link my entire project! Now that I’m so much better at programming than I used to be, making a Makefile was actually not all that hard.

So, this made me think. CMake is “weak” because it makes assumptions. If you don’t have everything in a symlink at /usr/local/cuda, it’s not really worth trying. I know Linux-exclusivity is biased but I’d rather have a Makefile that works everywhere in Linux vs a CMake build that doesn’t work for every version of Linux but might on Windows.

Anyway, don’t download the CUDA 8 associated driver if you’re on Ubuntu 16.04. Using the “official” package seems to be the most stable way of downloading CUDA.