DataDog / dd-sdk-ios

Datadog SDK for iOS - Swift and Objective-C.
Apache License 2.0
219 stars 127 forks source link

Cannot build for testing: Undefined symbol #1449

Closed gmoraleda closed 4 months ago

gmoraleda commented 1 year ago

The issue

I've integrated DD in a custom Swift Package. Importing that package into my app target works flawlessly. I'm facing issues when building for testing. The compiler throws the following errors:

image

Datadog SDK version:

2.1.2

Last working Datadog SDK version:

N/A

Dependency Manager:

SPM

Xcode version:

Version 14.3 (14E222b)

Swift version:

swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)

Deployment Target:

iOS 15: iPhone

macOS version:

13.5.1 (22G90)

This is my Package.swift manifest:

let package = Package(
    name: "CapmoLogging",
    platforms: [
        .iOS(.v15),
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "CapmoLogging",
            targets: ["CapmoLogging"]
        ),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", exact: "3.8.1"),
        .package(url: "https://github.com/Datadog/dd-sdk-ios.git", exact: "2.1.2"),
        .package(url: "https://github.com/firebase/firebase-ios-sdk.git", exact: "10.14.0"),
        .package(url: "https://github.com/apollographql/apollo-ios.git", exact: "1.4.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "CapmoLogging",
            dependencies: [
                .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"),
                .product(name: "DatadogCore", package: "dd-sdk-ios"),
                .product(name: "DatadogLogs", package: "dd-sdk-ios"),
                .product(name: "DatadogRUM", package: "dd-sdk-ios"),
                .product(name: "DatadogTrace", package: "dd-sdk-ios"),
                .product(name: "FirebaseCrashlytics", package: "firebase-ios-sdk"),
                .product(name: "Apollo", package: "apollo-ios"),
            ]
        ),
        .testTarget(
            name: "CapmoLoggingTests",
            dependencies: ["CapmoLogging"]
        ),
    ]
)

The issue seems to be around DatadogInternal, which I require to inject the DatatodURLSessionDelegate in my Apollo client:

import Apollo
import DatadogTrace
import Foundation

// Helpers https://github.com/DataDog/dd-sdk-ios/issues/416
// https://github.com/ncreated/iOSTutorial/pull/1/files#diff-cbdc81feecfa385baf9dbbbde18afc412bddea7518c879a2e3a393ac28d298f5

public final class DatadogURLSessionClient: URLSessionClient, __URLSessionDelegateProviding {
    public let ddURLSessionDelegate = DatadogURLSessionDelegate()

    override public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
        ddURLSessionDelegate.urlSession(session, task: task, didFinishCollecting: metrics)
        super.urlSession(session, task: task, didFinishCollecting: metrics)
    }

    override public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        ddURLSessionDelegate.urlSession(session, task: task, didCompleteWithError: error)
        super.urlSession(session, task: task, didCompleteWithError: error)
    }

    override public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        ddURLSessionDelegate.urlSession(session, dataTask: dataTask, didReceive: data)
        super.urlSession(session, dataTask: dataTask, didReceive: data)
    }
}
gmoraleda commented 1 year ago

~I was able to solve this issue by specifying my library type as dynamic in the Package manifest. In case it helps other folks.~

gmoraleda commented 1 year ago

Sadly, the Testflight version would crash immediately due to the missing dynamic library. I reopen the issue in case anyone has other ideas about how to fix this.

pm-dev commented 5 months ago

This is a real issue we've been seeing for a year+. One way to work past it might be to xcodebuild build-for-testing then xcodebuild test-without-building. I haven't found a workaround that allows executing tests within Xcode.

Screenshot 2024-05-14 at 4 42 25 PM
maxep commented 5 months ago

Hey @gmoraleda and @pm-dev

I'm very sorry for such a long reply, we totally missed it.

I'm not able to replicate, here the sample project I have setup: sample.zip

The test target compiles and run fine in my case. Do you have sample project that replicate the issue?

Thanks!

pm-dev commented 5 months ago

This seems to happen during incremental builds with a specific dependency hierarchy, so it's a bit hard to reproduce despite it happening frequently in my project. Although this is likely an spm/xcodebuild bug where the build gets confused by from DatadogInternal, there may be a workaround that prevents this. I'll keep working on a consistent repro.

ncreated commented 4 months ago

Closing this issue due to inactivity. We're unable to reproduce this problem on our side. If it still persists (there were both SDK and Xcode updates since it was first opened) please attach sample project that we can look into and we will re-open it.