CMAKE_CXX_SOURCE_FILE_EXTENSIONS not working with thrust/cuda - c++

Thrust allows for one to specify different backends at cmake configure time via the THRUST_DEVICE_SYSTEM flag. My problem is that I have a bunch of .cu files that I want to be compiled as regular c++ files when a user runs cmake with -DTHRUST_DEVICE_SYSTEM=OMP (for example). If I change the extension of the .cu files to .cpp they compile fine (indicating that I just need tell cmake to use the c++ compiler on the .cu files). But if I add .cu to CMAKE_CXX_SOURCE_FILE_EXTENSIONS then I get a CMake Error: Cannot determine link language for target "cuda_kernels". Here's a minimal cmake example:
cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES C CXX Fortran)
set(KERNELS_USE_OMP OFF)
if ("${THRUST_DEVICE_SYSTEM}" STREQUAL "OMP")
set(KERNELS_USE_OMP ON)
endif()
# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT KERNELS_USE_OMP)
enable_language(CUDA)
else()
list(PREPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS "cu;CU")
endif()
message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")
find_package(Thrust REQUIRED CONFIG)
thrust_create_target(Thrust FROM_OPTIONS)
add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels Thrust)
The output of the message command on my system is: -- cu;CU;C;M;c++;cc;cpp;cxx;mm;mpp;CPP;ixx;cppm
Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?

Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?
The extension-to-language for <LANG> is set as soon as <LANG> is enabled by inspecting the value of the CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS variable when the language detection module exits.
Unfortunately, there is no blessed way to override this list for CXX as it is hard-coded in Modules/CMakeCXXCompiler.cmake.in.
Perhaps the best way of working around the actual error would be to use the LANGUAGE source file property to tell CMake how to compile the individual CUDA files, like so:
cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES CXX)
find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)
thrust_is_cuda_system_found(USE_CUDA)
if (USE_CUDA)
enable_language(CUDA)
endif()
set(cuda_kernel_sources my_kernels.cu)
add_library(cuda_kernels ${cuda_kernel_sources})
target_link_libraries(cuda_kernels PRIVATE Thrust)
if (NOT USE_CUDA)
set_source_files_properties(
${cuda_kernel_sources}
PROPERTIES
LANGUAGE CXX
)
endif ()
This will certainly be friendlier to other projects that might try to add_subdirectory yours.
However, if we want to be very naughty, we can do this:
cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES NONE)
###
# Hacky language extension override
function(add_cuda_extensions variable access value current_list_file stack)
if (NOT cu IN_LIST value)
list(PREPEND "${variable}" "cu" "CU")
set("${variable}" "${${variable}}" PARENT_SCOPE)
endif ()
endfunction()
# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT THRUST_DEVICE_SYSTEM STREQUAL "OMP")
enable_language(CUDA)
enable_language(CXX)
else()
variable_watch(CMAKE_CXX_SOURCE_FILE_EXTENSIONS add_cuda_extensions)
enable_language(CXX)
endif()
###
# Normal project code starts here
message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")
find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)
add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels PRIVATE Thrust)
This waits for the platform module to try to write CMAKE_CXX_SOURCE_FILE_EXTENSIONS and then any time it's accessed, quickly inserts the cu and CU extensions to the list.

Related

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

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.).

CMake: Instruct compiler to ignore warnings from libs folder

I'm trying to specify to the compiler to ignore all messages + warnings originating from the libs folder, where I keep my external libraries used in my project.
The LLVM library is the main cause of the problem, since the warnings produced fill up the entire screen making it very difficult for me to efficiently identify compile-time errors, etc.
I'm using CMake and have my LLVM 9.0.0 library under the libs folder. I would like to instruct the compiler (using CMake) to ignore all warnings and messages originating from the libs folder.
This is my CMakeLists.txt file:
# General project settings.
cmake_minimum_required(VERSION 3.12.4)
project(ionir)
# Setup compiler flags.
set(CMAKE_CXX_STANDARD 17)
# General project information.
set(PROJECT_URL "https://github.com/ionlang/ir-c")
# Setup source and build directories.
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
option(USE_MD "Use MD instead of MTd" OFF)
if (USE_MD)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MD")
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
endif(USE_MD)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
# Setup versioning.
set(VERSION_MAJOR "1")
set(VERSION_MINOR "0")
set(VERSION_PATCH "0")
set(VERSION "$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)")
# Configure and use LLVM. Also ensures LLVM 9.0.0 is installed.
find_package(LLVM 9.0.0 EXACT REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
# Include LLVM source directories (for syntax support, etc.). The SYSTEM symbol supposedly marks the directory to supress warnings.
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) #---> COMMENTED TO SOLVE CIRCULAR DEPS. PROBLEM.
add_definitions(${LLVM_DEFINITIONS})
# Disable warnings from includes.
#add_library(llvm INTERFACE)
#target_sources(llvm INTERFACE)
#target_include_directories(llvm PRIVATE include/ SYSTEM INTERFACE include/)
# Set source file(s).
file(GLOB_RECURSE SOURCES
"src/*.h"
"src/*.cpp"
)
# Specify that this project is a library.
add_library(${PROJECT_NAME} ${SOURCES})
# Provide include directories to be used in the build command. Position in file matters.
#target_include_directories(${PROJECT_NAME} PRIVATE "src")
include_directories("src")
# Find the libraries that correspond to the LLVM components
# that we wish to use
# llvm_map_components_to_libnames(llvm_libs support core irreader)
# Link against LLVM libraries.
target_link_libraries(${PROJECT_NAME} ${llvm_libs})
# Setup unit testing using Google Test (GTest) if applicable. This binds the CMakeLists.txt on the test project.
option(BUILD_TESTS "Build tests" ON)
if (BUILD_TESTS)
add_subdirectory(libs/googletest)
add_subdirectory(test)
endif()
And below is some of the warnings/messages I'm receiving that are filling up the console.
How can I accomplish this?

Finding Direct3D 12 using CMake

So I've been trying to learn CMake and use it with C++. I'd like to have a go at creating a portable game engine which uses Direct3D 12 on Windows.
Currently, I have the following CMakeLists.txt for my project:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(PsychoEngineCore)
set(SRCS_CXX ${CMAKE_CURRENT_LIST_DIR})
include(${CMAKE_CURRENT_SOURCE_DIR}/src/dir_src.cmake)
set(LIB_TYPE "STATIC" CACHE STRING "Static or Dynamic Linking")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU OR
${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
set(warnings "-Wall -Wextra -Werror")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
set(warnings "/W4 /WX /EHsc")
endif()
if(NOT CONFIGURED_ONCE)
set(CMAKE_CXX_FLAGS "${warnings}"
CACHE STRING "Flags used by the compiler during all build types." FORCE)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Do we want static libraries?
# When STATIC_LINKING is TRUE, then cmake looks for binaries ending in ".a".
# THIS IS FOR LINUX ONLY!
if(LIB_TYPE EQUAL STATIC)
if (UNIX AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES(".a"))
endif(UNIX AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set_target_properties(surface PROPERTIES LINK_SEARCH_END_STATIC 1)
endif(LIB_TYPE EQUAL STATIC)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include(GenerateExportHeader)
add_library(${PROJECT_NAME} ${LIB_TYPE} ${SRCS_CXX})
GENERATE_EXPORT_HEADER(
${PROJECT_NAME}
EXPORT_MACRO_NAME PE_API
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/Engine/API/${PROJECT_NAME}Export.hpp
DEPRECATED_MACRO_NAME PE_API_DEP
STATIC_DEFINE PE_STATIC
)
Currently I have my d3d12.lib file in the following location:
C:\Program Files (x86)\Windows Kits\10\Libs\10.0.16299.0\um\x64
Is there a way to keep the path dynamic and preferably "update" if a newer version is available on said system?
Thanks!
Turning my comment into an answer
Generally speaking, just add a
target_link_libraries((${PROJECT_NAME} d3d12.lib)
The Windows SDK (where the Direct3D SDK is now part of) is in the standard search paths e.g. of the linker for libraries. So it's found automatically by the MSVC compiler and linker.
And I don't think that upgrading to a newer (yet unknown) API version automatically is a good idea. You're writing your program for a specific API version.
Working Example
Here is a minimal working example (Tested VS2017 15.5.5, CMake 3.9.0):
cmake_minimum_required(VERSION 3.0)
project(Direct3DExample)
find_package(Git REQUIRED)
set(_path "${CMAKE_BINARY_DIR}/DirectX-Graphics-Samples/Samples/Desktop/D3D12HelloWorld/src/HelloTriangle")
if (NOT EXISTS "${_path}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" clone https://github.com/Microsoft/DirectX-Graphics-Samples.git
)
endif()
file(GLOB _files "${_path}/*")
list(APPEND _shader ${_files})
list(FILTER _files EXCLUDE REGEX "\\.vcxproj|\\.hlsl")
list(FILTER _shader INCLUDE REGEX "\\.hlsl")
get_filename_component(_name "${_path}" NAME)
add_executable(${_name} WIN32 ${_files})
target_compile_definitions(${_name} PRIVATE "UNICODE" "_UNICODE")
target_link_libraries(${_name} PRIVATE "d3d12.lib" "dxgi.lib" "d3dcompiler.lib")
add_custom_command(
TARGET ${_name}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${_shader} $<TARGET_FILE_DIR:${_name}>
)
If you need more (compilers/linkers that are not finding the Windows SDK automatically), you may want to look the following find_package() config code:
https://github.com/Microsoft/DirectXShaderCompiler/blob/master/cmake/modules/FindD3D12.cmake

CMake Error: CMake can not determine linker language for target: myapp

I am trying to compile vMime by cmake, but I am getting error above,
I am using graphical interface of cmake and my makefiles.txt is below. It configures properly but do not generate
cmake_minimum_required(VERSION 2.8)
PROJECT(CXX)#vmime
enable_language(CXX)
set(VerifyCXX VerifyCXX.cxx)
add_definitions(-DVERIFY_CXX)
set_target_properties(${TARGET} PROPERTIES LINKER_LANGUAGE Cxx)
add_executable(myapp vmime)
install(TARGETS myapp DESTINATION bin)
Help will be highly appreciated as I am stuck at point for couple of days.
CMake probably can not determine linker language for target myapp, because the target does not contain any source files with recognized extensions.
add_executable(myapp vmime)
should be probably replaced by
add_executable(myapp ${VerifyCXX})
Also this command
set_target_properties(${TARGET} PROPERTIES LINKER_LANGUAGE Cxx)
cannot be succesfull, because ${TARGET} is used-before-set. You should call it after add_executable
set_target_properties(myapp PROPERTIES LINKER_LANGUAGE CXX)
Note that usually it is not needed at all.
For others' benefit, make sure you did not overlook an earlier error such as:
Cannot find source file:
MyFirstSourceFile.cpp
Another way to cause CMake to give you the error, "CMake Error: CMake can not determine linker language for target: myapp", is if you mistakenly point it exclusively at sources that do not exist.
For instance: I'm moving files from one directory to another and had the pre-move files with the post-move paths in my CMakeLists.txt. My output window is not very tall and I focused too soon on the "can not determine linker language" error!
I use clion IDE based on cmake, my source files named *.cc
project(server)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
file(GLOB SRC_FILE "main.cc" "listenfd.cc" "socket_util.cc"
"timers.cc" "network.cc" "main_event.cc")
add_executable(server ${server})
set_target_properties(server PROPERTIES LINKER_LANGUAGE CXX)
after I change
add_executable(server ${server}) to
add_executable(server "main.cc")
then I solved it, I really don't know why?
after experiment I found when use file(GLOB ....) like file(GLOB "src/main.cc") I must specify the relative path, then it works.

CMake third party library undefined reference

I already read and searched a lot (e.g. 1 2 3, several docs for CMake, similar projects, etc. to find a solution but I have not been able to solve my problem. I am relatively new to Cmake and Linux (Ubuntu 14.04).
I want to use libsbp (https://github.com/swift-nav/libsbp) to write a program in C++ to communicate with a GPS module. I cloned the repository and installed the C-Library. So now in /usr/local/lib there are two files: libsbp.so and libsbp-static.a and the headers are in /usr/local/include/libsbp
In my own project I include the headers with #include "libsbp/sbp.h" which also works.
Now the Problem: if I want to use a method from libsbp e.g. sbp_state_init(&s); I get undefined reference to "sbp_state_init(sbp_state_t*)"
The relevant part of my Cmake for my own project:
link_directories(/usr/local/lib)
add_executable(main ${QT_SOURCES} ${QT_HEADER_HPP})
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)
As I said before, I tried some things:
find_library(SBP_LIB sbp /usr/local/lib) -> same error
same goes for using libsbp in target_link_libraries or searching for it
link_directory(/usr/local/lib)
trying different paths, even moveing libsbp.so into the project directory and "finding" it with ${CMAKE_CURRENT_SOURCE_DIR}
Maybe you can help me!
edit:
this is the CMakeList.txt from the libsbp/c/src directory
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif (NOT DEFINED BUILD_SHARED_LIBS)
file(GLOB libsbp_HEADERS "${PROJECT_SOURCE_DIR}/include/libsbp/*.h")
include_directories("${PROJECT_SOURCE_DIR}/CBLAS/include")
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
include_directories("${PROJECT_SOURCE_DIR}/lapacke/include")
include_directories("${PROJECT_SOURCE_DIR}/include/libsbp")
set(libsbp_SRCS
edc.c
sbp.c
)
add_library(sbp-static STATIC ${libsbp_SRCS})
install(TARGETS sbp-static DESTINATION lib${LIB_SUFFIX})
if(BUILD_SHARED_LIBS)
add_library(sbp SHARED ${libsbp_SRCS})
install(TARGETS sbp DESTINATION lib${LIB_SUFFIX})
else(BUILD_SHARED_LIBS)
message(STATUS "Not building shared libraries")
endif(BUILD_SHARED_LIBS)
install(FILES ${libsbp_HEADERS} DESTINATION include/libsbp)
this is the CMakeList.txt from /libsbp/c/
cmake_minimum_required(VERSION 2.8.9)
project(libsbp)
# Setup flags for Code Coverage build mode
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C++ compiler for building with code coverage."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C compiler for building with code coverage."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used for linking binaries with code coverage."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the shared libraries linker during builds with code coverage."
FORCE )
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
# Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE )
# Set project version using Git tag and hash.
execute_process(
COMMAND git describe --dirty --tags --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_VERSION_FOUND
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)
# Set project version explicitly for release tarballs.
#set(VERSION foo)
message(STATUS "libsbp version: ${VERSION}")
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Some compiler options used globally
set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}")
add_subdirectory(src)
add_subdirectory(docs)
add_subdirectory(test)
It seems that your program uses C++ and the library is written in C.
Symbols in C and C++ are encoded differently (mangled). When including C headers from C++ you need to tell the compiler. This can be done by declaring the symbols extern "C".
extern "C" {
#include <libsbp/sbp.h>
}
Some libraries already include this in their headers, but not sbp.
You have (at least) two possibilities:
Installing the library (this is what you did)
Integrating the library in your CMake project
When installing the library, the target_link_libraries command needs to be modified slightly:
find_library(SBP_LIB sbp /usr/local/lib)
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} ${SBP_LIB})
When you integrate the library in your CMake project, you can directly use the following command without using find_library. This works, because the library is known to CMake since it is built within the current project.
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)