Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. iOS -ObjC link option leads to "duplicate symbol" for QtCore.framework
Forum Updated to NodeBB v4.3 + New Features

iOS -ObjC link option leads to "duplicate symbol" for QtCore.framework

Scheduled Pinned Locked Moved Solved Mobile and Embedded
2 Posts 1 Posters 247 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    MarcoDC
    wrote on 19 May 2025, 12:44 last edited by MarcoDC
    #1

    Im am working on porting my Qt app (with support for mac, iOS and Android) from Qt 5.15.17 to Qt 6.9 (which already worked out so far :D) and now from QMake using .pro files to CMake.

    The initial cause for my problem was this error message when trying to call
    "[FIRApp configure]" from my objective-c file application.mm:

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSData gul_dataByGzippingData:error:]: unrecognized selector sent to class 0x1f10f4610'
    *** First throw call stack:
    (0x188a725fc 0x185fed244 0x188bcb008 0x188a755c8 0x188a74ef0 0x1012ce1fc 0x1010cd7d4 0x1010cd60c 0x190806fa8 0x19080a45c 0x19081e620 0x19081d1e8 0x190818ec0 0x1908196c4 0x2137dc644 0x2137da474)
    libc++abi: terminating due to uncaught exception of type NSException
    

    After a quick search I noted that this is possibly because I did not compile with "-ObjC" flag.

    So I tried to do some modifications in my project:
    1. I tried to use the flag "-ObjC" using this block

    target_link_options(${PROJECT_NAME} PUBLIC -ObjC)
    

    But when trying to compile, I receive a lot of errors like

    Undefined symbols for architecture arm64:
      "__swift_FORCE_LOAD_$_swiftCompatibility50", referenced from:
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_FirebaseCoreInternal in FirebaseCoreInternal[4](_ObjC_HeartbeatController.o)
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_FirebaseCrashlytics in FirebaseCrashlytics[84](CrashlyticsRemoteConfigManager.o)
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_FirebaseRemoteConfigInterop in FirebaseRemoteConfigInterop[4](RemoteConfigConstants.o)
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_FirebaseSessions in FirebaseSessions[6](ApplicationInfo.o)
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_Promises in Promises[4](Promise.o)
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_GoogleMobileAds in GoogleMobileAds[arm64][430](GADMarketplaceKitSignals.o)
          __swift_FORCE_LOAD_$_swiftCompatibility50_$_FBAdMAISKOverlayManager in FBAudienceNetwork[4](FBAdMAISKOverlayManager.o)
          ...
    "__swift_FORCE_LOAD_$_swiftCompatibilityConcurrency", referenced from:
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_FirebaseCoreInternal in FirebaseCoreInternal[4](_ObjC_HeartbeatController.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_FirebaseCrashlytics in FirebaseCrashlytics[84](CrashlyticsRemoteConfigManager.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_FirebaseRemoteConfigInterop in FirebaseRemoteConfigInterop[4](RemoteConfigConstants.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_FirebaseSessions in FirebaseSessions[6](ApplicationInfo.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_FirebaseSharedSwift in FirebaseSharedSwift[4](FirebaseDataEncoder.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_Promises in Promises[4](Promise.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency_$_GoogleMobileAds in GoogleMobileAds[arm64][430](GADMarketplaceKitSignals.o)
          ...
      "__swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements", referenced from:
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_FirebaseCoreInternal in FirebaseCoreInternal[4](_ObjC_HeartbeatController.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_FirebaseCrashlytics in FirebaseCrashlytics[84](CrashlyticsRemoteConfigManager.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_FirebaseRemoteConfigInterop in FirebaseRemoteConfigInterop[4](RemoteConfigConstants.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_FirebaseSessions in FirebaseSessions[6](ApplicationInfo.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_Promises in Promises[4](Promise.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_GoogleMobileAds in GoogleMobileAds[arm64][430](GADMarketplaceKitSignals.o)
          __swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements_$_FBAdMAISKOverlayManager in FBAudienceNetwork[4](FBAdMAISKOverlayManager.o)
          ...
    ld: symbol(s) not found for architecture arm64
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    

    2. Thats why I added the base swift directories to my linker settings using

    target_link_directories(${PROJECT_NAME} PUBLIC
            "/usr/lib/swift"
            "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos"
        )
    

    But now this leads to a lot of duplicated symbol errors:

    duplicate symbol '_OBJC_METACLASS_$_WeakPointerLifetimeTracker' in:
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][166](qcore_mac.mm.o)
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][166](qcore_mac.mm.o)
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][166](qcore_mac.mm.o)
    duplicate symbol '_OBJC_CLASS_$_RunLoopModeTracker' in:
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][168](qeventdispatcher_cf.mm.o)
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][168](qeventdispatcher_cf.mm.o)
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][168](qeventdispatcher_cf.mm.o)
    duplicate symbol 'AppleUnifiedLogger::messageHandler(QtMsgType, QMessageLogContext const&, QString const&, QString const&)' in:
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][166](qcore_mac.mm.o)
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][166](qcore_mac.mm.o)
        /Users/user/Qt/6.9.0/ios/lib/QtCore.framework/QtCore[arm64][166](qcore_mac.mm.o)
    ...
    

    After a few days of research (and ChatGPTing like a vibe coder xD) I tried a lot of things but wasn't really able to solve this problem at all /
    Am I missing something important here or doing anything completely wrong?

    3. I have created a new empty Test project and tried to dabble around with some flags and compiler properties to embed swift libraries like
    XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES
    but the problem is the same :/

    ld: 98 duplicate symbols
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)

    cmake_minimum_required(VERSION 3.16)
    
    project(Test VERSION 1.00 LANGUAGES C CXX OBJC OBJCXX Swift)
    
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    # Set C++ standard (if needed)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    set(BUILD_SHARED_LIBS OFF)
    
    find_package(Qt6 REQUIRED COMPONENTS Quick)
    
    qt_standard_project_setup(REQUIRES 6.9)
    
    qt_add_executable(appTest
        main.cpp
    )
    
    qt_add_qml_module(appTest
        URI Test
        VERSION 1.0
        QML_FILES
            Main.qml
    )
    
    # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
    # If you are developing for iOS or macOS you should consider setting an
    # explicit, fixed bundle identifier manually though.
    set_target_properties(appTest PROPERTIES
    
        MACOSX_BUNDLE TRUE
        WIN32_EXECUTABLE TRUE
    #    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appTest
    #    MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/ios/Info.plist"
        MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
        MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
        # Sign embedded frameworks
    #    XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
        # Embed Swift libraries
    #    XCODE_ATTRIBUTE_ENABLE_BITCODE "NO"
    #    XCODE_ATTRIBUTE_SWIFT_VERSION "5.6"
        XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES "NO"
    #    XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
    )
    
    target_link_options(appTest PUBLIC -ObjC) # -lz -lswiftCompatibility51 -lswiftCompatibility56)
    
    # Link additional Library directory for swift support
    #target_link_directories(appTest PRIVATE
    #    "/usr/lib/swift"
    #    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos"
    #)
    
    target_link_libraries(appTest
        PRIVATE Qt6::Quick
    )
    
    include(GNUInstallDirs)
    install(TARGETS appTest
        BUNDLE DESTINATION .
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    )
    
    1 Reply Last reply
    0
    • M Offline
      M Offline
      MarcoDC
      wrote 29 days ago last edited by
      #2

      I actually found a solution to my problem :DDD

      In fact this was a bug in Qt since 6.7.3:
      https://bugreports.qt.io/browse/QTBUG-135978?gerritReviewStatus=Open
      which now seems to be fixed https://codereview.qt-project.org/c/qt/qtbase/+/643588

      A workaround for now suggest here https://bugreports.qt.io/browse/QTBUG-132412
      is to

      Configure with cmake 3.29+ and the extra -DQT_FORCE_CMP0156_TO_NEW=ON option.

      which I did by setting the policy in my root project cmake file right before find_package:

      # Enable CMP0156 explicitly to prevent duplicate symbol errors when using -ObjC linker flag
      if (POLICY CMP0156)
          message(STATUS "Setting CMP0156 policy to NEW...")
          set(QT_FORCE_CMP0156_TO_NEW ON CACHE BOOL "Force CMake policy CMP0156 to NEW behavior for Qt6")
      elseif ()
          message(ERROR "CMP0156 policy not available! Please switch to cmake 3.29+ and Qt6.9")
      endif ()
      
      1 Reply Last reply
      2
      • M MarcoDC has marked this topic as solved 29 days ago

      1/2

      19 May 2025, 12:44

      • Login

      • Login or register to search.
      1 out of 2
      • First post
        1/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved