Cmake: how to choose C++ headers - c++

I want to choose between using gcc and clang and also want to choose between libstdc++ and libc++. This site explains how to mix compilers and standard libraries. I can choose between compilers by calling cmake like CC=gcc CCX=g++ cmake... or with CC=clang....
The problem is that with libstdc++ I need to use the flag -I/usr/include/c++/5 and with libc++ the -I/usr/include/c++/v1.
For portability reasons I do not want to include the above paths neither in CMakeListst.txt, neither as a command line argument. Is there a way to do this and let cmake autodetect it?

Maybe you already know this, find_package boost or openssl are also see certain environment variable such as BOOST_ROOT and OPENSSL_ROOT_DIR. So you need such hint variable also.
Like cpprestsdk cmake script,
I think your CMakeLists.txt is
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message("-- Setting clang option")
include_directories(${Your_path})
...
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
message("-- Setting gcc options")
include_directories(${Your_path})
...
else()
message("-- Unknown compiler, success is doubtful.")
message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}")
endif()

Related

CMake skips standard precompiled headers

I'm new to C++, really trying to get familiar with CMake, but there's always something wrong.
I'm using CLion with Cygwin and G++11 package installed
My CMakeLists.txt file:
cmake_minimum_required(VERSION 3.20)
project(testing)
set(CMAKE_CXX_STANDARD 20)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif ()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
add_executable(testing main.cpp)
Clion says me that execution header is not found, but I could locate it in lib/ folder:
Could somebody tell me what I'm doing wrong?
Here are a few things I have tried when debugging similar problems:
If in doubt, delete and re-create your build directories. CMake caches certain variables and can sometimes get into a weird state. A fresh directory will remove any uncertainty.
CMake should print out what compiler it is using - Check that and make sure it's correct. For example, it could be finding an older version that does not have that header.
In this case, the fix may be to put your desired compiler at the front of your PATH, or to force CMake to find the correct one via CMAKE_CXX_COMPILER.
Build in verbose mode - you should be able to see what include paths are being used (-I, -isystem). Make sure that directory is in there.
Alternatively, you can dump a compile_commands.json file that should contain the same information by setting CMAKE_EXPORT_COMPILE_COMMANDS=true
Try using one of these build commands to build a single object in your Cygwin shell. If it works, it may indicate a problem with how your CLion is configured.

CMake+OpenCL+CUDA -> runtime library may be hidden

I'm using CMake 3.16, with a CMakeLists.txt file specifying a minimum CMake version of 3.9. In my file, I have:
find_package(CUDA 8.0 REQUIRED)
find_package(OpenCL REQUIRED)
# etc. etc.
target_link_libraries(my_executable
PRIVATE
cuda # The NVIDIA CUDA driver API
${CUDA_LIBRARIES}
OpenCL::OpenCL
)
Now, in the CMake generation phase, I get the error:
CMake Warning at CMakeLists.txt:44 (add_executable):
Cannot generate a safe runtime search path for target my_executable because
files in some directories may conflict with libraries in implicit
directories:
runtime library [libOpenCL.so.1] in /usr/lib64 may be hidden by files in:
/usr/local/cuda/lib64
Some of these libraries may not be found correctly.
Now, I do want the libOpenCL.so.1 from the CUDA directories; and building does produce an executable with the correct dependency. How can I tell CMake that this masking is ok, and not have it print the warning message?
Note: Working with CUDA in CMake has changed a lot over the 3.x series of releases. So whatever was happening before 3.8 is irrelevant, and also things changed significantly in 3.17 with a few more non-trivial changes afterwards. Answers about pre-3.8 and 3.17-or-later are, well, fine - but not what I need.
I know this doesn't answer your question precisely, but as of CMake 3.17+, the CUDA OpenCL libraries are loaded by the FindCUDAToolkit module. It is used like so:
cmake_minimum_required(VERSION 3.17)
project(my_proj LANGUAGES C CXX CUDA)
find_package(CUDAToolkit 8.0 REQUIRED)
# ...
target_link_libraries(
my_executable
PRIVATE
CUDA::cuda_driver
CUDA::cudart
CUDA::OpenCL
)
I hope this answer will help other readers who are using up-to-date CMake, because whatever answer works on 3.9 will not be quite as nice.
As #AlexReinking suggests in a comment, you can avoid this warning by giving CMake a (strong) hint regarding which OpenCL location you want to use. Before running CMake, set your OpenCL_ROOT environment variable to /usr/local/cuda; with a CMake version higher than 3.12, the find_package() command will use that variable, preferring to locate OpenCL there if possible - and not warn you about the alternative location.

How do I designate which compiler is called when running cmake + make?

I'm trying to compile a c++ project with cmake and make on OSX but it looks like make is using CXX or clang when I want to use g++ (gcc) so I can follow the answer here to tell the compiler where to find header files (#includes) for tbb used in the project: Need help getting intel TBB working?
brew list shows that I have up to date versions of cmake, make, gcc, and swig installed.
Here's the project I'm trying to compile for reference: https://github.com/nmoehrle/mvs-texturing/blob/master/README.md
I came across this related answer and was able to get the project working! MacOS, CMake and OpenMP
I updated the cmakelists.txt with the following commands to set llvm as the compiler. Note, I needed to update the llvm file path to match the version number I have installed.
set(CMAKE_C_COMPILER "/usr/local/Cellar/llvm/5.0.1/bin/clang")
set(CMAKE_CXX_COMPILER "/usr/local/Cellar/llvm/5.0.1/bin/clang++")
set(OPENMP_LIBRARIES "/usr/local/Cellar/llvm/5.0.1/lib")
set(OPENMP_INCLUDES "/usr/local/Cellar/llvm/5.0.1/include")
Then I was also having issues with OpenMP so I added this section to configure the OpenMP include directories and link directories.
if (OPENMP_FOUND)
include_directories("${OPENMP_INCLUDES}")
link_directories("${OPENMP_LIBRARIES}")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif(OPENMP_FOUND)
I'm a novice dev and wish I had more insight into why this worked but it fixed my issues!

Configure cmake to choose compiler based on environment

My current project directory looks like
myproject
/-build
/-include
/-somefile.h
/-somefile2.h
/-myproject.cpp
/-CMakeLists.txt
and current CMakeLists.txt looks like :
cmake_minimum_required (VERSION 3.1)
project (myproject)
add_executable(myproject myproject.cpp)
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/build)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
include_directories("${PROJECT_INCLUDE_DIR}")
include_directories("${PROJECT_SOURCE_DIR}")
I want to build this project in both x64Windows and x64Linux environment while keeping single cmake file. Currently I have Visual Studio 13 CE in Win and gcc in Linux. Is it possible that Cmake could intelligently choose the correct compiler depending on OS? And what changes should I make to CMakeLists for that?
I'm using normal stuff like STL and vanilla C++ ( no os dependent libraries) if that matters. Thanks
You want to add conditional code for each compiler:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# Set the C++ and linker flags to GCC specifics here.
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Set the C++ and linker flags to VC++ specifics here.
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# Set the C++ and linker flags to Clang specifics here.
elseif()
The right compiler is set automatically at least on linux. On windows I don't know. However you could always overwrite the selected compiler by the environment variables CC and CXX. This changes the cmake configuration. The changes will only affect new build configurations. So don't forget to delete your old one before selecting a new compiler.
Edit: The compiler must be of course in your PATH variable. Otherwise CMake will not find it correctly.

Linking libc++ to CMake project on Linux

I want to use libc++ together with clang on Arch Linux in CMake project. I installed libc++ and added following lines to CMakeLists.txt as said on LLVM site in Linux section of "Using libc++ in your programs":
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS "-lc++abi")
I have tried just "++abi" in linker's flags, but it didn't help. I need some help in figuring out what i should write in my CMakeLists.txt.
Don't forget to set the compiler to clang++:
set(CMAKE_CXX_COMPILER "clang++")
Also, purge the cmake generated files (delete the folder CMakeFiles and CMakeCache.txt).
Depending on your system, it might also help to set
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
The "proper" way to do this in CMake at the moment, until a specific base feature is added to switch standard libraries that is, is to use a toolchain file.
In that toolchain file you specify the compiler etc similarly to the other answers here.
BUT what's great about toolchains is they can be swapped out quickly either on the commandline (using -DCMAKE_TOOLCHAIN_FILE=path/to/file) OR in VSCode with CMakeTools extension installed, and probably other editors too.
But having to hand code your own toolchain files is yet another obscure chore! No fun!
Luckily, I stumbled upon this github that maintains a suite of them so you don't have to write them from scratch! Should be a lot less likely to get them wrong.
https://github.com/ruslo/polly