Search code examples
c++cmakecudasycl

Setting Various compilers in CMake for creating a shared library


I am looking to set various compilers for different folders in my project, which should compile to a shared library.

The project structure is as follows -

/Cuda
    a.cu
    b.cu
    c.cu
    header.cuh
/SYCL
    a.cpp
    b.cpp
    c.cpp
    header.h
main.cpp
test.cpp

All the files under the Cuda folder must be compiled by nvcc, and the files under the SYCL folder by a specific compiler that is present at a path in the system. All the files outside these folders (namely main.cpp and test.cpp) are normal C++ code and use the headers present in these two folders and must be compiled with GCC.

How do I go about writing the CMake for such a project structure(which aims to be a shared lib).

Edit - The project needn't have only one dedicated CMake. My approach was as follows -

  • Each Folder(Cuda and SYCL) can have their dedicated CmakeLists.txt which would specify the compiler and the various flags to go with it.
  • A master CMake outside the folder can use the add_subdirectory command. And this is where I get stuck, I am not sure what to do next, how to link these two folders with the main and the test files.

Solution

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