Using Cmake with Multiple Compilers for the Same Language

Using CMake with multiple compilers for the same language

It's impossible to do this with CMake.

CMake only keeps one set of compiler properties which is shared by all targets in a CMakeLists.txt file. If you want to use two compilers, you need to run CMake twice. This is even true for e.g. building 32bit and 64bit binaries from the same compiler toolchain.

The quick-and-dirty way around this is using custom commands. But then you end up with what are basically glorified shell-scripts, which is probably not what you want.

The clean solution is: Don't put them in the same CMakeLists.txt! You can't link between different architectures anyway, so there is no need for them to be in the same file. You may reduce redundancies by refactoring common parts of the CMake scripts into separate files and include() them.

The main disadvantage here is that you lose the ability to build with a single command, but you can solve that by writing a wrapper in your favorite scripting language that takes care of calling the different CMake-makefiles.

Setting Various compilers in CMake for creating a shared library

CMake allows one compiler per language, so simply writing this is enough:

cmake_minimum_required(VERSION 3.20)
project(example LANGUAGES CXX CUDA)

add_subdirectory(Cuda)
add_subdirectory(SYCL)

You can separately set the C++ and CUDA compilers by setting CMAKE_CXX_COMPILER and CMAKE_CUDA_COMPILER at the configure command line.

$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_CUDA_COMPILER=nvcc

Also, I want to clear up this misconception:

Each Folder(Cuda and SYCL) can have their dedicated CmakeLists.txt which would specify the compiler and the various flags to go with it.

The CMakeLists.txt file should not attempt to specify the compiler. It's tricky to do correctly, can't always be done (especially in the add_subdirectory case) and unnecessarily restricts your ability to switch out the compiler. Maybe you have both GCC 10 and 11 installed and want to compare the two.

Similarly, you should not specify flags in the CMakeLists.txt file that aren't absolutely required to build, and you should always check the CMake documentation to see if the flags you're interested in have been abstracted for you. For instance, CMake has special handling of the C++ language standard (via target_compile_features) and CUDA separable compilation (via the CUDA_SEPARABLE_COMPILATION target property).

The best solution, as I have detailed here, is to set optional flags via the *_FLAGS* variables in a preset or toolchain.

How can I have CMake compile the same input file in two different languages?

You could create library targets mycpplib and myclib in the different directories (in the different CMakeLists.txt). That way you may call set_source_files_properties in the directory where mycpplib library is created, and that call won't affect on myclib.

There are also DIRECTORY and TARGET_DIRECTORY options for command set_source_files_properties, which could affect on the directory where the property will be visible:

# In 'c/CMakeLists.txt`
# add_library(myclib ${CMAKE_SOURCE_DIR}/foo.bar)
# In 'cpp/CMakeLists.txt`
# add_library(mycpplib ${CMAKE_SOURCE_DIR}/foo.bar)
# In CMakeLists.txt
add_subdirectory(c)
add_subdirectory(cpp)
set_source_file_properties(foo.bar TARGET_DIRECTORY myclib
PROPERTIES LANGUAGE C)
set_source_file_properties(foo.bar TARGET_DIRECTORY mycpplib
PROPERTIES LANGUAGE CXX)

Using CMake with multiple compilers for the same language

It's impossible to do this with CMake.

CMake only keeps one set of compiler properties which is shared by all targets in a CMakeLists.txt file. If you want to use two compilers, you need to run CMake twice. This is even true for e.g. building 32bit and 64bit binaries from the same compiler toolchain.

The quick-and-dirty way around this is using custom commands. But then you end up with what are basically glorified shell-scripts, which is probably not what you want.

The clean solution is: Don't put them in the same CMakeLists.txt! You can't link between different architectures anyway, so there is no need for them to be in the same file. You may reduce redundancies by refactoring common parts of the CMake scripts into separate files and include() them.

The main disadvantage here is that you lose the ability to build with a single command, but you can solve that by writing a wrapper in your favorite scripting language that takes care of calling the different CMake-makefiles.



Related Topics



Leave a reply



Submit