Backstory. 1) Starting with Qt 6.8, the prebuilt Qt for iOS SDK is built as static framework bundles instead of static libraries. That is done so that we can embed a privacy manifest into each framework bundle. 2) Up until CMake 3.28, CMake would not attempt to de-duplicate static libraries (or frameworks) on the command line. Starting with CMake 3.29, the CMP0156 policy was introduced to allow such de-duplication. 3) Since a while ago, Qt had its own policy handling for CMP0156, which it force sets to OLD, to disable any de-duplication. That was done to avoid possible regressions on platforms where link order matters. 4) A developer might add the -ObjC linker flag to a project, to ensure the linker retains all Objective-C categories it encounters in all the static libraries that were provided on the link line. Retaining in this case means that the /whole/ object file of a static library will be linked to the final executable. 5) The Apple ld linker (both the legacy and the new ld_prime one) can't cope with duplicate static frameworks on the link line when the -ObjC flag is used. It ends up throwing duplicate symbol errors, from trying to link the same object file from the same static framework more than once. The linker works just fine if the link line contains duplicate static libraries, rather than static frameworks. 6) When a project links against Qt6::Gui and Qt6::Core, the link line will contain Qt6::Core twice. This gets even more involved, when linking plugins, which cause static framework cycles, and thus a framework might appear multiple times. Thus, we have the situation that Qt forces the CMP0156 policy to OLD, Qt6::Core appears multiple times on the link line, no de-duplication is performed, the project adds the -ObjC flag, and the linker throws duplicate symbol errors. We can fix this by force setting the CMP0156 policy to NEW when targeting Apple platforms and using CMake 3.29+. A potential workaround for a project developer is to set the policy to NEW manually in their project. Unfortunately that doesn't work for older Qt versions. That's because CMake applies the policy value when add_executable is called, and the policy value in qt_add_executable is the one that is recorded when the function is defined. And the recorded policy is always OLD, because Qt6Config.cmake calls cmake_minimum_required with VERSION up to 3.21, which resets the policy value to OLD. So we have to force set the policy in qt_add_executable / qt_add_library via the existing __qt_internal_set_cmp0156 function. The __qt_internal_set_cmp0156 had some diagnostics to show a warning when the user modifies the policy themselves, but this never worked because of reason stated above: the policy value was always overridden in Qt6Config.cmake. To actually make the diagnostic work, there is now new code to save the policy value in the current directory scope, before Qt resets it. This only works if a project uses the find_package(Qt6 COMPONENTS Foo) signature. It won't work with a find_package(Qt6Core)-like signature. The policy value is not modified for platforms other than Apple ones for now. Amends 9702c3c78b2c16db6a9d0515d7d7698d9b064cd8 Pick-to: 6.8 6.5 Fixes: QTBUG-135978 Change-Id: I4d6e6c2a01e7092b417fc669d2aea40cf2dca578 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> (cherry picked from commit c20d7bcb86361d0c9f8af3807dcad9db1a3a5ca0) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
…
…
Description
Languages
C++
84.3%
HTML
4.9%
C
3.9%
CMake
3.6%
Objective-C++
2%
Other
0.8%