I recently tried upgrading CMake and got an unexpected build failure with Visual Studio 2022 suddenly returning LNK1189 (>65k symbols) for a large private project. After a bunch of testing different versions, it looks like the upgrade from CMake 4.0 to 4.1 changes the build flags in a way that results in a ton more symbols being exported when CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS is enabled.
The large failing project is private, but I created a minimal test project to debug what flags changed. I attached some text files with the flag lists for a minimal .dll test project, and it looks like /Zc:wchar_t, /Zc:inline, and /Zc:forScope were removed. From looking at the MSVC docs, /Zc:inline (Remove unreferenced COMDAT) seems like the most likely cause of LNK1189, since it was likely removing unused symbols that are now getting exported.
Was this change intended? I tried reading over the CMake 4.1 release notes, but haven’t seen anything that describes the changes I’m seeing.
The only change mentioning CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS that I can see for CMake 4.1 is MR 10791, but that MR looks like it should reduce the number of exported symbols and it doesn’t seem to be doing anything with the compiler flags you mentioned.
@brad.king Are you aware of any other changes related to CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS that went into CMake 4.1? This post sounds like there has been a regression.
I tried explicitly adding /Zc:inline to our internal project again, and it fixed the LNK1189 error. The number of exported symbols in the .def file dropped by 7x (200,000 down to ~27,000, lots of Eigen templates). Seems very likely that changing that flag was the cause.
Speculating a bit, it looks like the other two flags that changed (/Zc:wchar_t and /Zc:forScope) are on by default according to the MSVC docs, so I’m wondering if something changed to stop setting unnecessary flags and accidentally also affected /Zc:inline?
I poked around in the 4.1 changes list, and this looks relevant:
Microsoft.Cl.Common.props adds some cl flags by default, but for CMake they may not match what’s produced by command-line generators. If the -Zc:wchar_t, -Zc:forScope, and/or -Zc:inline flags are not specified by the project or user, suppress them.
Yes, removal of those flags was intentional. We are willing to make such changes without a policy when it is about consistency among generators. In this case MSBuild was adding flags the project didn’t specify. If a project needs particular flags, it should specify them, and then it will work in all generators, not just Visual Studio.
Thanks. That was sort of my impression from reading the PR, but good to get it confirmed.
Might have been useful to have a note in the CMake 4.1 change log, but I’m not actually sure how much time it would have saved me. I was already a couple of days into re-installing different MSVC toolsets and Windows SDK versions before I thought to check CMake. A bunch of stuff got updated around the same time, which kind of muddied the waters for a while.
In the end, the fix for my project was to enable pretty much every /Zc: conformance flag that wasn’t listed as “on by default” in the MSVC docs, including the /Zc:inline one in question here.