# CheckLanguage does not take the C++ standard into account

**URL:** https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433
**Category:** Development
**Tags:** lang:cuda
**Created:** [August 13, 2024, 11:48am UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433 "2024-08-13T11:48:53Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![krasznaa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/krasznaa/32/893_2.png) [@krasznaa](https://discourse.cmake.org/u/krasznaa)
#### Post date: [August 13, 2024, 11:48am UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/1 "2024-08-13T11:48:53Z")

</div>

Hi,

I’ve run into an issue recently that I think CMake could be helping with in a better way. 🤔 In one of our projects we tend to make use of the very latest version of certain compilers at the same time. Which does not always work. For instance right now one cannot use [CUDA 12.6](https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html) with [oneAPI 2024.2.1](https://www.intel.com/content/www/us/en/developer/articles/release-notes/intel-oneapi-toolkit-release-notes.html) as the host compiler.

```auto
/home/krasznaa/software/nvidia/cuda-12.6.0/x86_64/bin/nvcc
-forward-unknown-to-host-compiler
-ccbin=/home/krasznaa/software/intel/oneapi-2024.2.1/compiler/2024.2/bin/compiler/clang++
-allow-unsupported-compiler -std=c++20 -c main.cu -o main.cu.o
/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3433):
error: type name is not allowed
       : bool_constant<__is_layout_compatible(_Tp, _Up)>
                                              ^

/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3433):
error: type name is not allowed
       : bool_constant<__is_layout_compatible(_Tp, _Up)>
                                                   ^

/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3433):
error: identifier "__is_layout_compatible" is undefined
       : bool_constant<__is_layout_compatible(_Tp, _Up)>
                       ^

/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3440):
error: type name is not allowed
         = __is_layout_compatible(_Tp, _Up);
                                  ^

/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3440):
error: type name is not allowed
         = __is_layout_compatible(_Tp, _Up);
                                       ^

5 errors detected in the compilation of "main.cu".

```

That part has nothing to do with CMake, the “interesting” part is just that this compiler combination happens to not have issues when using C++17. But it does with C++20. So now, when I write the following CMake code:

```cmake
cmake_minimum_required(VERSION 3.26)
project(CheckLanguageCUDA VERSION 0.0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20 CACHE STRING "Host compiler C++ version")
set(CMAKE_CUDA_STANDARD 20 CACHE STRING "CUDA compiler C++ version")

include(CheckLanguage)
check_language(CUDA)

if(CMAKE_CUDA_COMPILER)
   enable_language(CUDA)
endif()

```

, I get the following output:

```auto
-- The CXX compiler identification is IntelLLVM 2024.2.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /home/krasznaa/software/intel/oneapi-2024.2.1/compiler/2024.2/bin/icpx - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for a CUDA compiler
-- Looking for a CUDA compiler - /home/krasznaa/software/nvidia/cuda-12.6.0/x86_64/bin/nvcc
-- Looking for a CUDA host compiler - /home/krasznaa/software/intel/oneapi-2024.2.1/compiler/2024.2/bin/icpx
-- The CUDA compiler identification is NVIDIA 12.6.20
-- Detecting CUDA compiler ABI info
-- Detecting CUDA compiler ABI info - failed
-- Check for working CUDA compiler: /home/krasznaa/software/nvidia/cuda-12.6.0/x86_64/bin/nvcc
-- Check for working CUDA compiler: /home/krasznaa/software/nvidia/cuda-12.6.0/x86_64/bin/nvcc - broken
CMake Error at /home/krasznaa/software/kitware/cmake-3.30.2/x86_64-ubuntu2204-gcc11-opt/share/cmake-3.30/Modules/CMakeTestCUDACompiler.cmake:59 (message):
  The CUDA compiler

    "/home/krasznaa/software/nvidia/cuda-12.6.0/x86_64/bin/nvcc"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: '/home/krasznaa/development/cmake/build/CMakeFiles/CMakeScratch/TryCompile-ym6qLI'
    
    Run Build Command(s): /home/krasznaa/software/kitware/cmake-3.30.2/x86_64-ubuntu2204-gcc11-opt/bin/cmake -E env VERBOSE=1 /usr/bin/gmake -f Makefile cmTC_fac61/fast
    /usr/bin/gmake -f CMakeFiles/cmTC_fac61.dir/build.make CMakeFiles/cmTC_fac61.dir/build
    gmake[1]: Entering directory '/home/krasznaa/development/cmake/build/CMakeFiles/CMakeScratch/TryCompile-ym6qLI'
    Building CUDA object CMakeFiles/cmTC_fac61.dir/main.cu.o
    /home/krasznaa/software/nvidia/cuda-12.6.0/x86_64/bin/nvcc -forward-unknown-to-host-compiler -ccbin=/home/krasznaa/software/intel/oneapi-2024.2.1/compiler/2024.2/bin/icpx -allow-unsupported-compiler -std=c++20 "--generate-code=arch=compute_52,code=[compute_52,sm_52]" -MD -MT CMakeFiles/cmTC_fac61.dir/main.cu.o -MF CMakeFiles/cmTC_fac61.dir/main.cu.o.d -x cu -c /home/krasznaa/development/cmake/build/CMakeFiles/CMakeScratch/TryCompile-ym6qLI/main.cu -o CMakeFiles/cmTC_fac61.dir/main.cu.o
    /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3433): error: type name is not allowed
          : bool_constant<__is_layout_compatible(_Tp, _Up)>
                                                 ^
    
    /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3433): error: type name is not allowed
          : bool_constant<__is_layout_compatible(_Tp, _Up)>
                                                      ^
    
    /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3433): error: identifier "__is_layout_compatible" is undefined
          : bool_constant<__is_layout_compatible(_Tp, _Up)>
                          ^
    
    /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3440): error: type name is not allowed
            = __is_layout_compatible(_Tp, _Up);
                                     ^
    
    /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits(3440): error: type name is not allowed
            = __is_layout_compatible(_Tp, _Up);
                                          ^
    
    5 errors detected in the compilation of "/home/krasznaa/development/cmake/build/CMakeFiles/CMakeScratch/TryCompile-ym6qLI/main.cu".
    gmake[1]: *** [CMakeFiles/cmTC_fac61.dir/build.make:79: CMakeFiles/cmTC_fac61.dir/main.cu.o] Error 2
    gmake[1]: Leaving directory '/home/krasznaa/development/cmake/build/CMakeFiles/CMakeScratch/TryCompile-ym6qLI'
    gmake: *** [Makefile:127: cmTC_fac61/fast] Error 2
    
    

  

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:12 (enable_language)

-- Configuring incomplete, errors occurred!

```

This is because [CheckLanguage](https://cmake.org/cmake/help/latest/module/CheckLanguage.html) doesn’t propagate (among other things) the `CMAKE_<LANG>_STANDARD` variables to the test project that it sets up. Which can result in an error like this.

Now… the setup that I’m describing here is broken. So it’s not the end of the world that CMake doesn’t handle it quite correctly at the moment. But still, I wonder if `check_language(...)` could potentially be taught to work correctly in such situations as well. 🤔

Cheers,  
Attila

---

<div class="post-metadata">

### Author: ![scivision](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/a87d85/32.png) [@scivision](https://discourse.cmake.org/u/scivision)
#### Post date: [August 13, 2024, 4:17pm UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/2 "2024-08-13T16:17:26Z")

</div>

Does patching your CheckLanguage.cmake work with this change?

```patch
diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 35ad0368d6..82c736eba3 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -115,6 +115,11 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
     else()
       set(_D_CMAKE_LANG_PLATFORM "")
     endif()
+ if(CMAKE_${lang}_STANDARD)
+ set(_D_CMAKE_LANG_STANDARD "-DCMAKE_${lang}_STANDARD:STRING=${CMAKE_${lang}_STANDARD}")
+ else()
+ set(_D_CMAKE_LANG_STANDARD "")
+ endif()
     execute_process(
       WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
       COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
@@ -124,6 +129,7 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
                                  ${_D_CMAKE_MAKE_PROGRAM}
                                  ${_D_CMAKE_TOOLCHAIN_FILE}
                                  ${_D_CMAKE_LANG_PLATFORM}
+ ${_D_CMAKE_LANG_STANDARD}
       OUTPUT_VARIABLE _cl_output
       ERROR_VARIABLE _cl_output
       RESULT_VARIABLE _cl_result

```

you can copy CheckLanguage.cmake locally and patch as above to try it. E.g. in your CMakeLists.txt

```cmake
include(${CMAKE_CURRENT_SOURCE_DIR}/CheckLanguage.cmake)

```

---

<div class="post-metadata">

### Author: ![krasznaa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/krasznaa/32/893_2.png) [@krasznaa](https://discourse.cmake.org/u/krasznaa)
#### Post date: [August 13, 2024, 5:00pm UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/3 "2024-08-13T17:00:54Z")

</div>

That change does indeed achieve the behaviour that I’d like. 👍

```auto
-- The CXX compiler identification is IntelLLVM 2024.2.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /home/krasznaa/software/intel/oneapi-2024.2.1/compiler/2024.2/bin/icpx - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for a CUDA compiler
-- Looking for a CUDA compiler - NOTFOUND
-- Configuring done (2.8s)
-- Generating done (0.0s)
-- Build files have been written to: /home/krasznaa/Development/build

```

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [August 13, 2024, 9:48pm UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/4 "2024-08-13T21:48:11Z")

</div>

> [@krasznaa](#):
>
> This is because [CheckLanguage](https://cmake.org/cmake/help/latest/module/CheckLanguage.html) doesn’t propagate (among other things) the `CMAKE_<LANG>_STANDARD` variables to the test project that it sets up.

Policy CMP0067 controls this aspect. When it is set to NEW (which it would be in your example project), the underlying `try_compile()` call that `check_language()` uses should be propagating the language standard variables to the test sub-build.

I wonder if in your experiments you are not resetting the `CMAKE_CXX_STANDARD` and `CMAKE_CUDA_STANDARD` variables. These wouldn’t normally be made cache variables like in your example. Can you repeat your tests, but change those two lines to the following (change the value between 20 and 17 as per your previous testing):

```cmake
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CUDA_STANDARD 20)

```

The results should be the same either way, but if you make them cache variables, you have to remember to force their value when you re-test with a different value to the first run.

---

<div class="post-metadata">

### Author: ![krasznaa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/krasznaa/32/893_2.png) [@krasznaa](https://discourse.cmake.org/u/krasznaa)
#### Post date: [August 14, 2024, 6:51am UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/5 "2024-08-14T06:51:42Z")

</div>

Hi Craig,

No, the variable type is not an important aspect here. I tried, but using “simple variables” in my example code doesn’t change anything with how `check_language(...)` behaves. And in any case, I was configuring my build from scratch each time for this example, so the build directory remembering the value of the cache variables was not a concern.

As @scivision showed, `CheckLanguage.cmake` doesn’t actually use `try_compile(...)`. It uses `execute_process(...)` to set up a whole other cmake project under the hood. So [CMP0067](https://cmake.org/cmake/help/latest/policy/CMP0067.html) unfortunately doesn’t help here. 🙁

Best,  
Attila

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [August 15, 2024, 7:58am UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/6 "2024-08-15T07:58:07Z")

</div>

Ah, right, this one is different. Taking a step back, `CheckLanguage` only tries to answer the question “Can I enable this language at all?”. You are wanting to ask a different question, one that is quite complex because you’re actually trying to check combinations of things.

What I would recommend is enable your languages before you set any language standards at all. That should succeed. Then you can use one of the `try_compile()`-based commands to check if you will be able to use a particular language standard for the combination of compilers that are enabled. If you end up working out that you do have CUDA, but not a toolchain you can actually use, then use some custom project-specific variable to indicate that and check that throughout your project where you need to provide different behavior for whether you have a suitable CUDA toolchain or not.

---

<div class="post-metadata">

### Author: ![krasznaa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/krasznaa/32/893_2.png) [@krasznaa](https://discourse.cmake.org/u/krasznaa)
#### Post date: [August 15, 2024, 8:46am UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/7 "2024-08-15T08:46:45Z")

</div>

The line here is really fuzzy though, isn’t it?

[CheckLanguage.cmake](https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/CheckLanguage.cmake?ref_type=heads) does forward a bunch of info from the main project down to the test project already. Even things like [CMAKE\_HIP\_PLATFORM](https://cmake.org/cmake/help/latest/variable/CMAKE_HIP_PLATFORM.html). So I’m not so sure that also forwarding `CMAKE_HIP_STANDARD` (or in my case `CMAKE_CUDA_STANDARD`) would be that fundamentally different. 🤔

But as I started, this is not a hill that I want to die on. I just wanted to raise the issue for consideration.

Best,  
Attila

---

<div class="post-metadata">

### Author: ![scivision](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/a87d85/32.png) [@scivision](https://discourse.cmake.org/u/scivision)
#### Post date: [August 15, 2024, 1:42pm UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/8 "2024-08-15T13:42:12Z")

</div>

[https://gitlab.kitware.com/cmake/cmake/-/merge\_requests/9739](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/9739)  
attempts to implement this change.

Edit: the MR was closed, with Brad King noting more discussion is needed.

---

<div class="post-metadata">

### Author: ![scivision](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/a87d85/32.png) [@scivision](https://discourse.cmake.org/u/scivision)
#### Post date: [August 15, 2024, 1:46pm UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/9 "2024-08-15T13:46:59Z")

</div>

Thinking about this more, I also think like Craig above that `try_compile()` is a more appropriate solution. I have several projects that combine C++ and Fortran functions calling each other, which can require specific compiler flags for older compilers. I use `try_compile()` to detect problems successfully.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [August 15, 2024, 2:05pm UTC](https://discourse.cmake.org/t/checklanguage-does-not-take-the-c-standard-into-account/11433/10 "2024-08-15T14:05:27Z")

</div>

> [@krasznaa](#):
>
> does forward a bunch of info from the main project down to the test project already

Those are about making sure the check project uses the same toolchain and target platform as `enable_language` would in the calling project.
