I found I had to set the variables before the initial project() line:
cmake_minimum_required(VERSION 3.12)
set(CMAKE_C_COMPILER_NAMES clang gcc icc cc)
set(CMAKE_CXX_COMPILER_NAMES clang++ g++ icpc c++ cxx)
project(foo C CXX)
If you visit the source code for the file that does this, you can see that it loads system-specific configuration files to set these variables. You might be able to make your solution more compatible by including those and reusing their results:
cmake_minimum_required(VERSION 3.12)
include(Platform/${CMAKE_SYSTEM_NAME}-Determine-C OPTIONAL)
include(Platform/${CMAKE_SYSTEM_NAME}-C OPTIONAL)
set(CMAKE_C_COMPILER_NAMES clang gcc icc cc ${CMAKE_C_COMPILER_NAMES})
include(Platform/${CMAKE_SYSTEM_NAME}-Determine-CXX OPTIONAL)
include(Platform/${CMAKE_SYSTEM_NAME}-CXX OPTIONAL)
set(CMAKE_CXX_COMPILER_NAMES clang++ g++ icpc c++ cxx ${CMAKE_CXX_COMPILER_NAMES})
project(foo C CXX)
But further review of CMake's internals and ideally communication with the cmake developers around the issue is advised here, because future implementation changes in cmake could alter the functionality. If you open an issue with them around the use-case, they may express the best available solution. They will then have that solution in mind for further code improvements, giving it better compatibility.