How to link cuda library to cpp project/files with Cmake? - c++

I am trying to write a gui program using the gtk libraries and do some matrix operations with the cuda libraries, however I get an error when trying to link the cuda libraries in my project. My Cmake looks like this:
cmake_minimum_required(VERSION 3.21)
project(untitled1)
set(CMAKE_CXX_STANDARD 14)
find_package(CUDAToolkit)
include_directories(${CUDA_INCLUDE_DIRS})
link_directories(${CUDA_LIBRARY_DIRS})
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER})
add_executable(untitled1 main.cpp bob.h bob.cu)
target_link_libraries(untitled1 ${GTK3_LIBRARIES} ${CUDA_LIBRARIES} ${CUDA_CUDART_LIBRARY})
But I get the following error
-- Unable to find cuda_runtime.h in "/usr/lib/cuda/include" for CUDAToolkit_INCLUDE_DIR.
-- Unable to find cudart library.
-- Could NOT find CUDAToolkit (missing: CUDAToolkit_INCLUDE_DIR CUDA_CUDART) (found version "11.2.67")
-- Configuring done
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
CUDA_CUDART_LIBRARY (ADVANCED)
I am on Pop OS 21.10 (Ubuntu), I can use the Cuda libraries and nvcc outside of this project, so I know it is installed and working properly. I just don't know how to link the cuda libraries to a non cuda project.
Edit: Working CMakeLists.txt down below thx to dhyun
# Set the minimum version of cmake required to build this project
cmake_minimum_required(VERSION 3.21)
# Set the name and the supported language of the project
project(final CUDA)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CUDA_STANDARD 14)
# Use the package PkgConfig to detect GTK+ headers/library files
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
# Setup CMake to use GTK+, tell the compiler where to look for headers
# and to the linker where to look for libraries
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
# Add other flags to the compiler
add_definitions(${GTK_CFLAGS_OTHER})
# Add an executable compiled from files:
add_executable(final main.cu showtext.h)
target_link_libraries(final ${GTK3_LIBRARIES})
# Idk what this does or if it's necessary, but it works with it and was there on creation
# So I'm keeping it :)
set_target_properties(final PROPERTIES
CUDA_SEPARABLE_COMPILATION ON)

I can't speak for your exact setup, but I've had success with CMake and CUDA on Ubuntu by directly enabling CUDA as a language in the project declaration rather than using find_package(CUDAToolkit).
Something like this:
cmake_minimum_required(VERSION 3.21)
project(untitled1 LANGUAGES CUDA CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CUDA_STANDARD 14)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER})
add_executable(untitled1 main.cpp bob.h bob.cu)
target_link_libraries(untitled1 ${GTK3_LIBRARIES})
I believe cudart is linked automatically, but you will need to specify any other libraries you use (cufft, cublas, cudnn, etc.).

Related

How to determine what LLVM components used in source for cmake?

I'm new to cmake and LLVM. Here is a confusing question when I configure CMakeLists.txt for my own LLVM project.
Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.24)
project(llvm_in_practice)
set(CMAKE_CXX_STANDARD 14)
FILE(GLOB SOURCE_FILES ${CMAKE_SOURCE_DIR}/src/*.cpp)
find_package(LLVM REQUIRED CONFIG)
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
include_directories(include)
add_executable(main ${SOURCE_FILES})
llvm_map_components_to_libnames(llvm_libs core)
target_link_libraries(main ${llvm_libs})
I'm ok with most of all the configuration except for llvm_map_components_to_libnames(llvm_libs core). In my source, I use #include <llvm/IR/Value.h> etc. to include LLVM into my project. However, in cmake, I need to know what component the header file belongs to for making cmake right.
I'v tried llvm_map_components_to_libnames(llvm_libs ir) which obviously not work. I also tried llvm-config --components to see all components but I do not know how to determine which one I should use.
How can I checkout which component the LLVM header file belongs to?

mingw-g++ can't find include directory

I'm trying to compile my program for Windows, on Linux, so I installed the w64-mingw32 compiler via the Debian package manager. I made a separate cmakelists file where I chose x86_64-w64-mingw32-g++ as the compiler. When I try to run my build script, I get errors where it can't find the libraries that I use in my project. This is my cmake file:
cmake_minimum_required (VERSION 3.5)
if (POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
else (NOT POLICY CMP0072)
message(STATUS "Could not use CMP0072 policy")
endif(POLICY CMP0072)
project(opengl-test LANGUAGES CXX)
set(CMAKE_CXX_COMPILER "/usr/bin/x86_64-w64-mingw32-g++")
set(CMAKE_C_COMPILER "/usr/bin/x86_64-w64-mingw32-gcc")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GNUInstallDirs)
set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set (source_dir "${PROJECT_SOURCE_DIR}/src/")
set (base_dir "${source_dir}/base/")
set (IMGUI_DIR "/usr/include/imgui")
set(GCC_COVERAGE_LINK_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
file(GLOB source_files "${source_dir}/*.cpp")
file(GLOB_RECURSE base_files "${base_dir}/*.cpp")
file(GLOB imgui_files "${IMGUI_DIR}/*.cpp")
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_executable(${PROJECT_NAME} ${source_files} ${imgui_files} ${base_files})
#target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
message(STATUS ${OPENGL_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PUBLIC ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES})
A lot of the code in the cmakelists file doesn't do anything because I was trying to make it work but nothing was working. I left it in so you can see what I've tried and doesn't work.
I can run this and it compiles, but I get a linker error.
CMake Warning:
No source or binary directory provided. Both will be assumed to be the
same as the current working directory, but note that this warning will
become a fatal error in future CMake releases.
-- /usr/lib/x86_64-linux-gnu/libOpenGL.so/usr/lib/x86_64-linux-gnu/libGLX.so/usr/lib/x86_64-linux-gnu/libGLU.so
-- Configuring done
CMake Warning at CMakeLists.txt:38 (add_executable):
Cannot generate a safe runtime search path for target opengl-test because
files in some directories may conflict with libraries in implicit
directories:
runtime library [libGLEW.so.2.1] in /usr/lib64 may be hidden by files in:
/usr/lib/x86_64-linux-gnu
Some of these libraries may not be found correctly.
-- Generating done
-- Build files have been written to: /home/user/Documents/CPP-Stuff/Scrap-Framework
[29/29] Linking CXX executable opengl-test
FAILED: opengl-test
: && /usr/bin/x86_64-w64-mingw32-g++ -g CMakeFiles/opengl-test.dir/src/main.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_demo.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_draw.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_impl_glfw.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_impl_opengl3.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_tables.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_widgets.cpp.o CMakeFiles/opengl-test.dir/src/base/Application/Application.cpp.o CMakeFiles/opengl-test.dir/src/base/Application/Window.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/Cubemap.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/Texture.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/UniformBuffer.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/VertexBuffer.cpp.o CMakeFiles/opengl-test.dir/src/base/Input/Input.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/Material.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/Mesh.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/Model.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/ModelLoader.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/FPSCamera.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/MaterialManager.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/Renderbuffer.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/Renderer.cpp.o CMakeFiles/opengl-test.dir/src/base/Scene/Lights.cpp.o CMakeFiles/opengl-test.dir/src/base/Scene/Scene.cpp.o CMakeFiles/opengl-test.dir/src/base/Scene/Skybox.cpp.o CMakeFiles/opengl-test.dir/src/base/Shader/Shader.cpp.o CMakeFiles/opengl-test.dir/src/base/Shader/ShaderManager.cpp.o -o opengl-test -Wl,-rpath,/usr/lib/x86_64-linux-gnu -lglfw /usr/lib/x86_64-linux-gnu/libOpenGL.so /usr/lib/x86_64-linux-gnu/libGLX.so /usr/lib/x86_64-linux-gnu/libGLU.so /usr/lib64/libGLEW.so && :
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lglfw
/usr/bin/x86_64-w64-mingw32-ld: /usr/lib/x86_64-linux-gnu/libOpenGL.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
The include files are located in /usr/include/, but I also put them in /usr/x86_64-w64-mingw32/include/.
Does anyone know how I can fix this, or a better way to compile for Windows on Linux?
You need to build the libraries you're using for Windows, or find prebuilt ones, e.g. in MSYS2 repositories. You also need to point CMake to those libraries.
I've made Quasi-MSYS2 to automate both.
Example usage:
# Install Clang, LLD, Wine. Then:
git clone https://github.com/holyblackcat/quasi-msys2
cd quasi-msys2/
make install _gcc _glfw _glew
env/shell.sh
# Build
cd your/project/location
mkdir build
cd build
cmake ..
make
# Run with Wine
./a.exe
Here is CMakeLists.txt I've used. I removed the cross-compilation stuff (which is handled automatically).
cmake_minimum_required (VERSION 3.5)
if (POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
else (NOT POLICY CMP0072)
message(STATUS "Could not use CMP0072 policy")
endif(POLICY CMP0072)
project(opengl-test LANGUAGES CXX)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_executable(a 1.cpp)
message(STATUS ${OPENGL_LIBRARIES})
target_link_libraries(a PUBLIC ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES} GLEW::GLEW)
I also put them in /usr/x86_64-w64-mingw32/include/
You shouldn't modify system include directories manually. Leave them to your package manager.

Linking Facebook Proxygen with Cmake

Facebook's wangle library can be set up with cmake like below:
set_and_check(WANGLE_INCLUDE_DIR /usr/local/include/wangle)
set_and_check(WANGLE_CMAKE_DIR /usr/local/lib/cmake/wangle)
if (NOT TARGET wangle::wangle)
include("${WANGLE_CMAKE_DIR}/wangle-targets.cmake")
endif()
set(WANGLE_LIBRARIES wangle::wangle)
if (NOT wangle_FIND_QUIETLY)
message(STATUS "Found wangle: ${PACKAGE_PREFIX_DIR}")
endif()
However, proxygen's install.sh doesn't put the include and lib files in /usr/local like wangle and other fb libraries do.
What is the proper way to set the include and link with proxygen via cmake?
According to the proxygen README you should install all requirements, including folly, wangle, fmt, fizz, and mvfst if you need HTTP/3 protocol. After installing proxygen with the instruction in the README you can use it in your CMake project. Following is an example CMakeLists.txt and you can find the complete sample project in this repo.
cmake_minimum_required(VERSION 3.10)
project(3hat)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(proxygen REQUIRED)
find_package(gflags REQUIRED)
add_subdirectory(server)

How to build static library with bundled dependencies - CMake

I am currently using CMake to create a static library which utilizes a few of the static libraries from OpenCV 4 ( core imgcodecs video highgui imgproc ). My intention is to be able to bundle all of the required OpenCV static libraries into my own library so that I can distribute it as one library. Additionally, I want for the user of my library to not have to install OpenCV 4 on their system (but do not mind if the user has to do simple installs using apt-get install). I know there are tools for bundling static libraries (such as using ar for linux).
However, where I really am having the issue is with all the dependencies of OpenCV (such as libjpeg, libpng, etc). I don't necessarily mind if these libraries are bundled with mine or linked dynamically as they are relatively easy to install (can be installed with sudo apt-get install, whereas opencv4 needs to be built from source).
What is the best way to go about doing this?
This is my current CMakeLists.txt
It is currently working, but that is because I am using find_package(OpenCV REQUIRED) (which defeats the purpose of what I am trying to do). When I remove that line, the linker complains about not being able to find the OpenCV dependencies.
cmake_minimum_required(VERSION 2.8)
project(myproject)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
list(APPEND LINKER_LIBS opencv_core opencv_highgui opencv_video opencv_imgcodecs libmxnet.so libncnn.a nlohmann_json::nlohmann_json)
file(GLOB SRC${CMAKE_CURRENT_LIST_DIR}/src/*.cpp${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_library(myproject ${SRC})
target_link_libraries(myproject ${LINKER_LIBS} ${OpenMP_CXX_FLAGS})
To elaborate on my question. I build my project which generates libmyproject.a. I then take this library and will eventually extract the symbols from the OpenCV libs (libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a) and add them to my lib (for the time being, I have not yet done this step, which is why in the below example I am linking libopencv_*). I then use my library in a new project, for which the CMakeLists.txt is shown below:
cmake_minimum_required(VERSION 2.8)
project(myproject-driver)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)
add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver myproject libncnn.a ${OpenMP_CXX_FLAGS} libmxnet.so libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a)
Building this generates the following errors:
Linking CXX executable myproject-driver
/usr/bin/ld: /home/nchafni/Cyrus/myproject/lib/libopencv_imgcodecs.a(grfmt_jpeg.cpp.o): undefined reference to symbol 'jpeg_default_qtables##LIBJPEG_8.0'
//usr/lib/x86_64-linux-gnu/libjpeg.so.8: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
How can I fix this. Is there some CMake command which will link all these dependencies for me? Do I need to manually track down each dependency of those libopencv_* libs and link those manually? Once again, this is assuming that the person using libmyproject.a can't use find_package(OpenCV REQUIRED) as it won't be defined as they have not installed OpenCV on their machine.
First of all, don't use the super old and outdated version 2.8 of CMake. CMake 3.x is so much more powerful and pretty straightforward to use.
Some tips for modern CMake.
Don't use file(GLOB), see here why that is.
Don't use directory wide instructions, rather use target instructions, e.g. target_include_directories vs. include_directories.
Don't use string variables like ${<PACKAGE_NAME>_LIBRARIES}, rather use targets, e.g. <Package_NAME>::lib
When using targets instead of string variables, all the properties (including LINK_INTERFACE) of that target will be populated to the library/executable when calling target_link_libraries, so no more include_directories,link_directories, etc.
myproject
cmake_minimum_required(VERSION 3.14)
project(myproject)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
set(SOURCES ...) # list all the source files here
add_library(myproject ${SOURCES})
target_include_directories(myproject PUBLIC # give it a scope
${CMAKE_CURRENT_LIST_DIR}/include
)
target_link_libraries(myproject PUBLIC # give it a scope
opencv_core # using the target, you will get all LINK_LIBRARIES
opencv_highgui
opencv_video
opencv_imgcodecs
libmxnet.so # where is this coming from?
libncnn.a # where is this coming from?
nlohmann_json::nlohmann_json
OpenMP::OpenMP_CXX ## linking against a target, CXX_FLAGS will be populated automatically
)
myprojec-driver
cmake_minimum_required(VERSION 3.14)
project(myproject-driver)
set(CMAKE_CXX_STANDARD 14)
add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver PUBLIC # give it a scope
myproject # gets all dependencies through the LINK_INTERFACE
)

Include Eigen library for Xcode project via CMake/CMakeLists.txt

I've got the following CMakeLists.txt (in my "project" folder) file for my project.
# define new project
PROJECT(SETUPMARKERTEST)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0 FATAL_ERROR)
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif(UNIX)
# Set static build for GLFW
SET(BUILD_SHED_LIBS OFF)
ADD_SUBDIRECTORY(ext/glfw-3.1.1)
# Set shared lib build for the rest
SET(BUILD_SHARED_LIBS ON)
# Find dependencies
SET(EIGEN_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/ext/Eigen-3.1.2")
FIND_PACKAGE(OpenCV REQUIRED)
# Set header and source files
SET(MAR_Test_SOURCES
src/main.cpp
src/MarkerTracker.h src/MarkerTracker.cpp
src/PoseEstimation.h src/PoseEstimation.cpp
)
# define executable
ADD_EXECUTABLE(${PROJECT_NAME} ${MAR_Test_SOURCES})
# define additional include directories and linking targets
INCLUDE_DIRECTORIES("ext/glfw-3.1.1/include" ${EIGEN_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OpenCV_LIBS} glfw ${OPENGL_glu_LIBRARY} ${GLFW_LIBRARIES})
And my Eigen folder is in "project/ext/Eigen/3.1.2/Eigen/".
Somehow when I created my project for Xcode (in "project/buildXcode/" with Cmake .. -G "Xcode") and run it, Xcode throws me the error:
So I guess there is some error in my CMakeLists.txt, unfortunately I received that file and I'm new to CMake and thus didn't write it on my own nor am I very skilled with CMake.
Do you know what causes the error and can you fix the CMakeLists.txt that my project runs with the Eigen library?
Unfortunately it looks like windows is having no problem with this, whereas mac is bleating.
You just have to use
#include <Eigen/Dense>
instead of
#include <Eigen\Dense>
...pretty stupid error.