Why does CMake force the use of libcublas with separable compilation? - cmake

I use CMake 3.11 to build the following tiny CUDA-based project:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.1)
find_package(CUDA 7.0 REQUIRED)
set(CUDA_SEPARABLE_COMPILATION ON)
cuda_add_executable(dummy dummy.cu)
dummy.cu:
int main() { }
Strangely enough, when building, the following command is used for the dlink phase:
/path/to/cuda/bin/nvcc -m64 -ccbin /opt/gcc-5.4.0/bin/gcc -dlink /home/joeuser/src/dummy/CMakeFiles/dummy.dir//./dummy_generated_dummy.cu.o /path/to/cuda/lib64/libcublas_device.a -o /home/joeuser/src/dummy/CMakeFiles/dummy.dir/./dummy_intermediate_link.o
Why is CMake linking against cublas where it supposedly doesn't need it?
Note: If I remove the SEPARABLE_COMPILATION line, cublas is not added to the dlink command arguments.

Partial answer:
This doesn't seem to happen if we use CMake's native CUDA language support, e.g.
cmake_minimum_required(VERSION 3.1)
enable_language(CUDA)
add_executable(dummy dummy.cu)
instead of the above - works. I can't make it not have separable compilation though, even if I set:
set_property(TARGET dummy PROPERTY CUDA_SEPARABLE_COMPILATION OFF)

Related

CMake and MinGW cannot disable "is deprecated" warnings also setting CMAKE_WARN_DEPRECATED

I am using CMake version 3.23 with MinGW compiler
This are the basic CMAKE settings:
CMAKE_MINIMUM_REQUIRED(VERSION 3.23)
## GENERAL INITIALIZATION
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
I use CMake -G "MinGW Makefiles" .. to build the project with MinGW generator and everything works. To compile I can use both CMake --build . or mingw32-make.exe: they both warks but gives the warnings that I am describing.
The problem is that I am using some external libraries (boost, turtle) that uses the template<class> class std::auto_ptr that is deprecated.
For this reason, when I compile my project, I get this warning:
C:/turtle/include/turtle/detail/action.hpp:220:22: warning: 'template<class> class std::auto_ptr' is deprecated [-Wdeprecated-declarations]
mutable std::auto_ptr< Result > v_;
^~~~~~~~
And many other of this type as well.
As I mentioned, those warnings are not a problem for compilation, but I would like to disable them.
I have tried to set CMAKE_WARN_DEPRECATED:
SET(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
but it does not work.
I have also tried
add_compile_options(-Wno-deprecated-declarations)
but it does not work as well.
EDIT:
As suggested in the comments by Alex Reinking CMAKE_WARN_DEPRECATED is not related to compilation warning but to CMAKE warning.
The only way I've found to eliminate the warnings was to redefine CMAKE_CXX_FLAGS:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
Hope it can be helpful

How to create CMakeLists for this make file [duplicate]

Work on Ubuntu 16
I used g++ main.cpp -lpq command for compiler my small project. Now I use Clion and wanna do same what I do with g++. But I can't add compiler flags in cmake file and get compile error.
cmake_minimum_required(VERSION 3.5.1)
project(day_g)
set(CMAKE_CXX_FLAGS "-lpq")
add_definitions(-lpq)
message("CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(day_g ${SOURCE_FILES})
Also I run only cmake file and get CMAKE_CXX_FLAGS with -lpq flag.
CMAKE_CXX_FLAGS is -lpq
-- Configuring done
-- Generating done
How properly add compiler flags to cmake file?
Flag -l is for linker, not for compiler. This flag is used for link with libraries. CMake has special command target_link_libraries for that purpose:
target_link_libraries(day_g pq)
-lq is not a compiler flag (CFLAGS) but a linker flag.
To pass a library in a CMake project you should use:
target_link_libraries(target_name libraries...)
Note that if you specify 'q' as library the project will link with libq.a or, if you are on windows q.dll.
... in your CMakeLists.txt the correct line to add is:
target_link_libraries(day_g pq)
Note also that when you add a CFLAG you should also "remember" the previous ones that may be added by libraries or by your platform, ie:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
To check the exact flags cmake is passing to compiler or linker you can always run, from the build directory, the following command:
make VERBOSE=1

C++20 modules with cmake + ninja [duplicate]

Clang and MSVC already supports Modules TS from unfinished C++20 standard.
Can I build my modules based project with CMake or other build system and how?
I tried build2, it supports modules and it works very well, but i have a question about it's dependency management (UPD: question is closed).
CMake currently does not support C++20 modules.
See also the relevant issue in the CMake issue tracker. Note that supporting modules requires far more support from the build system than inserting a new compiler option. It fundamentally changes how dependencies between source files have to be handled during the build: In a pre-modules world all cpp source files can be built independently in any order. With modules that is no longer true, which has implications not only for CMake itself, but also for the downstream build system.
Take a look at the CMake Fortran modules paper for the gory details. From a build system's point of view, Fortran's modules behave very similar to the C++20 modules.
Update: CMake 3.20 introduces experimental support for Modules with the Ninja Generator (and only for Ninja). Details can be found in the respective pull request. At this stage, this feature is still highly experimental and not intended for production use. If you intend to play around with this anyway, you really should be reading both the Fortran modules paper and the dependency format paper to understand what you're getting into.
This works on Linux Manjaro (same as Arch), but should work on any Unix OS. Of course, you need to build with new clang (tested with clang-10).
helloworld.cpp:
export module helloworld;
import <cstdio>;
export void hello() { puts("Hello world!"); }
main.cpp:
import helloworld; // import declaration
int main() {
hello();
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(main)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(PREBUILT_MODULE_PATH ${CMAKE_BINARY_DIR}/modules)
function(add_module name)
file(MAKE_DIRECTORY ${PREBUILT_MODULE_PATH})
add_custom_target(${name}.pcm
COMMAND
${CMAKE_CXX_COMPILER}
-std=c++20
-stdlib=libc++
-fmodules
-c
${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}
-Xclang -emit-module-interface
-o ${PREBUILT_MODULE_PATH}/${name}.pcm
)
endfunction()
add_compile_options(-fmodules)
add_compile_options(-stdlib=libc++)
add_compile_options(-fbuiltin-module-map)
add_compile_options(-fimplicit-module-maps)
add_compile_options(-fprebuilt-module-path=${PREBUILT_MODULE_PATH})
add_module(helloworld helloworld.cpp)
add_executable(main
main.cpp
helloworld.cpp
)
add_dependencies(main helloworld.pcm)
Assuming that you're using gcc 11 with a Makefile generator, the following code should work even without CMake support for C++20:
cmake_minimum_required(VERSION 3.19) # Lower versions should also be supported
project(cpp20-modules)
# Add target to build iostream module
add_custom_target(std_modules ALL
COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules"
COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# Function to set up modules in GCC
function (prepare_for_module TGT)
target_compile_options(${TGT} PUBLIC -fmodules-ts)
set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20)
set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF)
add_dependencies(${TGT} std_modules)
endfunction()
# Program name and sources
set (TARGET prog)
set (SOURCES main.cpp)
set (MODULES mymod.cpp)
# Setup program modules object library
set (MODULE_TARGET prog-modules)
add_library(${MODULE_TARGET} OBJECT ${MODULES})
prepare_for_module(${MODULE_TARGET})
# Setup executable
add_executable(${TARGET} ${SOURCES})
prepare_for_module(${TARGET})
# Add modules to application using object library
target_link_libraries(${TARGET} PRIVATE ${MODULE_TARGET})
Some explanation:
A custom target is added to build the standard library modules, in case you want to include standard library header units (search for "Standard Library Header Units" here). For simplicity, I just added iostream here.
Next, a function is added to conveniently enable C++20 and Modules TS for targets
We first create an object library to build the user modules
Finally, we create our executable and link it to the object library created in the previous step.
Not consider the following main.cpp:
import mymod;
int main() {
helloModule();
}
and mymod.cpp:
module;
export module mymod;
import <iostream>;
export void helloModule() {
std::cout << "Hello module!\n";
}
Using the above CMakeLists.txt, your example should compile fine (successfully tested in Ubuntu WSL with gcc 1.11.0).
Update:
Sometimes when changing the CMakeLists.txt and recompiling, you may encounter an error
error: import "/usr/include/c++/11/iostream" has CRC mismatch
Probably the reason is that every new module will attempt to build the standard library modules, but I'm not sure. Unfortunately I didn't find a proper solution to this (avoiding rebuild if the gcm.cache directory already exists is bad if you want to add new standard modules, and doing it per-module is a maintenance nightmare). My Q&D solution is to delete ${CMAKE_BINARY_DIR}/gcm.cache and rebuild the modules. I'm happy for better suggestions though.
CMake ships with experimental support for C++20 modules:
https://gitlab.kitware.com/cmake/cmake/-/blob/master/Help/dev/experimental.rst
This is tracked in this issue:
https://gitlab.kitware.com/cmake/cmake/-/issues/18355
There is also a CMakeCXXModules repository that adds support for modules to CMake.
https://github.com/NTSFka/CMakeCxxModules
While waiting for proper C++20 modules support in CMake, I've found that if using MSVC Windows, for right now you can make-believe it's there by hacking around the build instead of around CMakeLists.txt: continously generate with latest VS generator, and open/build the .sln with VS2020. The IFC dependency chain gets taken care of automatically (import <iostream>; just works). Haven't tried Windows clang or cross-compiling. It's not ideal but for now at least another decently workable alternative today, so far.
Important afterthought: use .cppm and .ixx extensions.
CMake does not currently support C++20 modules like the others have stated. However, module support for Fortran is very similar, and perhaps this could be easily changed to support modules in C++20.
http://fortranwiki.org/fortran/show/Build+tools
Now, perhaps there i an easy way to modify this to support C++20 directly. Not sure. It is worth exploring and doing a pull request should you resolve it.
Add MSVC version (revised from #warchantua 's answer):
cmake_minimum_required(VERSION 3.16)
project(Cpp20)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(PREBUILT_MODULE_DIR ${CMAKE_BINARY_DIR}/modules)
set(STD_MODULES_DIR "D:/MSVC/VC/Tools/MSVC/14.29.30133/ifc/x64") # macro "$(VC_IFCPath)" in MSVC
function(add_module name)
file(MAKE_DIRECTORY ${PREBUILT_MODULE_DIR})
add_custom_target(${name}.ifc
COMMAND
${CMAKE_CXX_COMPILER}
/std:c++latest
/stdIfcDir ${STD_MODULES_DIR}
/experimental:module
/c
/EHsc
/MD
${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}
/module:export
/ifcOutput
${PREBUILT_MODULE_DIR}/${name}.ifc
/Fo${PREBUILT_MODULE_DIR}/${name}.obj
)
endfunction()
set(CUSTOM_MODULES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/modules)
add_module(my_module ${CUSTOM_MODULES_DIR}/my_module.ixx)
add_executable(test
test.cpp
)
target_compile_options(test
BEFORE
PRIVATE
/std:c++latest
/experimental:module
/stdIfcDir ${STD_MODULES_DIR}
/ifcSearchDir ${PREBUILT_MODULE_DIR}
/reference my_module=${PREBUILT_MODULE_DIR}/my_module.ifc
/EHsc
/MD
)
target_link_libraries(test ${PREBUILT_MODULE_DIR}/my_module.obj)
add_dependencies(test my_module.ifc)
I was not able to find Cmake support for modules. Here is an example how to use modules using clang. I am using Mac and this example works ok on my system. It took me quite a while to figure this out so unsure how general this is across linux or Windows.
Source code in file driver.cxx
import hello;
int main() { say_hello("Modules"); }
Source code in file hello.cxx
#include <iostream>
module hello;
void say_hello(const char *n) {
std::cout << "Hello, " << n << "!" << std::endl;
}
Source code in file hello.mxx
export module hello;
export void say_hello (const char* name);
And to compile the code with above source files, here are command lines on terminal
clang++ \
-std=c++2a \
-fmodules-ts \
--precompile \
-x c++-module \
-Xclang -fmodules-embed-all-files \
-Xclang -fmodules-codegen \
-Xclang -fmodules-debuginfo \
-o hello.pcm hello.mxx
clang++ -std=c++2a -fmodules-ts -o hello.pcm.o -c hello.pcm
clang++ -std=c++2a -fmodules-ts -x c++ -o hello.o \
-fmodule-file=hello.pcm -c hello.cxx
clang++ -std=c++2a -fmodules-ts -x c++ -o driver.o \
-fmodule-file=hello=hello.pcm -c driver.cxx
clang++ -o hello hello.pcm.o driver.o hello.o
and to get clean start on next compile
rm -f *.o
rm -f hello
rm -f hello.pcm
expected output
./hello
Hello, Modules!
Hope this helps, all the best.
With C++20 Modules the file compilation order matters, which is totally new. That's why the implementation is complicated and still experimental in 2023. Please read the authors blogpost

How to get cmake generate -std=c++14 flag for qcc compiler

I'm trying to cross compile some c++ library for QNX neutrino using cmake. In CMakeLists.txt file I specified CMAKE_CXX_STANDARD 14 required, but the resulting compiler command line does not contain the -std=c++14 option.
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
I've tried using target compile features:
target_compile_features(my_library PRIVATE cxx_std_14)
but that gives me the following error:
CMake Error at CMakeLists.txt:53 (target_compile_features):
target_compile_features no known features for CXX compiler
"QCC"
version 5.4.0.
When I'm using check_cxx_compiler_flag feature, it seems to recognize the option:
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-std=c++14 CXX14_SUPPORT)
if(CXX14_SUPPORT)
message("c++14 support found")
else()
message("c++14 unsupported")
endif()
This outputs message
c++14 support found
Running qcc manually it accepts the -std=c++14 option just fine and the code using std::make_unique compiles just fine.
Also using the native compiler (Ubuntu 18.04, gcc) everything work fine with cmake generated makefiles. make VERBOSE=1 displays the following command line (I removed some directories):
/usr/local/bin/c++ -Dshm_transfer_EXPORTS -I... -fPIC -std=gnu++14 -o CMakeFiles/shm_transfer.dir/src/SharedMemoryTransfer.cpp.o -c .../SharedMemoryTransfer.cpp
as opposed to the command line using qcc toolchain:
.../qnx700/host/linux/x86_64/usr/bin/qcc -lang-c++ -Vgcc_ntox86_64 -lang-c++ -Dshm_transfer_EXPORTS -I... -fPIC -o CMakeFiles/shm_transfer.dir/src/SharedMemoryTransfer.cpp.o -c .../SharedMemoryTransfer.cpp
I would have expected the cmake command to recognize that qcc supports the -std=c++14 option and generates the corresponding command lines because of the CMAKE_CXX_STANDARD setting.
Use
set_property(TARGET ${PROJECT_NAME} PROPERTY LINKER_LANGUAGE CXX)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
. Using this you can stick the compiler setting to the target, while global flags are dis encouraged and can be overwritten by other cmake consumers. This the reason I assume why the deprecated set(CMAKE_CXX_STANDARD 14) did not help you: I can not see your full CMakeLists.txt and bet you have many sub folders and other targets, which could reset the CMAKE_CXX_STANDARD them selfs. Also make sure of the ordering of the CMake commands.
And you can replace ${PROJECT_NAME} with my_library if you want.
add_compile_options(-std=gnu++14)
Add this to your project level CMakeLists.txt file, not in toolchain.

Build MPICH with CMake

I need to force my Cmake to build and link my MPI code with MPICH. My MPICH is installed using the Ubuntu Package manager, in a standard location /usr/lib/mpich/. However, CMake still looks for the OpenMPI libraries, which I do not use. How can I instruct CMake to look for MPICH instead?
Below, you can see the output of some basic diagnostics:
$ whereis openmpi
openmpi:
$ whereis mpich
mpich: /usr/lib/mpich /usr/include/mpich
$ mpicc -v
mpicc for MPICH version 3.2
Below, I also provide the Cmake script and the errors I get from cmake and the mpirun.mpich. My Cmake is 3.5.1 and I run on Ubuntu Xenial 16.04.
cmake_minimum_required(VERSION 3.0)
message (STATUS "Adding mpiService")
find_package(MPI REQUIRED)
set(CMAKE_C_COMPILER mpicc)
set(CMAKE_CXX_COMPILER mpicxx)
set(MPI_GUESS_LIBRARY_NAME MPICH2)
message(STATUS ${MPI_INCLUDE_PATH})
message(STATUS ${MPI_C_LIBRARIES})
#add_definitions(-DOMPI_SKIP_MPICXX)
add_executable(mpiService main.cpp)
set(CMAKE_VERBOSE_MAKEFILE ON)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
target_link_libraries(
mpiService
PRIVATE
${MPI_C_LIBRARIES}
)
From the Cmake STATUS I get the following output:
/usr/lib/openmpi/include/openmpi/opal/mca/event/libevent2021/libevent/usr/lib/openmpi/include/openmpi/opal/mca/event/libevent2021/libevent/include/usr/lib/openmpi/include/usr/lib/openmpi/include/openmpi
/usr/lib/openmpi/lib/libmpi.so
And when I run the binary I get the following:
ubuntu#node1:~$ mpirun.mpich -np 2 --host node1,node2 mpiService
mpiService: error while loading shared libraries: libmpi.so.12: cannot open shared object file: No such file or directory
mpiService: error while loading shared libraries: libmpi.so.12: cannot open shared object file: No such file or directory
How can I instruct CMake to look for MPICH instead?
According to FindMPI documentation, you may set MPI_<lang>_COMPILER variable to the desired MPI compiler:
Set MPI_<lang>_COMPILER to the MPI wrapper (mpicc, etc.) of your
choice and reconfigure. FindMPI will attempt to determine all the
necessary variables using THAT compiler's compile and link flags.
set(MPI_CXX_COMPILER <path-to-mpich-compiler>)
find_package(MPI REQUIRED)
Alternatively, since CMake version 3.10, variable MPI_EXECUTABLE_SUFFIX can be set instead:
A suffix which is appended to all names that are being looked for. For instance you may set this to .mpich or .openmpi to prefer the one or the other on Debian and its derivatives.
set(MPI_EXECUTABLE_SUFFIX ".mpich")
find_package(MPI REQUIRED)
Herewith my current solution.
find_package(MPI REQUIRED)
# ----------------
# This is the only thing that made it work
# ----------------
set(MPI_C_LIBRARIES "/usr/lib/mpich/lib/libmpich.so")
set(MPI_INCLUDE_PATH "/usr/include/mpich")
# ----------------
add_executable(mpiService main.cpp)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
target_link_libraries(
mpiService
${MPI_C_LIBRARIES}
)
I personally do not like this solution, as I have to explicitly specify the path. Any other proposed solution was still building with OpenMPI. If I find a better alternative, I will re-post.