Users could pass flags by environment variables like CFLAGS/CXXFLAGS/LDFLAGS
or by using CMAKE_<LANG>_FLAGS_INIT/CMAKE_<t>_LINKER_FLAGS_INIT. So this
toolchain file should append to INIT flags instead. Otherwise, user
flags would be discarded here by assigning to CMAKE_<LANG>_FLAGS
directly.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
User could pass flags by environment variables like CFLAGS/CXXFLAGS/LDFLAGS or by using CMAKE_<LANG>_FLAGS_INIT/CMAKE_<t>_LINKER_FLAGS_INIT. So this toolchain file should append to INIT flags instead. Otherwise, user flags would be discarded here by assigning to CMAKE_<LANG>_FLAGS directly.
Can you elaborate a bit more here so I follow properly (with more explanation of exactly what cmake does here)? If the user has set e.g. CXXFLAGS, that does end up picked up by cmake and set in CMAKE_CXX_FLAGS_INIT - is that correct? What happened before, when we appended things into CMAKE_CXX_FLAGS without taking CMAKE_CXX_FLAGS_INIT into account - were the flags from CXXFLAGS and/or CMAKE_CXX_FLAGS_INIT missed/forgotten/overridden? Can you explain the implicit cmake behavious that are at play here?
Also, for the native tool build, target flags should not be used.
Flags specified to the main cmake build (CMAKE_<LANG>_FLAGS*) shouldn't be propagated automatically to the inner native cmake build, or am I missing something?
cmake uses CMAKE_<LANG>_FLAGS_INIT (INIT flags themselves are initialized by environment variables like CFLAGS/CXXFLAGS/LDFLAGS, or by a cmake toolchain file) to initialize CMAKE_<LANG>_FLAGS. If CMAKE_<LANG>_FLAGS is set by the user directly, cmake will not initialize it from CMAKE_<LANG>_FLAGS_INIT anymore, so the user-specified flags are lost. Docs on CMAKE_<LANG>_FLAGS_INIT suggests that the preferred behavior is for a toolchain file to manipulate INIT flags.
Also, for the native tool build, target flags should not be used.
Flags specified to the main cmake build (CMAKE_<LANG>_FLAGS*) shouldn't be propagated automatically to the inner native cmake build, or am I missing something?
That's right except when users specify flags by environment vars which will be picked up by sub-cmake through the above-described initialization process. Setting CMAKE_<LANG>_FLAGS to empty here is to avoid that.
llvm/cmake/platforms/WinMsvc.cmake | ||
---|---|---|
254–258 | I'm not a fan of this. A pattern I like to follow is to pass a CMAKE_TOOLCHAIN_FILE to CROSS_TOOLCHAIN_FLAGS_NATIVE, so that the native build flags get configured via a toolchain file instead of ad-hoc variable setting. Pre-set cached copies of these variables will interfere with that toolchain file's ability to set flags, and in particular, it'll break the toolchain file's use of the *_INIT variables, which is kinda ironic given the purpose of this diff :) Would unsetting the env vars in the toolchain file instead accomplish the same goal? | |
282–283 | I think we can avoid having the two separate variables, and just do a direct setting, if we make sure this toolchain file is only evaluated once per CMake invocation. Now that we've raised our minimum CMake version, just adding include_guard(GLOBAL) at the top ought to do the trick. It's fine to leave that for a follow-up change (or not do it at all). |
Somehow this change broke cross compiling for 32-bit windows using WinMsvc.cmake. Cmake ends up adding /machine:x64 to the linker flags during one of its first checks, and that fails.
Thanks for reporting this. What's your env output look like during config and build time? How do I reproduce it locally?
Hmm. Are you passing any CMAKE_C_FLAGS or CMAKE_CXX_FLAGS directly as part of your configuration? That'd make the CMAKE_*_FLAGS_INIT in this file be ignored.
The only variables I'm passing: CMAKE_C_COMPILER_TARGET, CMAKE_CXX_COMPILER_TARGET, CMAKE_ASM_COMPILER_TARGET, CMAKE_BUILD_TYPE, LLVM_ENABLE_ASSERTIONS, LLVM_CONFIG_PATH, COMPILER_RT_DEFAULT_TARGET_ONLY, CMAKE_TOOLCHAIN_FILE, LLVM_NATIVE_TOOLCHAIN, MSVC_BASE, WINSDK_BASE, WINSDK_VER, HOST_ARCH.
CMakeCCompilerId.c ends up being compiled with no flags at all.
It still happens when I cut down to CMAKE_TOOLCHAIN_FILE, LLVM_NATIVE_TOOLCHAIN, MSVC_BASE, WINSDK_BASE, WINSDK_VER and HOST_ARCH.
It turns out CMAKE_*_FLAGS is only initialized from CMAKE_*_FLAGS_INIT _after_ CMAKE_DETERMINE_COMPILER_ID is done.
I'm not a fan of this. A pattern I like to follow is to pass a CMAKE_TOOLCHAIN_FILE to CROSS_TOOLCHAIN_FLAGS_NATIVE, so that the native build flags get configured via a toolchain file instead of ad-hoc variable setting. Pre-set cached copies of these variables will interfere with that toolchain file's ability to set flags, and in particular, it'll break the toolchain file's use of the *_INIT variables, which is kinda ironic given the purpose of this diff :)
Would unsetting the env vars in the toolchain file instead accomplish the same goal?