# A way to force "Check for working ${LANG} compiler" test?

**URL:** https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026
**Category:** Usage
**Tags:** os:linux
**Created:** [February 7, 2024, 3:00pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026 "2024-02-07T15:00:16Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![al42and](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9fc29f/32.png) [@al42and](https://discourse.cmake.org/u/al42and)
#### Post date: [February 7, 2024, 3:00pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/1 "2024-02-07T15:00:16Z")

</div>

Hi!

I would like to ask if there is a “proper” way to _force_ the compiler sanity check even if it passes the ABI check?

For our package, a lot of users are trying to do `-DCMAKE_CXX_COMPILER=gcc -DCMAKE_C_COMPILER=gcc`, which CMake accepts initially, leading to obscure linking errors down the line. It would be nice if there was a way to force CMake to _not_ skip the compiler check, even if the compiler is known, so that users get a better error message.

Example (Ubuntu 22.04, CMake 3.28.2): `gcc` is considered a working C++ compiler, but it fails the very basic `try_compile`:

```console
$ cmake -S. -Bbuild/ -DCMAKE_CXX_COMPILER=gcc
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/gcc - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Trying to compile a sample C++ file
CMake Error at CMakeLists.txt:11 (message):
  Cannot compile a sample file: Change Dir:
  '/home/aland/tmp/cmake-test/build/CMakeFiles/CMakeTmp'

  Run Build Command(s): /usr/bin/cmake -E env VERBOSE=1 /usr/bin/gmake -f
  Makefile cmTC_7e4ff/fast

  /usr/bin/gmake -f CMakeFiles/cmTC_7e4ff.dir/build.make
  CMakeFiles/cmTC_7e4ff.dir/build

  gmake[1]: Entering directory
  '/home/aland/tmp/cmake-test/build/CMakeFiles/CMakeTmp'

  Building CXX object CMakeFiles/cmTC_7e4ff.dir/main.cpp.o

  /usr/bin/gcc -std=gnu++17 -o CMakeFiles/cmTC_7e4ff.dir/main.cpp.o -c
  /home/aland/tmp/cmake-test/main.cpp

  Linking CXX executable cmTC_7e4ff

  /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_7e4ff.dir/link.txt
  --verbose=1

  /usr/bin/gcc CMakeFiles/cmTC_7e4ff.dir/main.cpp.o -o cmTC_7e4ff

  /usr/bin/ld: CMakeFiles/cmTC_7e4ff.dir/main.cpp.o: in function
  `__static_initialization_and_destruction_0(int, int)':

  main.cpp:(.text+0x3b): undefined reference to `std::ios_base::Init::Init()'

  /usr/bin/ld: main.cpp:(.text+0x56): undefined reference to
  `std::ios_base::Init::~Init()'

  collect2: error: ld returned 1 exit status

  gmake[1]: *** [CMakeFiles/cmTC_7e4ff.dir/build.make:99: cmTC_7e4ff] Error 1

  gmake[1]: Leaving directory
  '/home/aland/tmp/cmake-test/build/CMakeFiles/CMakeTmp'

  gmake: *** [Makefile:127: cmTC_7e4ff/fast] Error 2

-- Configuring incomplete, errors occurred!

```

Here’s `CMakeLists.txt` used:

```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

message(STATUS "Trying to compile a sample C++ file")
try_compile(MAIN_CPP_COMPILES "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/main.cpp" OUTPUT_VARIABLE MAIN_CPP_ERROR)

if (NOT MAIN_CPP_COMPILES)
    message(FATAL_ERROR "Cannot compile a sample file: ${MAIN_CPP_ERROR}")
endif ()

```

`main.cpp`:

```cpp
#include <iostream>

int main()
{
    return 0;
}

```

---

<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: [February 7, 2024, 6:10pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/2 "2024-02-07T18:10:37Z")

</div>

I indicate compiler selection by setting environment variables CC CXX etc.

On Unix-like OS:

```auto
export CC=gcc CXX=g++ 

```

This must be before the first CMake command.

---

<div class="post-metadata">

### Author: ![al42and](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9fc29f/32.png) [@al42and](https://discourse.cmake.org/u/al42and)
#### Post date: [February 7, 2024, 6:19pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/3 "2024-02-07T18:19:38Z")

</div>

From what I can tell, this will suffer from the same problem if the user sets `CXX=gcc`: CMake will happily accept the compiler without any diagnostics, only for it to fail at the build stage.

What I want is to have a way to force CMake to actually check that compiler works. It is always possible to add `try_compile` with a trivial C++ code to project’s CMakeLists.txt, but it feels like there should be a better, standardized way to check that the supplied C++ compiler is actually a C++ compiler.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 7, 2024, 8:51pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/4 "2024-02-07T20:51:20Z")

</div>

Does `-DCMAKE_<LANG>_ABI_COMPILED=FALSE` work if passed at first configure time?

---

<div class="post-metadata">

### Author: ![al42and](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9fc29f/32.png) [@al42and](https://discourse.cmake.org/u/al42and)
#### Post date: [February 7, 2024, 10:21pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/5 "2024-02-07T22:21:05Z")

</div>

Thanks for the hint. That indeed forces the compiler check instead of skipping, but, surprisingly, `gcc` is still considered a working C++ compiler:

```console
$ cmake -S. -Bbuild/ -DCMAKE_CXX_COMPILER=gcc -DCMAKE_CXX_ABI_COMPILED=FALSE
-- The CXX compiler identification is GNU 11.4.0
-- Check for working CXX compiler: /usr/bin/gcc
-- Check for working CXX compiler: /usr/bin/gcc - works
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Trying to compile a sample C++ file
CMake Error at CMakeLists.txt:11 (message):
  Cannot compile a sample file: Change Dir:
[same error message as in OP]

```

Looking at the [source code](https://gitlab.kitware.com/cmake/cmake/-/blob/b8ed46eade08186114b754d28226c5153fcc0f29/Modules/CMakeTestCXXCompiler.cmake#L38-66), it appears that only compiler definition is checked, but no actual C++ symbols are used. While, for my case, the problem occurs when trying to link to the C++ standard library.

---

<div class="post-metadata">

### Author: ![fdk17](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/f/ea666f/32.png) [@fdk17](https://discourse.cmake.org/u/fdk17)
#### Post date: [February 7, 2024, 11:16pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/6 "2024-02-07T23:16:35Z")

</div>

I recall that using gcc as a C++ compiler needs special flags to link with the C++ standard libraries. Are you sure you don’t want to use g++ for the CXX compiler?

---

<div class="post-metadata">

### Author: ![al42and](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9fc29f/32.png) [@al42and](https://discourse.cmake.org/u/al42and)
#### Post date: [February 7, 2024, 11:46pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/7 "2024-02-07T23:46:57Z")

</div>

> [@fdk17](#):
>
> Are you sure you don’t want to use g++ for the CXX compiler?

_I_ definitely want to use `g++` 🙂 But some of our users are, by mistake, setting both C and C++ compilers to `gcc`, which results in rather confusing error messages mid-configure or mid-build (see text above, I don’t think it’s easy to figure out what is wrong).

So, I want to know if there is a way to obtain a good diagnostic from CMake in such a case. Since CMake already does compiler sanity checks, and accidentally setting the wrong compiler seems like an easy mistake to make, I hope that there should be some better way to do it then writing our own `try_compile` test to double-check the compiler sanity after CMake already deemed it working.

So far, it seems there are two problems:

- By default, the compiler is not actually checked as long as it passes the ABI checks. That can be avoided by forcing `CMAKE_CXX_ABI_COMPILED` to false, per @ben.boeckel’s suggestion.
- When the check is forced by the method above, CMake still reports “Check for working CXX compiler: /usr/bin/gcc - works” (or even “Check for working CXX compiler: /usr/bin/gfortran - works”). To me, “working CXX compiler” implies that “try\_compile” a simple C++ source should succeed without any extra flags; but it does not.
  - [CMake has an explicit handling of “C++ compiler is set to a C compiler” problem](https://gitlab.kitware.com/cmake/cmake/-/blob/b8ed46eade08186114b754d28226c5153fcc0f29/Modules/CMakeTestCXXCompiler.cmake#L41-45) which does not catch this very situation, so perhaps the current behavior is a defect?

---

<div class="post-metadata">

### Author: ![fdk17](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/f/ea666f/32.png) [@fdk17](https://discourse.cmake.org/u/fdk17)
#### Post date: [February 8, 2024, 1:27am UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/8 "2024-02-08T01:27:25Z")

</div>

FYI,

In `cmake/Modules/CMakeCXXCompilerABI.cpp` it has this stanza:

```auto
#ifndef __cplusplus
# error "A C compiler has been selected for C++."
#endif

#include "CMakeCompilerABI.h"

```

This stanza should detect a `c` compiler being used for `c++` when compiling this file. I believe this is the standard way of detecting `c++` compilers.

But `gcc` has its determine language by file name suffix feature.

```auto
 -x language
           Specify explicitly the language for the following input files
           (rather than letting the compiler choose a default based on
           the file name suffix).

```

Which causes `gcc` to act like a `c++` compiler for `c++` source code. However `gcc`, when driving the link step, performs linking for `c` executables. Makes sense in the context that compiling and linking are two different operations.

Even if you altered the ABI tests to call a C++ standard library call, the user still could set `CMAKE_TRY_COMPILE_TARGET_TYPE` to `STATIC_LIBRARY` which turns off linking when `try_compile` is used. So, it wouldn’t catch the problem all the time.

Good luck!

---

<div class="post-metadata">

### Author: ![al42and](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9fc29f/32.png) [@al42and](https://discourse.cmake.org/u/al42and)
#### Post date: [February 11, 2024, 11:42pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/9 "2024-02-11T23:42:10Z")

</div>

> [@fdk17](#):
>
> However `gcc`, when driving the link step, performs linking for `c` executables. Makes sense in the context that compiling and linking are two different operations.

True.

But, since CMake uses the same binary as a linker driver, I would argue that it’s reasonable to expect that both aspects are tested (in a single test or separately is less of an issue from user’s perspective).

> [@fdk17](#):
>
> I believe this is the standard way of detecting `c++` compilers.

Yeah. I’m a bit surprised that GCC did not consider that people are relying on such behavior. True, compiling and linking are separate steps, but people who use different binaries or bother with explicit linking to the C++ std library are likely to be able to differentiate between different compiler drivers for different source files.

> [@fdk17](#):
>
> Even if you altered the ABI tests to call a C++ standard library call, the user still could set `CMAKE_TRY_COMPILE_TARGET_TYPE` to `STATIC_LIBRARY` which turns off linking when `try_compile` is used. So, it wouldn’t catch the problem all the time.

Thanks for pointing out that possibility. But, I guess, for now we would resort to a simple `try_compile` check: should be robust enough to catch simple user errors.

---

<div class="post-metadata">

### Author: ![fdk17](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/f/ea666f/32.png) [@fdk17](https://discourse.cmake.org/u/fdk17)
#### Post date: [February 12, 2024, 11:37pm UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/10 "2024-02-12T23:37:17Z")

</div>

FYI,  
[Warn if gcc is used as CXX\_COMPILER? (#20385) · Issues · CMake / CMake · GitLab (kitware.com)](https://gitlab.kitware.com/cmake/cmake/-/issues/20385)

---

<div class="post-metadata">

### Author: ![al42and](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9fc29f/32.png) [@al42and](https://discourse.cmake.org/u/al42and)
#### Post date: [February 13, 2024, 10:34am UTC](https://discourse.cmake.org/t/a-way-to-force-check-for-working-lang-compiler-test/10026/11 "2024-02-13T10:34:54Z")

</div>

Thanks!
