cmake-gui: environment variables stay defined when switching projects
Problem
CMake sets the environment variable CC
and CXX
when it finds the C and C++ compiler.
However, cmake-gui
does not undefine these environment variables again, when cmaking another project (or clearing the cache). It only sets them to the empty string.
This impacts e.g. the result of if (DEFINED ENV{CXX})
between runs of different (!) CMake projects.
Steps to reproduce the problem
You can reproduce the problem quite simply with the following CMakeLists.txt
file:
cmake_minimum_required(VERSION 3.18)
if (DEFINED ENV{CC})
message( STATUS "Before project command: CC env-variable is DEFINED! Value: `$ENV{CC}`" )
else()
message( STATUS "Before project command: CC env-variable is NOT DEFINED!" )
endif()
if (DEFINED ENV{CXX})
message( STATUS "Before project command: CXX env-variable is DEFINED! Value: `$ENV{CXX}`" )
else()
message( STATUS "Before project command: CXX env-variable is NOT DEFINED!" )
endif()
if (DEFINED CMAKE_C_COMPILER)
message( STATUS "Before project command: CMAKE_C_COMPILER variable is DEFINED! Value: `${CMAKE_C_COMPILER}`" )
else()
message( STATUS "Before project command: CMAKE_C_COMPILER variable is NOT DEFINED!" )
endif()
if (DEFINED CMAKE_CXX_COMPILER})
message( STATUS "Before project command: CMAKE_CXX_COMPILER variable is DEFINED! Value: `${CMAKE_CXX_COMPILER}`" )
else()
message( STATUS "Before project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!" )
endif()
if (DEFINED CACHE{CMAKE_C_COMPILER)
message( STATUS "Before project command: CMAKE_C_COMPILER cache variable is DEFINED! Value: `$CACHE{CMAKE_C_COMPILER}`" )
else()
message( STATUS "Before project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!" )
endif()
if (DEFINED CACHE{CMAKE_CXX_COMPILER})
message( STATUS "Before project command: CMAKE_CXX_COMPILER cache variable is DEFINED! Value: `$CACHE{CMAKE_CXX_COMPILER}`" )
else()
message( STATUS "Before project command: CMAKE_CXX_COMPILER cache variable is NOT DEFINED!" )
endif()
project( EnvTest VERSION 3.18.0 )
if (DEFINED ENV{CC})
message( STATUS "After project command: CC env-variable is DEFINED! Value: `$ENV{CC}`" )
else()
message( STATUS "After project command: CC env-variable is NOT DEFINED!" )
endif()
if (DEFINED ENV{CXX})
message( STATUS "After project command: CXX env-variable is DEFINED! Value: `$ENV{CXX}`" )
else()
message( STATUS "After project command: CXX env-variable is NOT DEFINED!" )
endif()
if (DEFINED CMAKE_C_COMPILER)
message( STATUS "After project command: CMAKE_C_COMPILER variable is DEFINED! Value: `${CMAKE_C_COMPILER}`" )
else()
message( STATUS "After project command: CMAKE_C_COMPILER variable is NOT DEFINED!" )
endif()
if (DEFINED CMAKE_CXX_COMPILER})
message( STATUS "After project command: CMAKE_CXX_COMPILER variable is DEFINED! Value: `${CMAKE_CXX_COMPILER}`" )
else()
message( STATUS "After project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!" )
endif()
if (DEFINED CACHE{CMAKE_C_COMPILER)
message( STATUS "After project command: CMAKE_C_COMPILER cache variable is DEFINED! Value: `$CACHE{CMAKE_C_COMPILER}`" )
else()
message( STATUS "After project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!" )
endif()
if (DEFINED CACHE{CMAKE_CXX_COMPILER})
message( STATUS "After project command: CMAKE_CXX_COMPILER cache variable is DEFINED! Value: `$CACHE{CMAKE_CXX_COMPILER}`" )
else()
message( STATUS "After project command: CMAKE_CXX_COMPILER cache variable is NOT DEFINED!" )
endif()
Just run cmake-gui
, cmake this CMakeLists.txt
file into one directory /tmp/build1
, and afterwards into a directory /tmp/build2
. You will notice a difference in the output.
Example output
Output for /tmp/build1
:
Before project command: CC env-variable is NOT DEFINED!
Before project command: CXX env-variable is NOT DEFINED!
Before project command: CMAKE_C_COMPILER variable is NOT DEFINED!
Before project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!
Before project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!
Before project command: CMAKE_CXX_COMPILER cache variable is NOT DEFINED!
The C compiler identification is GNU 9.3.0
The CXX compiler identification is GNU 9.3.0
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working C compiler: /usr/bin/cc - skipped
Detecting C compile features
Detecting C compile features - done
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Check for working CXX compiler: /usr/bin/c++ - skipped
Detecting CXX compile features
Detecting CXX compile features - done
After project command: CC env-variable is DEFINED! Value: `/usr/bin/cc`
After project command: CXX env-variable is DEFINED! Value: `/usr/bin/c++`
After project command: CMAKE_C_COMPILER variable is DEFINED! Value: `/usr/bin/cc`
After project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!
After project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!
After project command: CMAKE_CXX_COMPILER cache variable is DEFINED! Value: `/usr/bin/c++`
Configuring done
Output for /tmp/build2
:
Before project command: CC env-variable is DEFINED! Value: ``
Before project command: CXX env-variable is DEFINED! Value: ``
Before project command: CMAKE_C_COMPILER variable is NOT DEFINED!
Before project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!
Before project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!
Before project command: CMAKE_CXX_COMPILER cache variable is NOT DEFINED!
The C compiler identification is GNU 9.3.0
The CXX compiler identification is GNU 9.3.0
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working C compiler: /usr/bin/cc - skipped
Detecting C compile features
Detecting C compile features - done
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Check for working CXX compiler: /usr/bin/c++ - skipped
Detecting CXX compile features
Detecting CXX compile features - done
After project command: CC env-variable is DEFINED! Value: `/usr/bin/cc`
After project command: CXX env-variable is DEFINED! Value: `/usr/bin/c++`
After project command: CMAKE_C_COMPILER variable is DEFINED! Value: `/usr/bin/cc`
After project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!
After project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!
After project command: CMAKE_CXX_COMPILER cache variable is DEFINED! Value: `/usr/bin/c++`
Configuring done
These two outputs differ in the first two lines:
--- Output of /tmp/build1
+++ Output of /tmp/build2
@@ -1,5 +1,5 @@
-Before project command: CC env-variable is NOT DEFINED!
-Before project command: CXX env-variable is NOT DEFINED!
+Before project command: CC env-variable is DEFINED! Value: ``
+Before project command: CXX env-variable is DEFINED! Value: ``
Before project command: CMAKE_C_COMPILER variable is NOT DEFINED!
Before project command: CMAKE_CXX_COMPILER variable is NOT DEFINED!
Before project command: CMAKE_C_COMPILER cache variable is NOT DEFINED!
Analysis
CMake sets the environment-variables CC
and CXX
but cmake-gui
seems to be unable to unset and undefine them if cmaking another directory.
CMake sets the environment variables CC
and CXX
when it searches for (and finds) the C and C++ compiler, if the user did not specify them explicitly (by proving values for CMAKE_C_COMPILER
and CMAKE_CXX_COMPILER
). This is triggered when CMake encounters the project
or enable_language
command.
However, cmake-gui
is not properly undefining these environment variables again when clearing the CMake cache (by clicking on File --> Delete Cache
in the menu entry of cmake-gui
) or when configuring into another build-directory or an entirely different project.
As you might have noticed, the above example CMakeLists.txt
file demonstrates another inconsistency (which also occurs with cmake
or ccmake
). The CMAKE_CXX_COMPILER
variable will be set as CMake cache variable, while the CMAKE_C_COMPILER
variable will just be set as plain CMake variable.