Is there a downside for a toolchain to set vars in cache instead of _INIT?

One of game console vendor official toolchains sets variables like CMAKE_CXX_FLAGS as CACHE vars, instead of setting CMAKE_CXX_FLAGS_INIT and let CMake propagate it.

I found it when tried to create wrapper for vendor toolchain and saw that my updates to CMAKE_CXX_FLAGS_INIT has no effect. Did they create toolchain incorrectly then? What is the downside of settings cache vars directly instead of (as I understand it) recommended approach of setting just _INIT vars.

Setting the CMAKE_<lang>_FLAGS_INIT variables is the more correct thing to do. If a toolchain file sets CMAKE_<lang>_FLAGS instead, there are a few consequences:

  • Depending on what policies the project has set, this can discard a variable by the same name if it has already been set by the user or the project.
  • If the toolchain file is using FORCE when setting CMAKE_<lang>_FLAGS, it will discard any cache variable set by the user. This can hinder the user from doing things like experimenting with flags (e.g. different debugging levels or info formats), or adding flags for use cases the toolchain file didn’t consider (e.g. using sanitisers).
  • It prevents CMake from providing its standard set of flags. The CMAKE_<lang>_FLAGS_INIT variables are usually combined with default values CMake gives.

There are scenarios where a user might need to set CMAKE_<lang>_FLAGS in a toolchain file to achieve a particular set of flags. If a vendor is supplying a toolchain file, they can’t know all the scenarios a user may face, so the vendor should not force the flags with CMAKE_<lang>_FLAGS. They should use CMAKE_<lang>_FLAGS_INIT instead, unless the default flags CMAKE automatically combines them with are known to cause problems.

1 Like

I was incorrect in my initial assessment, _FLAGS vars are not set as CACHE FORCE, but just as normal vars. I suppose this way users are still free to experiment with flags after project was first configured. Vendor do set other vars as CACHE FORCE, like CMAKE_CXX_COMPILER, but I guess that is fine because those vars 100% should never be altered by user (that’s the purpose of the toolchain after all).

It leaves downside of not being able to provide initial set of vars in CMAKE_CXX_FLAGS_INIT as a configure option, but it can be mitigated by adding add_compile_options early in CMakeLists.txt file.

As for default flags CMake might be adding, what they could be? Vendor ships toolchain with custom CMAKE_SYSTEM_NAME, so unlikely CMake can/should have any meaningful defaults.

Overall, without CACHE FORCE their approach doesn’t have much downside I can see. I’ll still open support request asking to switch to a recommended way of using _INIT vars, but case to do so is not as strong as I thought initially.

It depends on the toolchain. For example, it is common for embedded toolchains from vendors to be based on gcc or clang. While the toolchain might be targeting some less common processor or architecture, CMake will still recognise them as a gcc or clang compiler and set up appropriate default flags for debugging, optimisation, etc.

1 Like