From 7a956de3008a834993e245d94f8a864e0ee68b4a Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Wed, 23 Sep 2026 12:11:32 +0200 Subject: [PATCH 01/19] Quick test for spm_dependency migration --- .../BenchmarkRunner.xcodeproj/project.pbxproj | 30 +++- .../xcshareddata/swiftpm/Package.resolved | 42 +++++ .../ios/BenchmarkRunner/PrivacyInfo.xcprivacy | 8 +- benchmarks/ios/Podfile | 12 +- benchmarks/ios/Podfile.lock | 146 +++++----------- .../project.pbxproj | 30 +++- .../xcshareddata/swiftpm/Package.resolved | 42 +++++ .../PrivacyInfo.xcprivacy | 8 +- example-new-architecture/ios/Podfile | 23 ++- example-new-architecture/ios/Podfile.lock | 154 ++++------------ .../project.pbxproj | 30 +++- .../xcshareddata/swiftpm/Package.resolved | 42 +++++ example/ios/Podfile | 23 ++- example/ios/Podfile.lock | 165 +++++------------- .../PrivacyInfo.xcprivacy | 8 +- packages/core/DatadogSDKReactNative.podspec | 81 +++++++-- .../DatadogInternalTesting.podspec | 55 +++++- ...DatadogSDKReactNativeSessionReplay.podspec | 66 +++++-- .../Sources/Utils/Bundle+SessionReplay.swift | 5 +- .../DatadogSDKReactNativeWebView.podspec | 63 +++++-- .../Sources/DatadogSDKReactNativeWebView.h | 9 + .../ios/Sources/RCTDatadogWebView.h | 15 +- .../ios/Sources/RCTDatadogWebViewManager.h | 7 + 23 files changed, 607 insertions(+), 457 deletions(-) create mode 100644 benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 example-new-architecture/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 example/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj index d845ae407..b5f481b32 100644 --- a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj @@ -17,9 +17,9 @@ 043403262DCB9CD700803AF8 /* BenchmarkVitals.mm in Sources */ = {isa = PBXBuildFile; fileRef = 043403242DCB9CD700803AF8 /* BenchmarkVitals.mm */; }; 04576C962DCBAF900078DCAB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 04576C952DCBAF900078DCAB /* main.m */; }; 04726DD72F46402A008D1A48 /* TracerProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04726DD62F46402A008D1A48 /* TracerProvider.swift */; }; - 0C80B921A6F3F58F76C31292 /* libPods-BenchmarkRunner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-BenchmarkRunner.a */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 20A397FC280595A8A9851556 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; + 52040CC80A3CB0E4C3A131B0 /* Pods_BenchmarkRunner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E927512A5C6D462705AE797 /* Pods_BenchmarkRunner.framework */; }; 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ @@ -42,8 +42,8 @@ 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = BenchmarkRunner/PrivacyInfo.xcprivacy; sourceTree = ""; }; 3B4392A12AC88292D35C810B /* Pods-BenchmarkRunner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenchmarkRunner.debug.xcconfig"; path = "Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner.debug.xcconfig"; sourceTree = ""; }; 5709B34CF0A7D63546082F79 /* Pods-BenchmarkRunner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenchmarkRunner.release.xcconfig"; path = "Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner.release.xcconfig"; sourceTree = ""; }; - 5DCACB8F33CDC322A6C60F78 /* libPods-BenchmarkRunner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BenchmarkRunner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = BenchmarkRunner/AppDelegate.swift; sourceTree = ""; }; + 7E927512A5C6D462705AE797 /* Pods_BenchmarkRunner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BenchmarkRunner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = BenchmarkRunner/LaunchScreen.storyboard; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -53,7 +53,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C80B921A6F3F58F76C31292 /* libPods-BenchmarkRunner.a in Frameworks */, + 52040CC80A3CB0E4C3A131B0 /* Pods_BenchmarkRunner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -110,7 +110,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 5DCACB8F33CDC322A6C60F78 /* libPods-BenchmarkRunner.a */, + 7E927512A5C6D462705AE797 /* Pods_BenchmarkRunner.framework */, ); name = Frameworks; sourceTree = ""; @@ -574,6 +574,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD_RUNPATH_SEARCH_PATHS = ( /usr/lib/swift, @@ -647,6 +658,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD_RUNPATH_SEARCH_PATHS = ( /usr/lib/swift, diff --git a/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..3c0312e44 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,42 @@ +{ + "originHash" : "ecc3edec2d3d8492b2aafc6cd36445ca859b5fde20181e9e4a9c7d388015e111", + "pins" : [ + { + "identity" : "dd-sdk-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/DataDog/dd-sdk-ios.git", + "state" : { + "revision" : "9a66954568bbbeee46eca36082a51b3dad581ae3", + "version" : "3.16.0" + } + }, + { + "identity" : "kscrash", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kstenerud/KSCrash.git", + "state" : { + "revision" : "3f77f379c2db001e0c261c2a51b7e2b115d31f91", + "version" : "2.6.0" + } + }, + { + "identity" : "opentelemetry-swift-core", + "kind" : "remoteSourceControl", + "location" : "https://github.com/open-telemetry/opentelemetry-swift-core", + "state" : { + "revision" : "06f8a460a66f813758d22f09025d85df45450a63", + "version" : "2.5.1" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "0442cb5a3f98ab802acb777929fdb446bda11a34", + "version" : "1.3.1" + } + } + ], + "version" : 3 +} diff --git a/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy b/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy index bad327615..41b8317f0 100644 --- a/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy +++ b/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy @@ -6,18 +6,18 @@ NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPICategoryFileTimestamp NSPrivacyAccessedAPITypeReasons - CA92.1 + C617.1 NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPICategoryUserDefaults NSPrivacyAccessedAPITypeReasons - C617.1 + CA92.1 diff --git a/benchmarks/ios/Podfile b/benchmarks/ios/Podfile index 92841ceb1..89ec38a2f 100644 --- a/benchmarks/ios/Podfile +++ b/benchmarks/ios/Podfile @@ -10,11 +10,9 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -linkage = ENV['USE_FRAMEWORKS'] -if linkage != nil - Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green - use_frameworks! :linkage => linkage.to_sym -end +# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires +# pods to be linked as dynamic frameworks. +use_frameworks! :linkage => :dynamic target 'BenchmarkRunner' do config = use_native_modules! @@ -27,6 +25,10 @@ target 'BenchmarkRunner' do # OpenTelemetrySdk is needed by the BenchmarkVitals code (metrics exporter, meter provider). # OpenTelemetryApi is already pulled in transitively via DatadogTrace, but OpenTelemetrySdk is not. + # + # /!\ DatadogTrace now pulls opentelemetry-swift-core through SwiftPM while this pod pulls + # OpenTelemetryApi through CocoaPods, so OpenTelemetryApi arrives via both package managers and + # may collide at link time. Untested -- if it does, source OpenTelemetrySdk from SPM too. pod 'OpenTelemetry-Swift-Sdk', '~> 2.5.0' post_install do |installer| diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 577819ad4..baf3114c4 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,26 +1,6 @@ PODS: - boost (1.84.0) - - DatadogCore (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogCrashReporting (3.16.0): - - DatadogInternal (= 3.16.0) - - KSCrash/Filters (= 2.5.1) - - KSCrash/Recording (= 2.5.1) - - DatadogFlags (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogInternal (3.16.0) - - DatadogLogs (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogRUM (3.16.0): - - DatadogInternal (= 3.16.0) - DatadogSDKReactNative (3.8.0): - - DatadogCore (= 3.16.0) - - DatadogCrashReporting (= 3.16.0) - - DatadogFlags (= 3.16.0) - - DatadogLogs (= 3.16.0) - - DatadogRUM (= 3.16.0) - - DatadogTrace (= 3.16.0) - - DatadogWebViewTracking (= 3.16.0) - DoubleConversion - glog - hermes-engine @@ -43,7 +23,6 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay (3.8.0): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.16.0) - DoubleConversion - glog - hermes-engine @@ -65,9 +44,7 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNativeWebView (3.8.0): - - DatadogInternal (= 3.16.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.16.0) - DoubleConversion - glog - hermes-engine @@ -80,6 +57,7 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - react-native-webview - React-NativeModulesApple - React-RCTFabric - React-rendererdebug @@ -88,13 +66,6 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSessionReplay (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogTrace (3.16.0): - - DatadogInternal (= 3.16.0) - - OpenTelemetry-Swift-Api (~> 2.5.0) - - DatadogWebViewTracking (3.16.0): - - DatadogInternal (= 3.16.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -103,17 +74,6 @@ PODS: - hermes-engine (0.78.2): - hermes-engine/Pre-built (= 0.78.2) - hermes-engine/Pre-built (0.78.2) - - KSCrash/Core (2.5.1) - - KSCrash/Filters (2.5.1): - - KSCrash/Recording - - KSCrash/RecordingCore - - KSCrash/ReportingCore - - KSCrash/Recording (2.5.1): - - KSCrash/RecordingCore - - KSCrash/RecordingCore (2.5.1): - - KSCrash/Core - - KSCrash/ReportingCore (2.5.1): - - KSCrash/Core - OpenTelemetry-Swift-Api (2.5.1) - OpenTelemetry-Swift-Sdk (2.5.1): - OpenTelemetry-Swift-Api (= 2.5.1) @@ -1963,16 +1923,6 @@ DEPENDENCIES: SPEC REPOS: https://github.com/CocoaPods/Specs.git: - - DatadogCore - - DatadogCrashReporting - - DatadogFlags - - DatadogInternal - - DatadogLogs - - DatadogRUM - - DatadogSessionReplay - - DatadogTrace - - DatadogWebViewTracking - - KSCrash - OpenTelemetry-Swift-Api - OpenTelemetry-Swift-Sdk - SocketRocket @@ -2134,25 +2084,15 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: 7eed8fbaaa1575503c389f343c230858343c8baf - DatadogCrashReporting: 04f3c3a5bfd9921aef4d44b4ab80accb39c84ddb - DatadogFlags: 033cf48e769c271843e77068c015519880011866 - DatadogInternal: e5a4652ee266986e29c6b8491aff7f78dc3b731d - DatadogLogs: 52792add5827042f619771a23656e2bfb6b0f4e7 - DatadogRUM: b78d608e013f39c5679ed31ad97dad323c6113e8 - DatadogSDKReactNative: 09dad2b43643ba603e1d8bdb241847917ba6f15d - DatadogSDKReactNativeSessionReplay: 6c6ec0adf5645e7167a4a6b1a6d1ceb656c29c51 - DatadogSDKReactNativeWebView: 34b05bdd6f540bb48c2ed19a3744698075c1b463 - DatadogSessionReplay: 932b2077b1a5367de1450479d72093621b9fd618 - DatadogTrace: 5ef84e254e2e1d337bc52e0cdf16396ca102aeb1 - DatadogWebViewTracking: e0470157f55a83680a549d79ba2985e0d17465db + DatadogSDKReactNative: a7089e56cc0cfa72a1cafdc7abe8fef5f627bf9a + DatadogSDKReactNativeSessionReplay: 459fac6340f6b5edbb0045ffe1ef0015f7cabfbb + DatadogSDKReactNativeWebView: 307574a321eb9646dbbe954d9b3654ec0666c240 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 hermes-engine: 2771b98fb813fdc6f92edd7c9c0035ecabf9fee7 - KSCrash: 8c4464fd5da7de520f2ce4a00fdf63f169a80f18 OpenTelemetry-Swift-Api: 3be9043f6288eb4ac3cbe7548b5bd45fb4ed5849 OpenTelemetry-Swift-Sdk: d9fa7bc839350f5a81467a5e877f727a8a77712d RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 @@ -2164,39 +2104,39 @@ SPEC CHECKSUMS: React-Core: 88e817c42de035378cc71e009193b9a044d3f595 React-CoreModules: dcf764d71efb4f75d38fcae8d4513b6729f49360 React-cxxreact: 8cdcc937c5fbc406fe843a381102fd69440ca78a - React-debug: 440175830c448e7e53e61ebb8d8468c3256b645e - React-defaultsnativemodule: 4824bcd7b96ee2d75c28b1ca21f58976867f5535 - React-domnativemodule: a421118b475618961cf282e8ea85347cc9bb453c - React-Fabric: 6ac7de06009eb96b609a770b17abba6e460b5f45 - React-FabricComponents: e3bc2680a5a9a4917ff0c8d7f390688c30ef753c - React-FabricImage: 8bad558dec7478077974caa96acc79692d6b71f5 - React-featureflags: b9cf9b35baca1c7f20c06a104ffc325a02752faa - React-featureflagsnativemodule: dc93d81da9f41f7132e24455ec8b4b60802fd5b0 - React-graphics: aaa5a38bea15d7b895b210d95d554af45a07002a + React-debug: 0a9fb34ecb645333d905645dabdcfdc945626078 + React-defaultsnativemodule: b5b92d4b4716825afa8c848b793fc7efdf8aeb5a + React-domnativemodule: 073b3161e1b49dfe9045884369ae1ec2b987de26 + React-Fabric: f62d9ce5c158ae40c2a7b2805b7c055297c9dad7 + React-FabricComponents: 4c48b1052f8f6c3b03c3c3e2a231f1abd6d89703 + React-FabricImage: 5ad03b0081353e1e047ae3471bb129c521bf02b1 + React-featureflags: 1bfa283a0e6f26eac629e8cef2add1b2670b6f4e + React-featureflagsnativemodule: 7dc781f04bbd4b394fccb85e187bdda954362bca + React-graphics: 7eefc878da8a522942358f53abd6a7170d757bf3 React-hermes: 08ad9fb832d1b9faef391be17309aa6a69fad23b - React-idlecallbacksnativemodule: aacea33ef6c511a9781f9286cc7cdf93f39bba14 - React-ImageManager: c596c3b658c9c14607f9183ed0f635c8dd77987c - React-jserrorhandler: 987609b2f16b7d79d63fcd621bf0110dd7400b35 + React-idlecallbacksnativemodule: 4a5d5ee0f8d7a9fa94ebd1426d349e866c223979 + React-ImageManager: ce227ed251701b3f37e25a2beede459078fcd82c + React-jserrorhandler: 6e5ffaef9b3364351ef6ef58d6665beabf615a0e React-jsi: afa286d7e0c102c2478dc420d4f8935e13c973fc React-jsiexecutor: 08f5b512b4db9e2f147416d60a0a797576b9cfef - React-jsinspector: 5a94bcae66e3637711c4d96a00038ab9ec935bf5 - React-jsinspectortracing: a12589a0adbb2703cbc4380dabe9a58800810923 - React-jsitracing: 0b1a403d7757cec66b7dd8b308d04db85eef75f3 + React-jsinspector: ebe0817345b1c0194ed5c64185269b9668fadf9a + React-jsinspectortracing: 6f251cb68796f3496698127deabe5b0bbbb89b52 + React-jsitracing: 4c3fd6a14f560c52c167254a07029bcf9b60f3d8 React-logger: 304814ae37503c8eb54359851cc55bd4f936b39c - React-Mapbuffer: b588d1ca18d2ce626f868f04ab12d8b1f004f12c - React-microtasksnativemodule: 11831d070aa47755bb5739069eb04ec621fec548 + React-Mapbuffer: 8ba61e036d346d363ad208cfb1dea6c7fce0dce0 + React-microtasksnativemodule: feb934d19767f38faf9f9f0efb7cc1dcdf2d11b7 react-native-config: 3367df9c1f25bb96197007ec531c7087ed4554c3 - react-native-safe-area-context: 9b169299f9dc95f1d7fe1dd266fde53bd899cd0c - react-native-slider: 27263d134d55db948a4706f1e47d0ec88fb354dd - react-native-webview: be9957759cb73cb64f2ed5359e32a85f1f5bdff8 - React-NativeModulesApple: 79a4404ac301b40bec3b367879c5e9a9ce81683c + react-native-safe-area-context: 4da09dc73a70ad08307a6c09f61c7b03fbd45699 + react-native-slider: 01962232986a825f44af5e3537c2defe90ced096 + react-native-webview: f3180bd28381ba09520b01f36fd84d377f6ebc49 + React-NativeModulesApple: 55d6d890aa60200292a90cc1ca6c53409650f48f React-perflogger: 0ea25c109dba33d47dec36b2634bf7ea67c1a555 - React-performancetimeline: f74480de6efbcd8541c34317c0baedb433f27296 + React-performancetimeline: 21656d07aede48ca0c8c3ca7d0e755eaa17f697c React-RCTActionSheet: 2ef95837e89b9b154f13cd8401f9054fc3076aff React-RCTAnimation: 33d960d7f58a81779eea6dea47ad0364c67e1517 React-RCTAppDelegate: 85c13403fd6f6b6cc630428d52bd8bd76a670dc9 React-RCTBlob: 74c986a02d951931d2f6ed0e07ed5a7eb385bfc0 - React-RCTFabric: 384a8fea4f22fc0f21299d771971862883ba630a + React-RCTFabric: 384a6e22644799f66f545bf0de4618f4652c791f React-RCTFBReactNativeSpec: eb1c3ec5149f76133593a516ff9d5efe32ebcecd React-RCTImage: 2c58b5ddeb3c65e52f942bbe13ff9c59bd649b09 React-RCTLinking: b6b14f8a3e62c02fc627ac4f3fb0c7bd941f907c @@ -2204,25 +2144,25 @@ SPEC CHECKSUMS: React-RCTSettings: 8148f6be0ccc0cfe6e313417ebf8a479caaa2146 React-RCTText: 64114531ad1359e4e02a4a8af60df606dbbabc25 React-RCTVibration: f4859417a7dd859b6bf18b1aba897e52beb72ef6 - React-rendererconsistency: 5ac4164ec18cfdd76ed5f864dbfdc56a5a948bc9 - React-rendererdebug: 3dc1d97bbee0c0c13191e501a96ed9325bbd920e - React-rncore: 0bace3b991d8843bb5b57c5f2301ec6e9c94718b - React-RuntimeApple: 1e1e0a0c6086bc8c3b07e8f1a2f6ca99b50419a0 - React-RuntimeCore: d39322c59bef2a4b343fda663d20649f29f57fcc + React-rendererconsistency: 80ffb3fc9635edb785c19f06eb1ba9e1d3b85ea6 + React-rendererdebug: ea9b0383484ade00d675582d7848be6a86c3feb5 + React-rncore: 7c0b895671632ea5eb84edb85f48e180816e9e33 + React-RuntimeApple: 8e0654961ab947d3febc60f77a4d9fe97e135d0a + React-RuntimeCore: b194b603daafd68b140ab4c871f1556efc2c69bc React-runtimeexecutor: 876dfc1d8daa819dfd039c40f78f277c5a3e66a6 - React-RuntimeHermes: 44f5f2baf039f249b31ea4f3e224484fd1731e0e - React-runtimescheduler: 3b3c5b50743bb8743ca49b9e5a70c2c385f156e1 - React-timing: 1ee3572c398f5579c9df5bf76aacddf5683ff74e - React-utils: 0cfb7c7fb37d4e5f31cc18ffc7426be0ae6bf907 + React-RuntimeHermes: f337612527ff2ca8bb86a861be4636f177bc3bbb + React-runtimescheduler: 307946600cf701b3ffe38b454d1d1a710e8e74e7 + React-timing: 96e060d0d0bf18522d363716623ed2c61f7107c7 + React-utils: 8adf5864fc96ef51957fee06a3e43ed26559d8a7 ReactAppDependencyProvider: b48473fe434569ff8f6cb6ed4421217ebcbda878 - ReactCodegen: 653a0d8532d8c7dab50c391392044d98e20c9f79 - ReactCommon: 547db015202a80a5b3e7e041586ea54c4a087180 - RNCPicker: ffbd7b9fc7c1341929e61dbef6219f7860f57418 - RNScreens: 0f01bbed9bd8045a8d58e4b46993c28c7f498f3c - RNSVG: 082ae2874b288a96c95326c4f6029793f7009d4b + ReactCodegen: 699df724d2244b1f6b87bce12580aabb172cc52a + ReactCommon: 8fdc2d8511f4099f25d5929f7fa4284c14a7e509 + RNCPicker: 4f336c7d99a43802c0e2b51c8cbe0c32b1e3d3e3 + RNScreens: ef58b1f3077f7ee62b58f958536ee5ccb52d96b5 + RNSVG: 02ef1157622e9e59e31c257e48a0dc943411c7bf SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: e14bad835e12b6c7e2260fc320bd00e0f4b45add + Yoga: 6eb60fc2c0eef63e7d2ef4a56e0a3353534143a2 -PODFILE CHECKSUM: d0574c1c0410627561bf4b1b55d0f1754283e022 +PODFILE CHECKSUM: 1b136836f3fad4e4ab921bff5d885c5d6596bcf4 COCOAPODS: 1.16.2 diff --git a/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj b/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj index ce12a7261..17db66bd7 100644 --- a/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj +++ b/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj @@ -10,7 +10,7 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 23A157380019DD81E7B34848 /* libPods-DdSdkReactNativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 61EAA7FCAAF9DA56562AE2DD /* libPods-DdSdkReactNativeExample.a */; }; + 4BBE00300BC79AB67EE46771 /* Pods_DdSdkReactNativeExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65BB5462DD7E7ABA0036E297 /* Pods_DdSdkReactNativeExample.framework */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; E05973ABEC106467505BAF84 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 91A6167299744A7A5E90FD00 /* PrivacyInfo.xcprivacy */; }; /* End PBXBuildFile section */ @@ -25,7 +25,7 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = DdSdkReactNativeExample/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = DdSdkReactNativeExample/main.m; sourceTree = ""; }; 340C792A76F8AD30116CC14F /* Pods-DdSdkReactNativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DdSdkReactNativeExample.debug.xcconfig"; path = "Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample.debug.xcconfig"; sourceTree = ""; }; - 61EAA7FCAAF9DA56562AE2DD /* libPods-DdSdkReactNativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DdSdkReactNativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 65BB5462DD7E7ABA0036E297 /* Pods_DdSdkReactNativeExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DdSdkReactNativeExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = DdSdkReactNativeExample/LaunchScreen.storyboard; sourceTree = ""; }; 91A6167299744A7A5E90FD00 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = DdSdkReactNativeExample/PrivacyInfo.xcprivacy; sourceTree = ""; }; E9E5D75547DBA2BF3A3DDBA3 /* Pods-DdSdkReactNativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DdSdkReactNativeExample.release.xcconfig"; path = "Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample.release.xcconfig"; sourceTree = ""; }; @@ -37,7 +37,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 23A157380019DD81E7B34848 /* libPods-DdSdkReactNativeExample.a in Frameworks */, + 4BBE00300BC79AB67EE46771 /* Pods_DdSdkReactNativeExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -79,7 +79,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 61EAA7FCAAF9DA56562AE2DD /* libPods-DdSdkReactNativeExample.a */, + 65BB5462DD7E7ABA0036E297 /* Pods_DdSdkReactNativeExample.framework */, ); name = Frameworks; sourceTree = ""; @@ -402,6 +402,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD = ""; LDPLUSPLUS = ""; @@ -482,6 +493,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD = ""; LDPLUSPLUS = ""; diff --git a/example-new-architecture/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved b/example-new-architecture/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..3c0312e44 --- /dev/null +++ b/example-new-architecture/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,42 @@ +{ + "originHash" : "ecc3edec2d3d8492b2aafc6cd36445ca859b5fde20181e9e4a9c7d388015e111", + "pins" : [ + { + "identity" : "dd-sdk-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/DataDog/dd-sdk-ios.git", + "state" : { + "revision" : "9a66954568bbbeee46eca36082a51b3dad581ae3", + "version" : "3.16.0" + } + }, + { + "identity" : "kscrash", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kstenerud/KSCrash.git", + "state" : { + "revision" : "3f77f379c2db001e0c261c2a51b7e2b115d31f91", + "version" : "2.6.0" + } + }, + { + "identity" : "opentelemetry-swift-core", + "kind" : "remoteSourceControl", + "location" : "https://github.com/open-telemetry/opentelemetry-swift-core", + "state" : { + "revision" : "06f8a460a66f813758d22f09025d85df45450a63", + "version" : "2.5.1" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "0442cb5a3f98ab802acb777929fdb446bda11a34", + "version" : "1.3.1" + } + } + ], + "version" : 3 +} diff --git a/example-new-architecture/ios/DdSdkReactNativeExample/PrivacyInfo.xcprivacy b/example-new-architecture/ios/DdSdkReactNativeExample/PrivacyInfo.xcprivacy index bad327615..41b8317f0 100644 --- a/example-new-architecture/ios/DdSdkReactNativeExample/PrivacyInfo.xcprivacy +++ b/example-new-architecture/ios/DdSdkReactNativeExample/PrivacyInfo.xcprivacy @@ -6,18 +6,18 @@ NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPICategoryFileTimestamp NSPrivacyAccessedAPITypeReasons - CA92.1 + C617.1 NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPICategoryUserDefaults NSPrivacyAccessedAPITypeReasons - C617.1 + CA92.1 diff --git a/example-new-architecture/ios/Podfile b/example-new-architecture/ios/Podfile index a08a06fde..da453411d 100644 --- a/example-new-architecture/ios/Podfile +++ b/example-new-architecture/ios/Podfile @@ -10,14 +10,18 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -linkage = ENV['USE_FRAMEWORKS'] -if linkage != nil - Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green - use_frameworks! :linkage => linkage.to_sym -end +# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires +# pods to be linked as dynamic frameworks: dd-sdk-ios declares its SPM products without an explicit +# `type:`, so SwiftPM builds them as static libraries, and combining those with CocoaPods' default +# static linkage produces duplicate symbols at link time. Dynamic frameworks are the only +# combination that works -- see https://github.com/facebook/react-native/pull/44627 for the full +# matrix. +use_frameworks! :linkage => :dynamic target 'DdSdkReactNativeExample' do - pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec', :testspecs => ['Tests'] + # No `:testspecs` here: the Datadog podspecs declare no test spec, because the native tests need + # `@testable` access to Datadog pod targets that do not exist once the SDK comes from SPM. + pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec' config = use_native_modules! @@ -35,13 +39,6 @@ target 'DdSdkReactNativeExample' do :mac_catalyst_enabled => false ) - # Enable `DD_SDK_COMPILED_FOR_TESTING` condition when compiling `DatadogSDK` dependency: - datadog_sdk_target = installer.pods_project.targets.detect {|t| ["DatadogCore", "DatadogRUM", "DatadogLogs", "DatadogInternal", "DatadogTrace", "DatadogCrashReporting"].include?(t.name) } - datadog_sdk_target.build_configurations.each do |config| - config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = '$(inherited) DD_SDK_COMPILED_FOR_TESTING' - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = min_ios_version_supported - end - installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = min_ios_version_supported diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 8096e0ca7..bc07dbd4d 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,26 +1,6 @@ PODS: - boost (1.84.0) - - DatadogCore (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogCrashReporting (3.16.0): - - DatadogInternal (= 3.16.0) - - KSCrash/Filters (= 2.5.1) - - KSCrash/Recording (= 2.5.1) - - DatadogFlags (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogInternal (3.16.0) - - DatadogLogs (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogRUM (3.16.0): - - DatadogInternal (= 3.16.0) - DatadogSDKReactNative (3.8.0): - - DatadogCore (= 3.16.0) - - DatadogCrashReporting (= 3.16.0) - - DatadogFlags (= 3.16.0) - - DatadogLogs (= 3.16.0) - - DatadogRUM (= 3.16.0) - - DatadogTrace (= 3.16.0) - - DatadogWebViewTracking (= 3.16.0) - DoubleConversion - glog - hermes-engine @@ -41,39 +21,6 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (3.8.0): - - DatadogCore (= 3.16.0) - - DatadogCrashReporting (= 3.16.0) - - DatadogFlags (= 3.16.0) - - DatadogLogs (= 3.16.0) - - DatadogRUM (= 3.16.0) - - DatadogTrace (= 3.16.0) - - DatadogWebViewTracking (= 3.16.0) - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.10.14.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - - DatadogTrace (3.16.0): - - DatadogInternal (= 3.16.0) - - OpenTelemetry-Swift-Api (~> 2.5.0) - - DatadogWebViewTracking (3.16.0): - - DatadogInternal (= 3.16.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -82,18 +29,6 @@ PODS: - hermes-engine (0.76.9): - hermes-engine/Pre-built (= 0.76.9) - hermes-engine/Pre-built (0.76.9) - - KSCrash/Core (2.5.1) - - KSCrash/Filters (2.5.1): - - KSCrash/Recording - - KSCrash/RecordingCore - - KSCrash/ReportingCore - - KSCrash/Recording (2.5.1): - - KSCrash/RecordingCore - - KSCrash/RecordingCore (2.5.1): - - KSCrash/Core - - KSCrash/ReportingCore (2.5.1): - - KSCrash/Core - - OpenTelemetry-Swift-Api (2.5.1) - RCT-Folly (2024.10.14.00): - boost - DoubleConversion @@ -1650,7 +1585,6 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DatadogSDKReactNative (from `../../packages/core/DatadogSDKReactNative.podspec`) - - DatadogSDKReactNative/Tests (from `../../packages/core/DatadogSDKReactNative.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) @@ -1719,16 +1653,6 @@ DEPENDENCIES: SPEC REPOS: https://github.com/CocoaPods/Specs.git: - - DatadogCore - - DatadogCrashReporting - - DatadogFlags - - DatadogInternal - - DatadogLogs - - DatadogRUM - - DatadogTrace - - DatadogWebViewTracking - - KSCrash - - OpenTelemetry-Swift-Api - SocketRocket EXTERNAL SOURCES: @@ -1866,23 +1790,13 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 7eed8fbaaa1575503c389f343c230858343c8baf - DatadogCrashReporting: 04f3c3a5bfd9921aef4d44b4ab80accb39c84ddb - DatadogFlags: 033cf48e769c271843e77068c015519880011866 - DatadogInternal: e5a4652ee266986e29c6b8491aff7f78dc3b731d - DatadogLogs: 52792add5827042f619771a23656e2bfb6b0f4e7 - DatadogRUM: b78d608e013f39c5679ed31ad97dad323c6113e8 - DatadogSDKReactNative: c364fd3d7c3ff3f078bcc44fe164aa4b345e91c3 - DatadogTrace: 5ef84e254e2e1d337bc52e0cdf16396ca102aeb1 - DatadogWebViewTracking: e0470157f55a83680a549d79ba2985e0d17465db + DatadogSDKReactNative: 4658ccf5324b283cec0b441733ae55d5fa2e3096 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 fmt: 01b82d4ca6470831d1cc0852a1af644be019e8f6 glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 - KSCrash: 8c4464fd5da7de520f2ce4a00fdf63f169a80f18 - OpenTelemetry-Swift-Api: 3be9043f6288eb4ac3cbe7548b5bd45fb4ed5849 RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 @@ -1892,56 +1806,56 @@ SPEC CHECKSUMS: React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d - React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: 814830ccbc3fb08d67d0190e63b179ee4098c67b - React-domnativemodule: 270acf94bd0960b026bc3bfb327e703665d27fb4 - React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b - React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb - React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f - React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 0d7091ae344d6160c0557048e127897654a5c00f - React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 + React-debug: f1956672cf545729afb71ef838a9789c2a9088f5 + React-defaultsnativemodule: a5c2c12043f7e57dd8f972d28cf0c2e0ee439051 + React-domnativemodule: 9d4b6d9828a7512832d23fb64e3f13366efe67ef + React-Fabric: 80d7bc9d0ea7981a188b1ea6a67df072af164489 + React-FabricComponents: 1887b9027e7da5679f099b999dc56b44dbc7628c + React-FabricImage: 27996e41c769616bb68f011362bf69c472a6b2f7 + React-featureflags: dc9c91fcd6a75cc95bd7fec184d0be8ad0f26db5 + React-featureflagsnativemodule: f483a827effd65c0b7b2c827607716c74f2a4ae1 + React-graphics: fa15bab1a7d44a57eeb54e3185117729b141ed4b React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 - React-idlecallbacksnativemodule: 6b84add48971da9c40403bd1860d4896462590f2 - React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 - React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 + React-idlecallbacksnativemodule: 97ecc9647f7e80ea4c05545c84a86dee05e816d0 + React-ImageManager: 1a6f5a858f86bc93bf210a88ec5575ff22b69aaa + React-jserrorhandler: ea750869c2aa5497b3d9322afe02eb7f756b9696 React-jsi: 95f7676103137861b79b0f319467627bcfa629ee React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 - React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 - React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b + React-jsinspector: 74c73f2b385b6a7979eddeba055961e9acc3cc42 + React-jsitracing: 182a6d4af2273f847daa8a3f841fd3ff8212d3f8 React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 - React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc - React-microtasksnativemodule: a645237a841d733861c70b69908ab4a1707b52ad - React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 + React-Mapbuffer: 129fa9634f42d88a0c3761d2829db85175b985ee + React-microtasksnativemodule: b5151a6d754fbf52292e758c4bb93b7c0d2f0b92 + React-nativeconfig: 415626a63057638759bcc75e0a96e2e07771a479 + React-NativeModulesApple: bffc60f55895c2723b1e5472fa40567fe3df4923 React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d - React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 + React-performancetimeline: 128acbcdacb8a5ee73aa4a2bf28db4e8627f111b React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 React-RCTAppDelegate: 1774aa421a29a41a704ecaf789811ef73c4634b6 React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 - React-RCTFabric: 731cda82aed592aacce2d32ead69d78cde5d9274 + React-RCTFabric: afb0e865f70c5017597f758d5749298dae9b87bf React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec - React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 - React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 - React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 + React-rendererconsistency: b89c074e22ca2b9eaa8013e1310c69db85364893 + React-rendererdebug: 383e6c8c8d9ee45e88e5d461ad1c6a4a7a0f9282 + React-rncore: 2a6efd857e10a3b299f8a7fe912fd332aa7e515a + React-RuntimeApple: f07537b48b715b6dd7a8d6145f4f6684d78984cc + React-RuntimeCore: cce02c6ade4d7e8d1854d275c9b367b913ed1fb3 React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 - React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe - React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e - ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c - ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd + React-RuntimeHermes: ec8b23b1a86022e9831ab775d1634fcbc7dfc500 + React-runtimescheduler: 222c73a654f32e3544a1384b2ced809bd51df2af + React-timing: a693c531e5627dcc200fc7286cbbebf73d73469d + React-utils: 52cb73e127a39fc2d9f02f503b2a7b3b0abd23dd + ReactCodegen: 31fcff227d0035956575be0c013a2edcc687a53c + ReactCommon: 78c49c7cf7df16983ebc3c646b4f47398437f2ec SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a + Yoga: 1259c7a8cbaccf7b4c3ddf8ee36ca11be9dee407 -PODFILE CHECKSUM: 85124514d3acbe8b60389d46d3c38133e7c8e8de +PODFILE CHECKSUM: e2bfd31ede533b920dccdc714d311ef0b2e666ac COCOAPODS: 1.16.2 diff --git a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj index bde88ccb4..51e7b602e 100644 --- a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj @@ -11,9 +11,9 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 2789DEF2415D78452154A27B /* Pods_ddSdkReactnativeExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF25158637ACC88517B07D7D /* Pods_ddSdkReactnativeExample.framework */; }; 7115D38EB0DCB0BDB39D62A2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A54EC6889135AAF4EFAD7EF0 /* PrivacyInfo.xcprivacy */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; - FB483A2F5418999CE4813EF0 /* libPods-ddSdkReactnativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE41272558F8A75D64B58C34 /* libPods-ddSdkReactnativeExample.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -29,8 +29,8 @@ 6D26190AF1861B20490BD908 /* Pods-ddSdkReactnativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ddSdkReactnativeExample.release.xcconfig"; path = "Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample.release.xcconfig"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ddSdkReactnativeExample/LaunchScreen.storyboard; sourceTree = ""; }; A54EC6889135AAF4EFAD7EF0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = ddSdkReactnativeExample/PrivacyInfo.xcprivacy; sourceTree = ""; }; - CE41272558F8A75D64B58C34 /* libPods-ddSdkReactnativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ddSdkReactnativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + EF25158637ACC88517B07D7D /* Pods_ddSdkReactnativeExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ddSdkReactnativeExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -38,7 +38,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - FB483A2F5418999CE4813EF0 /* libPods-ddSdkReactnativeExample.a in Frameworks */, + 2789DEF2415D78452154A27B /* Pods_ddSdkReactnativeExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -64,7 +64,7 @@ children = ( 04ACF1F52ED5D05F00602CDD /* datadog-configuration.json */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - CE41272558F8A75D64B58C34 /* libPods-ddSdkReactnativeExample.a */, + EF25158637ACC88517B07D7D /* Pods_ddSdkReactnativeExample.framework */, ); name = Frameworks; sourceTree = ""; @@ -388,6 +388,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 12.4; LD = ""; LDPLUSPLUS = ""; @@ -465,6 +476,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 12.4; LD = ""; LDPLUSPLUS = ""; diff --git a/example/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved b/example/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..3c0312e44 --- /dev/null +++ b/example/ios/DdSdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,42 @@ +{ + "originHash" : "ecc3edec2d3d8492b2aafc6cd36445ca859b5fde20181e9e4a9c7d388015e111", + "pins" : [ + { + "identity" : "dd-sdk-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/DataDog/dd-sdk-ios.git", + "state" : { + "revision" : "9a66954568bbbeee46eca36082a51b3dad581ae3", + "version" : "3.16.0" + } + }, + { + "identity" : "kscrash", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kstenerud/KSCrash.git", + "state" : { + "revision" : "3f77f379c2db001e0c261c2a51b7e2b115d31f91", + "version" : "2.6.0" + } + }, + { + "identity" : "opentelemetry-swift-core", + "kind" : "remoteSourceControl", + "location" : "https://github.com/open-telemetry/opentelemetry-swift-core", + "state" : { + "revision" : "06f8a460a66f813758d22f09025d85df45450a63", + "version" : "2.5.1" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "0442cb5a3f98ab802acb777929fdb446bda11a34", + "version" : "1.3.1" + } + } + ], + "version" : 3 +} diff --git a/example/ios/Podfile b/example/ios/Podfile index 0c9182f55..39caa3369 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -10,16 +10,16 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -linkage = ENV['USE_FRAMEWORKS'] -if linkage != nil - Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green - use_frameworks! :linkage => linkage.to_sym -end +# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires +# pods to be linked as dynamic frameworks. +use_frameworks! :linkage => :dynamic target 'ddSdkReactnativeExample' do - pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec', :testspecs => ['Tests'] - pod 'DatadogSDKReactNativeSessionReplay', :path => '../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec', :testspecs => ['Tests'] - pod 'DatadogSDKReactNativeWebView', :path => '../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec', :testspecs => ['Tests'] + # No `:testspecs` here: the Datadog podspecs declare no test spec, because the native tests need + # `@testable` access to Datadog pod targets that do not exist once the SDK comes from SPM. + pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec' + pod 'DatadogSDKReactNativeSessionReplay', :path => '../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec' + pod 'DatadogSDKReactNativeWebView', :path => '../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec' config = use_native_modules! @@ -38,11 +38,8 @@ target 'ddSdkReactnativeExample' do config[:reactNativePath], :mac_catalyst_enabled => false ) - # Enable `DD_SDK_COMPILED_FOR_TESTING` condition when compiling `DatadogSDK` dependency: - datadog_sdk_target = installer.pods_project.targets.detect {|t| ["DatadogCore", "DatadogRUM", "DatadogLogs", "DatadogInternal", "DatadogTrace", "DatadogCrashReporting"].include?(t.name) } - datadog_sdk_target.build_configurations.each do |config| - config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = '$(inherited) DD_SDK_COMPILED_FOR_TESTING' - end + # No `DD_SDK_COMPILED_FOR_TESTING` injection: the Datadog iOS SDK is no longer built as a pod + # target, so there is no build configuration to set it on. installer.pods_project.targets.each do |target| target.build_configurations.each do |config| diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 4bfc123e9..f2583f929 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,64 +1,14 @@ PODS: - boost (1.84.0) - - DatadogCore (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogCrashReporting (3.16.0): - - DatadogInternal (= 3.16.0) - - KSCrash/Filters (= 2.5.1) - - KSCrash/Recording (= 2.5.1) - - DatadogFlags (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogInternal (3.16.0) - - DatadogLogs (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogRUM (3.16.0): - - DatadogInternal (= 3.16.0) - DatadogSDKReactNative (3.8.0): - - DatadogCore (= 3.16.0) - - DatadogCrashReporting (= 3.16.0) - - DatadogFlags (= 3.16.0) - - DatadogLogs (= 3.16.0) - - DatadogRUM (= 3.16.0) - - DatadogTrace (= 3.16.0) - - DatadogWebViewTracking (= 3.16.0) - - React-Core - - DatadogSDKReactNative/Tests (3.8.0): - - DatadogCore (= 3.16.0) - - DatadogCrashReporting (= 3.16.0) - - DatadogFlags (= 3.16.0) - - DatadogLogs (= 3.16.0) - - DatadogRUM (= 3.16.0) - - DatadogTrace (= 3.16.0) - - DatadogWebViewTracking (= 3.16.0) - React-Core - DatadogSDKReactNativeSessionReplay (3.8.0): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.16.0) - - React-Core - - DatadogSDKReactNativeSessionReplay/Tests (3.8.0): - - DatadogSDKReactNative - - DatadogSessionReplay (= 3.16.0) - React-Core - - React-RCTText - DatadogSDKReactNativeWebView (3.8.0): - - DatadogInternal (= 3.16.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.16.0) - - React-Core - - DatadogSDKReactNativeWebView/Tests (3.8.0): - - DatadogInternal (= 3.16.0) - - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.16.0) - React-Core - react-native-webview - - React-RCTText - - DatadogSessionReplay (3.16.0): - - DatadogInternal (= 3.16.0) - - DatadogTrace (3.16.0): - - DatadogInternal (= 3.16.0) - - OpenTelemetry-Swift-Api (~> 2.5.0) - - DatadogWebViewTracking (3.16.0): - - DatadogInternal (= 3.16.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -68,18 +18,6 @@ PODS: - hermes-engine/Pre-built (= 0.76.9) - hermes-engine/Pre-built (0.76.9) - HMSegmentedControl (1.5.6) - - KSCrash/Core (2.5.1) - - KSCrash/Filters (2.5.1): - - KSCrash/Recording - - KSCrash/RecordingCore - - KSCrash/ReportingCore - - KSCrash/Recording (2.5.1): - - KSCrash/RecordingCore - - KSCrash/RecordingCore (2.5.1): - - KSCrash/Core - - KSCrash/ReportingCore (2.5.1): - - KSCrash/Core - - OpenTelemetry-Swift-Api (2.5.1) - RCT-Folly (2024.10.14.00): - boost - DoubleConversion @@ -1719,11 +1657,8 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DatadogSDKReactNative (from `../../packages/core/DatadogSDKReactNative.podspec`) - - DatadogSDKReactNative/Tests (from `../../packages/core/DatadogSDKReactNative.podspec`) - DatadogSDKReactNativeSessionReplay (from `../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec`) - - DatadogSDKReactNativeSessionReplay/Tests (from `../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec`) - DatadogSDKReactNativeWebView (from `../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec`) - - DatadogSDKReactNativeWebView/Tests (from `../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) @@ -1799,18 +1734,7 @@ DEPENDENCIES: SPEC REPOS: https://github.com/CocoaPods/Specs.git: - - DatadogCore - - DatadogCrashReporting - - DatadogFlags - - DatadogInternal - - DatadogLogs - - DatadogRUM - - DatadogSessionReplay - - DatadogTrace - - DatadogWebViewTracking - HMSegmentedControl - - KSCrash - - OpenTelemetry-Swift-Api - SocketRocket EXTERNAL SOURCES: @@ -1966,18 +1890,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 7eed8fbaaa1575503c389f343c230858343c8baf - DatadogCrashReporting: 04f3c3a5bfd9921aef4d44b4ab80accb39c84ddb - DatadogFlags: 033cf48e769c271843e77068c015519880011866 - DatadogInternal: e5a4652ee266986e29c6b8491aff7f78dc3b731d - DatadogLogs: 52792add5827042f619771a23656e2bfb6b0f4e7 - DatadogRUM: b78d608e013f39c5679ed31ad97dad323c6113e8 - DatadogSDKReactNative: d65150a6f37b4ca8f4d98909898a9c4632a7cbd6 - DatadogSDKReactNativeSessionReplay: 53f8448c51ea23aeb47fe3d67e7c383b91d06acf - DatadogSDKReactNativeWebView: 25586892c073fe6f95928dc556e6b623abe513f8 - DatadogSessionReplay: 932b2077b1a5367de1450479d72093621b9fd618 - DatadogTrace: 5ef84e254e2e1d337bc52e0cdf16396ca102aeb1 - DatadogWebViewTracking: e0470157f55a83680a549d79ba2985e0d17465db + DatadogSDKReactNative: 11a3d7460bac8d7e7750f4687fbe67214dd28edb + DatadogSDKReactNativeSessionReplay: 81c99bcdcbdb52aff01676bcdc15cbd4df67506c + DatadogSDKReactNativeWebView: 410633d047e11261985c97e9f71749c727211e2c DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -1985,8 +1900,6 @@ SPEC CHECKSUMS: glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352 - KSCrash: 8c4464fd5da7de520f2ce4a00fdf63f169a80f18 - OpenTelemetry-Swift-Api: 3be9043f6288eb4ac3cbe7548b5bd45fb4ed5849 RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 @@ -1996,63 +1909,63 @@ SPEC CHECKSUMS: React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d - React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: a965cb39fb0a79276ab611793d39f52e59a9a851 - React-domnativemodule: d647f94e503c62c44f54291334b1aa22a30fa08b - React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b - React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb - React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f - React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 95a02d895475de8ace78fedd76143866838bb720 - React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 + React-debug: f1956672cf545729afb71ef838a9789c2a9088f5 + React-defaultsnativemodule: f5e33b59be56f54f0e6c1991db55ddbc6de39181 + React-domnativemodule: 73f26e6bc782ca358497fbed427035ea01fcc297 + React-Fabric: 80d7bc9d0ea7981a188b1ea6a67df072af164489 + React-FabricComponents: 1887b9027e7da5679f099b999dc56b44dbc7628c + React-FabricImage: 27996e41c769616bb68f011362bf69c472a6b2f7 + React-featureflags: dc9c91fcd6a75cc95bd7fec184d0be8ad0f26db5 + React-featureflagsnativemodule: 1a0c73dca4158da552f074d469066d317c6a0570 + React-graphics: fa15bab1a7d44a57eeb54e3185117729b141ed4b React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 - React-idlecallbacksnativemodule: 0c1ae840cc5587197cd926a3cb76828ad059d116 - React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 - React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 + React-idlecallbacksnativemodule: 1e13269b40e163fe92cb1774a24bbe607beb0242 + React-ImageManager: 1a6f5a858f86bc93bf210a88ec5575ff22b69aaa + React-jserrorhandler: ea750869c2aa5497b3d9322afe02eb7f756b9696 React-jsi: 95f7676103137861b79b0f319467627bcfa629ee React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 - React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 - React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b + React-jsinspector: 74c73f2b385b6a7979eddeba055961e9acc3cc42 + React-jsitracing: 182a6d4af2273f847daa8a3f841fd3ff8212d3f8 React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 - React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc - React-microtasksnativemodule: 8732b71aa66045da4bb341ddee1bb539f71e5f38 + React-Mapbuffer: 129fa9634f42d88a0c3761d2829db85175b985ee + React-microtasksnativemodule: 5aeec323cb452dba293815d82bf08d7076e295d0 react-native-crash-tester: 3ffaa64141427ca362079cb53559fe9a532487ae react-native-safe-area-context: 04803a01f39f31cc6605a5531280b477b48f8a88 - react-native-webview: 1e12de2fad74c17b4f8b1b53ebd1e3baa0148d71 - React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 + react-native-webview: f0a8c96e34ec192f88eaf48c00fbefe415dd6ed2 + React-nativeconfig: 415626a63057638759bcc75e0a96e2e07771a479 + React-NativeModulesApple: bffc60f55895c2723b1e5472fa40567fe3df4923 React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d - React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 + React-performancetimeline: 128acbcdacb8a5ee73aa4a2bf28db4e8627f111b React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 React-RCTAppDelegate: 6c0377d9c4058773ea7073bb34bb9ebd6ddf5a84 React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 - React-RCTFabric: 7eb6dd2c8fda98cb860a572e3f4e4eb60d62c89e + React-RCTFabric: dba2f65bcfcede5e0b2ed7df48247cdb16f21f20 React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec - React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 - React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 - React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 + React-rendererconsistency: b89c074e22ca2b9eaa8013e1310c69db85364893 + React-rendererdebug: 383e6c8c8d9ee45e88e5d461ad1c6a4a7a0f9282 + React-rncore: 2a6efd857e10a3b299f8a7fe912fd332aa7e515a + React-RuntimeApple: f07537b48b715b6dd7a8d6145f4f6684d78984cc + React-RuntimeCore: cce02c6ade4d7e8d1854d275c9b367b913ed1fb3 React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 - React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe - React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e - ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c - ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd + React-RuntimeHermes: ec8b23b1a86022e9831ab775d1634fcbc7dfc500 + React-runtimescheduler: 222c73a654f32e3544a1384b2ced809bd51df2af + React-timing: a693c531e5627dcc200fc7286cbbebf73d73469d + React-utils: 52cb73e127a39fc2d9f02f503b2a7b3b0abd23dd + ReactCodegen: 31fcff227d0035956575be0c013a2edcc687a53c + ReactCommon: 78c49c7cf7df16983ebc3c646b4f47398437f2ec ReactNativeNavigation: 50c1eef68b821e7265eff3a391d27ed18fdce459 RNCAsyncStorage: 23e56519cc41d3bade3c8d4479f7760cb1c11996 - RNGestureHandler: 950dfa674dbf481460ca389c65b9036ac4ab8ada - RNScreens: 606ab1cf68162f7ba0d049a31f2a84089a6fffb4 + RNGestureHandler: 8d00cc737b38b7b67be2d9438242850182291fb4 + RNScreens: da5922094c3a1d9ce10625888b185798523b58ed SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a + Yoga: 1259c7a8cbaccf7b4c3ddf8ee36ca11be9dee407 -PODFILE CHECKSUM: a2729cbf6c0a559932ef8f49d27110873b77ff7d +PODFILE CHECKSUM: bf984a17ba7e485ff3a3654018482eba3acf4687 COCOAPODS: 1.16.2 diff --git a/example/ios/ddSdkReactnativeExample/PrivacyInfo.xcprivacy b/example/ios/ddSdkReactnativeExample/PrivacyInfo.xcprivacy index bad327615..41b8317f0 100644 --- a/example/ios/ddSdkReactnativeExample/PrivacyInfo.xcprivacy +++ b/example/ios/ddSdkReactnativeExample/PrivacyInfo.xcprivacy @@ -6,18 +6,18 @@ NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPICategoryFileTimestamp NSPrivacyAccessedAPITypeReasons - CA92.1 + C617.1 NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPICategoryUserDefaults NSPrivacyAccessedAPITypeReasons - C617.1 + CA92.1 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index e04f5fc2e..96ca2216f 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -2,6 +2,21 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# /!\ Remember to keep this version in sync with the other Datadog podspecs: +# - DatadogSDKReactNativeSessionReplay.podspec +# - DatadogSDKReactNativeWebView.podspec +# - DatadogInternalTesting.podspec +datadog_ios_version = '3.16.0' +datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' + +# The native iOS SDK is resolved through Swift Package Manager, using React Native's +# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links +# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +if !respond_to?(:spm_dependency, true) + raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ + "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." +end + Pod::Spec.new do |s| s.name = "DatadogSDKReactNative" s.version = package["version"] @@ -18,28 +33,56 @@ Pod::Spec.new do |s| s.dependency "React-Core" - # /!\ Remember to keep the versions in sync with DatadogSDKReactNativeSessionReplay.podspec - s.dependency 'DatadogCore', '3.16.0' - s.dependency 'DatadogLogs', '3.16.0' - s.dependency 'DatadogTrace', '3.16.0' - s.dependency 'DatadogRUM', '3.16.0' - s.dependency 'DatadogCrashReporting', '3.16.0' - s.dependency 'DatadogFlags', '3.16.0' - - # DatadogWebViewTracking is not available for tvOS - s.ios.dependency 'DatadogWebViewTracking', '3.16.0' - - s.test_spec 'Tests' do |test_spec| - test_spec.source_files = 'ios/Tests/**/*.{swift,json}' - test_spec.resources = 'ios/Tests/Fixtures' - test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } - end + # `spm_dependency` cannot be scoped per-platform the way `s.ios.dependency` can, so + # DatadogWebViewTracking is requested for every platform here. Our Swift sources already + # guard the import with `#if os(iOS)`, but dd-sdk-ios declares the product for all of its + # package platforms — building this pod for tvOS through SPM is therefore untested. + # + # Note that DatadogInternal is deliberately absent: it is an internal target of + # dd-sdk-ios, not an exported SPM product, so it cannot be requested here. It is expected + # to remain importable because React Native's `spm_dependency` helper appends the SPM + # build-products directory to this target's SWIFT_INCLUDE_PATHS. + spm_dependency(s, + url: datadog_ios_spm_url, + requirement: { kind: 'exactVersion', version: datadog_ios_version }, + products: [ + 'DatadogCore', + 'DatadogLogs', + 'DatadogTrace', + 'DatadogRUM', + 'DatadogCrashReporting', + 'DatadogFlags', + 'DatadogWebViewTracking' + ] + ) + + # The native test suite in ios/Tests relies on `@testable import DatadogCore` and on the Podfile + # injecting DD_SDK_COMPILED_FOR_TESTING into the Datadog pod targets. Neither is possible with the + # SDK resolved by SPM, as it is no longer built as a pod target, so no test spec is declared. + + # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so + # SwiftPM builds it into PackageFrameworks/ instead of emitting a bare .swiftmodule alongside + # the products. React Native's `spm_dependency` helper only appends the products directory to + # SWIFT_INCLUDE_PATHS, which leaves the module invisible to the compiler. Our sources import it + # for AnyEncodable, CoreRegistry, DatadogCoreProtocol and FeatureScope, so add the directory + # holding the package frameworks explicitly. + # + # Note this cannot be written against BUILT_PRODUCTS_DIR: CocoaPods gives every pod target its + # own CONFIGURATION_BUILD_DIR, so for this target BUILT_PRODUCTS_DIR is + # //DatadogSDKReactNative, one level below where SwiftPM actually + # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME + # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + datadog_spm_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + } + + xcconfig = datadog_spm_xcconfig.dup if ENV['RCT_NEW_ARCH_ENABLED'] == '1' - s.pod_target_xcconfig = { + xcconfig.merge!({ "DEFINES_MODULE" => "YES", "OTHER_CPLUSPLUSFLAGS" => "-DRCT_NEW_ARCH_ENABLED=1" - } + }) # install_modules_dependencies is only available on RN >= 0.71 if respond_to?(:install_modules_dependencies, true) @@ -48,4 +91,6 @@ Pod::Spec.new do |s| Pod::UI.warn "Using Datadog React Native SDK with new architecture on RN < 0.71 is discouraged and not officially supported." end end + + s.pod_target_xcconfig = xcconfig end diff --git a/packages/internal-testing-tools/DatadogInternalTesting.podspec b/packages/internal-testing-tools/DatadogInternalTesting.podspec index 46087cf81..0b60ed282 100644 --- a/packages/internal-testing-tools/DatadogInternalTesting.podspec +++ b/packages/internal-testing-tools/DatadogInternalTesting.podspec @@ -2,6 +2,18 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# /!\ Remember to keep this version in sync with DatadogSDKReactNative.podspec +datadog_ios_version = '3.16.0' +datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' + +# The native iOS SDK is resolved through Swift Package Manager, using React Native's +# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links +# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +if !respond_to?(:spm_dependency, true) + raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ + "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." +end + Pod::Spec.new do |s| s.name = "DatadogInternalTesting" s.version = package["version"] @@ -18,20 +30,51 @@ Pod::Spec.new do |s| s.dependency "React-Core" s.dependency "DatadogSDKReactNative" - - s.test_spec 'Tests' do |test_spec| - test_spec.source_files = 'ios/Tests/*.swift' - end + + # DatadogCore and DatadogInternal do not reach this pod through DatadogSDKReactNative: + # React Native's `spm_dependency` helper adds the SPM build-products directory to + # SWIFT_INCLUDE_PATHS per pod target, so this target only gets it by declaring its own SPM + # dependency. Our sources import both DatadogCore and DatadogInternal. + spm_dependency(s, + url: datadog_ios_spm_url, + requirement: { kind: 'exactVersion', version: datadog_ios_version }, + products: ['DatadogCore'] + ) + + # The test spec in ios/Tests does not `@testable import` anything from dd-sdk-ios, but it does + # plainly import DatadogCore and DatadogInternal. Test spec targets are separate from the main + # pod target and so do not receive the SWIFT_INCLUDE_PATHS entry above, which leaves those + # modules unresolvable, so no test spec is declared. # This guard prevents installing the dependencies when we run `pod install` in the old architecture. # The `install_modules_dependencies` function is only available from RN 0.71, the new architecture is not # supported on earlier RN versions. + # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so + # SwiftPM builds it into PackageFrameworks/ instead of emitting a bare .swiftmodule alongside + # the products. React Native's `spm_dependency` helper only appends the products directory to + # SWIFT_INCLUDE_PATHS, which leaves the module invisible to the compiler. Our sources import it + # for AnyEncodable, CoreRegistry, DatadogCoreProtocol and FeatureScope, so add the directory + # holding the package frameworks explicitly. + # + # Note this cannot be written against BUILT_PRODUCTS_DIR: CocoaPods gives every pod target its + # own CONFIGURATION_BUILD_DIR, so for this target BUILT_PRODUCTS_DIR is + # //DatadogSDKReactNative, one level below where SwiftPM actually + # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME + # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + datadog_spm_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + } + + xcconfig = datadog_spm_xcconfig.dup + if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then - s.pod_target_xcconfig = { + xcconfig.merge!({ "DEFINES_MODULE" => "YES", "OTHER_CPLUSPLUSFLAGS" => "-DRCT_NEW_ARCH_ENABLED=1" - } + }) install_modules_dependencies(s) end + + s.pod_target_xcconfig = xcconfig end diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index a78a62ca4..e121ee317 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -2,6 +2,18 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# /!\ Remember to keep this version in sync with DatadogSDKReactNative.podspec +datadog_ios_version = '3.16.0' +datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' + +# The native iOS SDK is resolved through Swift Package Manager, using React Native's +# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links +# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +if !respond_to?(:spm_dependency, true) + raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ + "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." +end + Pod::Spec.new do |s| s.name = "DatadogSDKReactNativeSessionReplay" s.version = package["version"] @@ -15,21 +27,35 @@ Pod::Spec.new do |s| s.source_files = "ios/Sources/**/*.{h,m,mm,swift}" - s.resource_bundles = { - 'DDSessionReplay' => ['assets/assets.json', 'assets/assets.bin'] - } + # A CocoaPods resource bundle would create a second target (`-DDSessionReplay`) whose + # CONFIGURATION_BUILD_DIR is pinned, inline in the generated project, to the pod-scoped + # //DatadogSDKReactNativeSessionReplay. When the pod also declares an + # SPM dependency, Xcode picks that bundle target as the host for the package's own resource + # bundles (Datadog_DatadogRUM.bundle, KSCrash_*.bundle, ...) and emits implicit copy tasks that + # read them from that pod-scoped directory -- while SwiftPM writes them to the shared products + # root one level up. The copies then fail with "no such file", and because the build dir is set + # inline rather than through the pod's xcconfig there is no way to redirect them from a podspec. + # Ship the two assets as plain resources instead: with no bundle target there is nothing for + # Xcode to mis-host, and it embeds the package resources into the app target as it does for the + # other Datadog pods. Bundle+SessionReplay.swift handles both layouts. + s.resources = ['assets/assets.json', 'assets/assets.bin'] s.dependency "React-Core" - - # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogSessionReplay', '3.16.0' s.dependency 'DatadogSDKReactNative' - s.test_spec 'Tests' do |test_spec| - test_spec.dependency "React-RCTText" - test_spec.source_files = 'ios/Tests/*.swift' - test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } - end + # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so + # it cannot be requested here; it is expected to stay importable via the SWIFT_INCLUDE_PATHS + # entry that React Native's `spm_dependency` helper adds to this target. + spm_dependency(s, + url: datadog_ios_spm_url, + requirement: { kind: 'exactVersion', version: datadog_ios_version }, + products: ['DatadogSessionReplay'] + ) + + # The native test suite in ios/Tests relies on `@testable import DatadogSessionReplay` and on the + # Podfile injecting DD_SDK_COMPILED_FOR_TESTING into the Datadog pod targets. Neither is possible + # with the SDK resolved by SPM, as it is no longer built as a pod target, so no test spec is + # declared. header_paths = %W[ $(inherited) @@ -42,11 +68,29 @@ Pod::Spec.new do |s| $(PODS_CONFIGURATION_BUILD_DIR)/React-timing/React_timing.framework/Headers/** ].join(' ') + # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so + # SwiftPM builds it into PackageFrameworks/ instead of emitting a bare .swiftmodule alongside + # the products. React Native's `spm_dependency` helper only appends the products directory to + # SWIFT_INCLUDE_PATHS, which leaves the module invisible to the compiler. Our sources import it + # for AnyEncodable, CoreRegistry, DatadogCoreProtocol and FeatureScope, so add the directory + # holding the package frameworks explicitly. + # + # Note this cannot be written against BUILT_PRODUCTS_DIR: CocoaPods gives every pod target its + # own CONFIGURATION_BUILD_DIR, so for this target BUILT_PRODUCTS_DIR is + # //DatadogSDKReactNative, one level below where SwiftPM actually + # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME + # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + datadog_spm_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + } + xcconfig = { 'HEADER_SEARCH_PATHS' => header_paths, 'USER_HEADER_SEARCH_PATHS' => header_paths, } + xcconfig.merge!(datadog_spm_xcconfig) + if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then s.compiler_flags = "-DRCT_NEW_ARCH_ENABLED=1" diff --git a/packages/react-native-session-replay/ios/Sources/Utils/Bundle+SessionReplay.swift b/packages/react-native-session-replay/ios/Sources/Utils/Bundle+SessionReplay.swift index 17e6f2d10..aae98deba 100644 --- a/packages/react-native-session-replay/ios/Sources/Utils/Bundle+SessionReplay.swift +++ b/packages/react-native-session-replay/ios/Sources/Utils/Bundle+SessionReplay.swift @@ -16,6 +16,9 @@ extension Bundle { return resourceBundle } - return nil + // When the native iOS SDK is resolved through Swift Package Manager the podspec ships the + // assets as plain resources rather than in a DDSessionReplay bundle, so they sit directly + // in the bundle we just looked in. + return bundle } } diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 722e76634..3440eb22e 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -2,6 +2,18 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# /!\ Remember to keep this version in sync with DatadogSDKReactNative.podspec +datadog_ios_version = '3.16.0' +datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' + +# The native iOS SDK is resolved through Swift Package Manager, using React Native's +# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links +# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +if !respond_to?(:spm_dependency, true) + raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ + "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." +end + Pod::Spec.new do |s| s.name = "DatadogSDKReactNativeWebView" s.version = package["version"] @@ -17,27 +29,50 @@ Pod::Spec.new do |s| s.source_files = "ios/Sources/*.{h,m,mm,swift}" s.dependency "React-Core" + s.dependency 'DatadogSDKReactNative' - if ENV['USE_FRAMEWORKS'] == 'static' - s.dependency "react-native-webview" - end + # Our headers subclass RNCWebViewImpl / RNCWebViewManager. Under framework linkage those headers + # are only reachable as , which requires react-native-webview to be a + # declared dependency so that CocoaPods puts its build directory on this target's + # FRAMEWORK_SEARCH_PATHS. + s.dependency "react-native-webview" - # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogWebViewTracking', '3.16.0' - s.dependency 'DatadogInternal', '3.16.0' - s.dependency 'DatadogSDKReactNative' + # DatadogInternal was previously declared explicitly here, but it is an internal target of + # dd-sdk-ios rather than an exported SPM product, so it cannot be requested. It is expected + # to stay importable via the SWIFT_INCLUDE_PATHS entry that React Native's `spm_dependency` + # helper adds to this target. + spm_dependency(s, + url: datadog_ios_spm_url, + requirement: { kind: 'exactVersion', version: datadog_ios_version }, + products: ['DatadogWebViewTracking'] + ) - s.test_spec 'Tests' do |test_spec| - test_spec.dependency "react-native-webview" - test_spec.dependency "React-RCTText" - - test_spec.source_files = 'ios/Tests/*.swift' - test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } - end + # The native test suite in ios/Tests relies on `@testable import DatadogWebViewTracking` and on + # the Podfile injecting DD_SDK_COMPILED_FOR_TESTING into the Datadog pod targets. Neither is + # possible with the SDK resolved by SPM, as it is no longer built as a pod target, so no test + # spec is declared. + + # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so + # SwiftPM builds it into PackageFrameworks/ instead of emitting a bare .swiftmodule alongside + # the products. React Native's `spm_dependency` helper only appends the products directory to + # SWIFT_INCLUDE_PATHS, which leaves the module invisible to the compiler. Our sources import it + # for AnyEncodable, CoreRegistry, DatadogCoreProtocol and FeatureScope, so add the directory + # holding the package frameworks explicitly. + # + # Note this cannot be written against BUILT_PRODUCTS_DIR: CocoaPods gives every pod target its + # own CONFIGURATION_BUILD_DIR, so for this target BUILT_PRODUCTS_DIR is + # //DatadogSDKReactNative, one level below where SwiftPM actually + # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME + # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + datadog_spm_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + } xcconfig = { "HEADER_SEARCH_PATHS" => "$(PODS_ROOT)/react-native-webview/**" } + + xcconfig.merge!(datadog_spm_xcconfig) # This guard prevents installing the dependencies when we run `pod install` in the old architecture. # The `install_modules_dependencies` function is only available from RN 0.71, the new architecture is not diff --git a/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h b/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h index 70bed4bd8..1fc7489a6 100644 --- a/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h +++ b/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h @@ -9,4 +9,13 @@ #import "RCTDatadogWebView.h" #import "RCTDatadogWebViewManager.h" +// react-native-webview is a static library under CocoaPods' default linkage, where its public +// headers land flat in Pods/Headers/Public and resolve as a quoted import. When the pod is built +// as a dynamic framework instead -- which is mandatory when the native Datadog iOS SDK is resolved +// through Swift Package Manager --the same header is only reachable +// as . Support both layouts. +#if __has_include() +#import +#else #import "RNCWebViewImpl.h" +#endif diff --git a/packages/react-native-webview/ios/Sources/RCTDatadogWebView.h b/packages/react-native-webview/ios/Sources/RCTDatadogWebView.h index 69b498a3d..3182f5504 100644 --- a/packages/react-native-webview/ios/Sources/RCTDatadogWebView.h +++ b/packages/react-native-webview/ios/Sources/RCTDatadogWebView.h @@ -4,7 +4,16 @@ * Copyright 2016-Present Datadog, Inc. */ +// react-native-webview is a static library under CocoaPods' default linkage, where its public +// headers land flat in Pods/Headers/Public and resolve as a quoted import. When the pod is built +// as a dynamic framework instead -- which is mandatory when the native Datadog iOS SDK is resolved +// through Swift Package Manager -- the same header is only reachable +// as . Support both layouts. +#if __has_include() +#import +#else #import "RNCWebViewImpl.h" +#endif @class RCTDatadogWebView; @@ -14,8 +23,8 @@ @interface RCTDatadogWebView : RNCWebViewImpl -@property (nonatomic, weak) id ddWebViewDelegate; -@property (nonatomic, assign) BOOL isTrackingEnabled; +@property(nonatomic, weak) id ddWebViewDelegate; +@property(nonatomic, assign) BOOL isTrackingEnabled; -- (WKWebView*) getWKWebView; +- (WKWebView *)getWKWebView; @end diff --git a/packages/react-native-webview/ios/Sources/RCTDatadogWebViewManager.h b/packages/react-native-webview/ios/Sources/RCTDatadogWebViewManager.h index 96e0dc2c1..2eb1bfc92 100644 --- a/packages/react-native-webview/ios/Sources/RCTDatadogWebViewManager.h +++ b/packages/react-native-webview/ios/Sources/RCTDatadogWebViewManager.h @@ -4,7 +4,14 @@ * Copyright 2016-Present Datadog, Inc. */ +// See the note in RCTDatadogWebView.h: this header resolves as a quoted import under CocoaPods' +// default static linkage, but only as when the pod is built as a +// dynamic framework. +#if __has_include() +#import +#else #import "RNCWebViewManager.h" +#endif @interface RCTDatadogWebViewManager : RNCWebViewManager @end From 2fffe9f1ee183b8830f351653b8e53843555f23b Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Tue, 29 Sep 2026 12:48:29 +0200 Subject: [PATCH 02/19] Add missing React-RCTText dependency and resolve OpenTelemetry from SwiftPM in benchmarks --- .../BenchmarkRunner.xcodeproj/project.pbxproj | 31 +++++++++++++++++++ benchmarks/ios/Podfile | 14 +++++---- benchmarks/ios/Podfile.lock | 13 ++------ example/ios/Podfile.lock | 3 +- packages/core/DatadogSDKReactNative.podspec | 5 ++- ...DatadogSDKReactNativeSessionReplay.podspec | 11 +++++-- 6 files changed, 54 insertions(+), 23 deletions(-) diff --git a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj index b5f481b32..e57958af2 100644 --- a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 043403262DCB9CD700803AF8 /* BenchmarkVitals.mm in Sources */ = {isa = PBXBuildFile; fileRef = 043403242DCB9CD700803AF8 /* BenchmarkVitals.mm */; }; 04576C962DCBAF900078DCAB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 04576C952DCBAF900078DCAB /* main.m */; }; 04726DD72F46402A008D1A48 /* TracerProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04726DD62F46402A008D1A48 /* TracerProvider.swift */; }; + 10520E8C306BAEDB00BBFBFF /* OpenTelemetryApi in Frameworks */ = {isa = PBXBuildFile; productRef = 10520E8B306BAEDB00BBFBFF /* OpenTelemetryApi */; }; + 10520E8E306BAEDB00BBFBFF /* OpenTelemetrySdk in Frameworks */ = {isa = PBXBuildFile; productRef = 10520E8D306BAEDB00BBFBFF /* OpenTelemetrySdk */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 20A397FC280595A8A9851556 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; 52040CC80A3CB0E4C3A131B0 /* Pods_BenchmarkRunner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E927512A5C6D462705AE797 /* Pods_BenchmarkRunner.framework */; }; @@ -53,7 +55,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 10520E8E306BAEDB00BBFBFF /* OpenTelemetrySdk in Frameworks */, 52040CC80A3CB0E4C3A131B0 /* Pods_BenchmarkRunner.framework in Frameworks */, + 10520E8C306BAEDB00BBFBFF /* OpenTelemetryApi in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -200,6 +204,9 @@ Base, ); mainGroup = 83CBB9F61A601CBA00E9B192; + packageReferences = ( + 10520E8A306BAEDB00BBFBFF /* XCRemoteSwiftPackageReference "opentelemetry-swift-core" */, + ); productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -721,6 +728,30 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 10520E8A306BAEDB00BBFBFF /* XCRemoteSwiftPackageReference "opentelemetry-swift-core" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/open-telemetry/opentelemetry-swift-core"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 2.5.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 10520E8B306BAEDB00BBFBFF /* OpenTelemetryApi */ = { + isa = XCSwiftPackageProductDependency; + package = 10520E8A306BAEDB00BBFBFF /* XCRemoteSwiftPackageReference "opentelemetry-swift-core" */; + productName = OpenTelemetryApi; + }; + 10520E8D306BAEDB00BBFBFF /* OpenTelemetrySdk */ = { + isa = XCSwiftPackageProductDependency; + package = 10520E8A306BAEDB00BBFBFF /* XCRemoteSwiftPackageReference "opentelemetry-swift-core" */; + productName = OpenTelemetrySdk; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; } diff --git a/benchmarks/ios/Podfile b/benchmarks/ios/Podfile index 89ec38a2f..829d1b642 100644 --- a/benchmarks/ios/Podfile +++ b/benchmarks/ios/Podfile @@ -23,13 +23,15 @@ target 'BenchmarkRunner' do :app_path => "#{Pod::Config.instance.installation_root}/.." ) - # OpenTelemetrySdk is needed by the BenchmarkVitals code (metrics exporter, meter provider). - # OpenTelemetryApi is already pulled in transitively via DatadogTrace, but OpenTelemetrySdk is not. + # OpenTelemetryApi and OpenTelemetrySdk are needed by the BenchmarkVitals code (metrics exporter, + # meter provider). They are not declared here: DatadogTrace already resolves + # opentelemetry-swift-core through SwiftPM, and both are products of that same package, so the + # BenchmarkRunner target links them directly from it. # - # /!\ DatadogTrace now pulls opentelemetry-swift-core through SwiftPM while this pod pulls - # OpenTelemetryApi through CocoaPods, so OpenTelemetryApi arrives via both package managers and - # may collide at link time. Untested -- if it does, source OpenTelemetrySdk from SPM too. - pod 'OpenTelemetry-Swift-Sdk', '~> 2.5.0' + # Pulling OpenTelemetrySdk from CocoaPods instead would bring a second copy of the OpenTelemetryApi + # module into the build -- one from the pod, one from SwiftPM -- which makes Xcode's explicit + # module scanner emit "is missing a dependency on 'OpenTelemetryApi'" warnings across every target + # that touches it. post_install do |installer| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index baf3114c4..4a15ed11d 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -37,6 +37,7 @@ PODS: - React-ImageManager - React-NativeModulesApple - React-RCTFabric + - React-RCTText - React-rendererdebug - React-utils - ReactCodegen @@ -74,9 +75,6 @@ PODS: - hermes-engine (0.78.2): - hermes-engine/Pre-built (= 0.78.2) - hermes-engine/Pre-built (0.78.2) - - OpenTelemetry-Swift-Api (2.5.1) - - OpenTelemetry-Swift-Sdk (2.5.1): - - OpenTelemetry-Swift-Api (= 2.5.1) - RCT-Folly (2024.11.18.00): - boost - DoubleConversion @@ -1851,7 +1849,6 @@ DEPENDENCIES: - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - OpenTelemetry-Swift-Sdk (~> 2.5.0) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) @@ -1923,8 +1920,6 @@ DEPENDENCIES: SPEC REPOS: https://github.com/CocoaPods/Specs.git: - - OpenTelemetry-Swift-Api - - OpenTelemetry-Swift-Sdk - SocketRocket EXTERNAL SOURCES: @@ -2085,7 +2080,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DatadogSDKReactNative: a7089e56cc0cfa72a1cafdc7abe8fef5f627bf9a - DatadogSDKReactNativeSessionReplay: 459fac6340f6b5edbb0045ffe1ef0015f7cabfbb + DatadogSDKReactNativeSessionReplay: 1687076f3ccd50cff8233738a83188ad84480384 DatadogSDKReactNativeWebView: 307574a321eb9646dbbe954d9b3654ec0666c240 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 @@ -2093,8 +2088,6 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 hermes-engine: 2771b98fb813fdc6f92edd7c9c0035ecabf9fee7 - OpenTelemetry-Swift-Api: 3be9043f6288eb4ac3cbe7548b5bd45fb4ed5849 - OpenTelemetry-Swift-Sdk: d9fa7bc839350f5a81467a5e877f727a8a77712d RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 RCTDeprecation: be794de7dc6ed8f9f7fbf525f86e7651b8b68746 RCTRequired: a83787b092ec554c2eb6019ff3f5b8d125472b3b @@ -2163,6 +2156,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 6eb60fc2c0eef63e7d2ef4a56e0a3353534143a2 -PODFILE CHECKSUM: 1b136836f3fad4e4ab921bff5d885c5d6596bcf4 +PODFILE CHECKSUM: 26bbffd54a9dc71f8787dc1ed59dcb5c1fc2e42e COCOAPODS: 1.16.2 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f2583f929..bfbdc72f2 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -5,6 +5,7 @@ PODS: - DatadogSDKReactNativeSessionReplay (3.8.0): - DatadogSDKReactNative - React-Core + - React-RCTText - DatadogSDKReactNativeWebView (3.8.0): - DatadogSDKReactNative - React-Core @@ -1891,7 +1892,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 DatadogSDKReactNative: 11a3d7460bac8d7e7750f4687fbe67214dd28edb - DatadogSDKReactNativeSessionReplay: 81c99bcdcbdb52aff01676bcdc15cbd4df67506c + DatadogSDKReactNativeSessionReplay: 4303aae49986751dbf7b7de4e2ad3026abe9dd90 DatadogSDKReactNativeWebView: 410633d047e11261985c97e9f71749c727211e2c DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index 96ca2216f..46e04b382 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -39,9 +39,8 @@ Pod::Spec.new do |s| # package platforms — building this pod for tvOS through SPM is therefore untested. # # Note that DatadogInternal is deliberately absent: it is an internal target of - # dd-sdk-ios, not an exported SPM product, so it cannot be requested here. It is expected - # to remain importable because React Native's `spm_dependency` helper appends the SPM - # build-products directory to this target's SWIFT_INCLUDE_PATHS. + # dd-sdk-ios, not an exported SPM product, so it cannot be requested here. Making it + # importable takes an extra search path -- see the FRAMEWORK_SEARCH_PATHS note below. spm_dependency(s, url: datadog_ios_spm_url, requirement: { kind: 'exactVersion', version: datadog_ios_version }, diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index e121ee317..381f79c9b 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -41,11 +41,16 @@ Pod::Spec.new do |s| s.resources = ['assets/assets.json', 'assets/assets.bin'] s.dependency "React-Core" + # RCTTextExtractor.mm references RCTTextView and the RCTText shadow view classes directly, so + # this pod has always had a link-time dependency on React-RCTText. It was only declared on the + # test spec, which went unnoticed while pods were linked statically and undefined symbols were + # deferred to the app link. + s.dependency "React-RCTText" s.dependency 'DatadogSDKReactNative' - # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so - # it cannot be requested here; it is expected to stay importable via the SWIFT_INCLUDE_PATHS - # entry that React Native's `spm_dependency` helper adds to this target. + # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so it + # cannot be requested here. Making it importable takes an extra search path -- see the + # FRAMEWORK_SEARCH_PATHS note below. spm_dependency(s, url: datadog_ios_spm_url, requirement: { kind: 'exactVersion', version: datadog_ios_version }, From 9025bea8ebea652a7f687b3762eb948bfecb697a Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Tue, 29 Sep 2026 15:06:24 +0200 Subject: [PATCH 03/19] Restore the native test suites removed during the SwiftPM migration --- example-new-architecture/ios/Podfile | 4 +-- example-new-architecture/ios/Podfile.lock | 26 +++++++++++++++++-- example/ios/Podfile | 14 +++++----- example/ios/Podfile.lock | 22 +++++++++++++--- packages/core/DatadogSDKReactNative.podspec | 8 +++--- .../core/ios/Tests/AnyEncodableTests.swift | 1 + .../ios/Tests/DatadogSdkWrapperTests.swift | 1 + packages/core/ios/Tests/DdFlagsTests.swift | 1 + packages/core/ios/Tests/DdLogsTests.swift | 1 + packages/core/ios/Tests/DdRumTests.swift | 1 + .../DdSdkNativeInitializationTests.swift | 1 + .../DdSdkSessionStartedListenerTests.swift | 1 + packages/core/ios/Tests/DdSdkTests.swift | 1 + packages/core/ios/Tests/DdTraceTests.swift | 1 + .../core/ios/Tests/GlobalStateTests.swift | 1 + packages/core/ios/Tests/MockDatadogCore.swift | 1 + packages/core/ios/Tests/MockRUMMonitor.swift | 1 + packages/core/ios/Tests/ModulesTest.swift | 1 + .../ios/Tests/RNDdSdkConfigurationTests.swift | 1 + packages/core/ios/Tests/RUMMocks.swift | 1 + ...DatadogSDKReactNativeSessionReplay.podspec | 18 ++++++++++--- .../ios/Tests/DdSessionReplayTests.swift | 1 + .../ios/Tests/RCTTextViewRecorderTests.swift | 1 + .../DatadogSDKReactNativeWebView.podspec | 18 ++++++++++--- 24 files changed, 100 insertions(+), 27 deletions(-) diff --git a/example-new-architecture/ios/Podfile b/example-new-architecture/ios/Podfile index da453411d..48dbc648d 100644 --- a/example-new-architecture/ios/Podfile +++ b/example-new-architecture/ios/Podfile @@ -19,9 +19,7 @@ prepare_react_native_project! use_frameworks! :linkage => :dynamic target 'DdSdkReactNativeExample' do - # No `:testspecs` here: the Datadog podspecs declare no test spec, because the native tests need - # `@testable` access to Datadog pod targets that do not exist once the SDK comes from SPM. - pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec' + pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec', :testspecs => ['Tests'] config = use_native_modules! diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index bc07dbd4d..24ea0f70c 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -21,6 +21,27 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - DatadogSDKReactNative/Tests (3.8.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.10.14.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1585,6 +1606,7 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DatadogSDKReactNative (from `../../packages/core/DatadogSDKReactNative.podspec`) + - DatadogSDKReactNative/Tests (from `../../packages/core/DatadogSDKReactNative.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) @@ -1790,7 +1812,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogSDKReactNative: 4658ccf5324b283cec0b441733ae55d5fa2e3096 + DatadogSDKReactNative: e281de7e36ebf1f752d237f975d8bdc4db044ef8 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -1856,6 +1878,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 1259c7a8cbaccf7b4c3ddf8ee36ca11be9dee407 -PODFILE CHECKSUM: e2bfd31ede533b920dccdc714d311ef0b2e666ac +PODFILE CHECKSUM: 65bae30d106f4e0fed15150fb60695cc8cddcf1b COCOAPODS: 1.16.2 diff --git a/example/ios/Podfile b/example/ios/Podfile index 39caa3369..20104baa9 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -15,11 +15,9 @@ prepare_react_native_project! use_frameworks! :linkage => :dynamic target 'ddSdkReactnativeExample' do - # No `:testspecs` here: the Datadog podspecs declare no test spec, because the native tests need - # `@testable` access to Datadog pod targets that do not exist once the SDK comes from SPM. - pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec' - pod 'DatadogSDKReactNativeSessionReplay', :path => '../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec' - pod 'DatadogSDKReactNativeWebView', :path => '../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec' + pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec', :testspecs => ['Tests'] + pod 'DatadogSDKReactNativeSessionReplay', :path => '../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec', :testspecs => ['Tests'] + pod 'DatadogSDKReactNativeWebView', :path => '../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec', :testspecs => ['Tests'] config = use_native_modules! @@ -38,8 +36,10 @@ target 'ddSdkReactnativeExample' do config[:reactNativePath], :mac_catalyst_enabled => false ) - # No `DD_SDK_COMPILED_FOR_TESTING` injection: the Datadog iOS SDK is no longer built as a pod - # target, so there is no build configuration to set it on. + # `DD_SDK_COMPILED_FOR_TESTING` is no longer injected. There is no pod target to set it on now + # that the SDK comes from SPM, and the native tests never needed it: none of them touch the + # three declarations it guards (`Datadog.flushAndDeinitialize` and its ObjC counterpart, and + # `DatadogContextProvider.replace(context:)`). installer.pods_project.targets.each do |target| target.build_configurations.each do |config| diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index bfbdc72f2..a8cca838e 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2,14 +2,25 @@ PODS: - boost (1.84.0) - DatadogSDKReactNative (3.8.0): - React-Core + - DatadogSDKReactNative/Tests (3.8.0): + - React-Core - DatadogSDKReactNativeSessionReplay (3.8.0): - DatadogSDKReactNative - React-Core - React-RCTText + - DatadogSDKReactNativeSessionReplay/Tests (3.8.0): + - DatadogSDKReactNative + - React-Core + - React-RCTText - DatadogSDKReactNativeWebView (3.8.0): - DatadogSDKReactNative - React-Core - react-native-webview + - DatadogSDKReactNativeWebView/Tests (3.8.0): + - DatadogSDKReactNative + - React-Core + - react-native-webview + - React-RCTText - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1658,8 +1669,11 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DatadogSDKReactNative (from `../../packages/core/DatadogSDKReactNative.podspec`) + - DatadogSDKReactNative/Tests (from `../../packages/core/DatadogSDKReactNative.podspec`) - DatadogSDKReactNativeSessionReplay (from `../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec`) + - DatadogSDKReactNativeSessionReplay/Tests (from `../../packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec`) - DatadogSDKReactNativeWebView (from `../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec`) + - DatadogSDKReactNativeWebView/Tests (from `../../packages/react-native-webview/DatadogSDKReactNativeWebView.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) @@ -1891,9 +1905,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogSDKReactNative: 11a3d7460bac8d7e7750f4687fbe67214dd28edb - DatadogSDKReactNativeSessionReplay: 4303aae49986751dbf7b7de4e2ad3026abe9dd90 - DatadogSDKReactNativeWebView: 410633d047e11261985c97e9f71749c727211e2c + DatadogSDKReactNative: 0436a25ca50eb0feb28a69db28cb537ac518bf3e + DatadogSDKReactNativeSessionReplay: 7ed882cd305f191988d9d8eff2ad57c9d736b21b + DatadogSDKReactNativeWebView: 34a534d31fef518cd26c205ea5679123f666a836 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -1967,6 +1981,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 1259c7a8cbaccf7b4c3ddf8ee36ca11be9dee407 -PODFILE CHECKSUM: bf984a17ba7e485ff3a3654018482eba3acf4687 +PODFILE CHECKSUM: 04d9739a3e9c4afbe3a81d5f7ddf602c423f0e9a COCOAPODS: 1.16.2 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index 46e04b382..c154f32cc 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -55,9 +55,11 @@ Pod::Spec.new do |s| ] ) - # The native test suite in ios/Tests relies on `@testable import DatadogCore` and on the Podfile - # injecting DD_SDK_COMPILED_FOR_TESTING into the Datadog pod targets. Neither is possible with the - # SDK resolved by SPM, as it is no longer built as a pod target, so no test spec is declared. + s.test_spec 'Tests' do |test_spec| + test_spec.source_files = 'ios/Tests/**/*.{swift,json}' + test_spec.resources = 'ios/Tests/Fixtures' + test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } + end # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so # SwiftPM builds it into PackageFrameworks/ instead of emitting a bare .swiftmodule alongside diff --git a/packages/core/ios/Tests/AnyEncodableTests.swift b/packages/core/ios/Tests/AnyEncodableTests.swift index ef20db530..ae8943c31 100644 --- a/packages/core/ios/Tests/AnyEncodableTests.swift +++ b/packages/core/ios/Tests/AnyEncodableTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative @testable import DatadogInternal diff --git a/packages/core/ios/Tests/DatadogSdkWrapperTests.swift b/packages/core/ios/Tests/DatadogSdkWrapperTests.swift index a445b2bbe..5be27d58e 100644 --- a/packages/core/ios/Tests/DatadogSdkWrapperTests.swift +++ b/packages/core/ios/Tests/DatadogSdkWrapperTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative import DatadogTrace diff --git a/packages/core/ios/Tests/DdFlagsTests.swift b/packages/core/ios/Tests/DdFlagsTests.swift index 3fca72ddc..80cc00b95 100644 --- a/packages/core/ios/Tests/DdFlagsTests.swift +++ b/packages/core/ios/Tests/DdFlagsTests.swift @@ -4,6 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ +import Foundation import XCTest import DatadogCore @_spi(Internal) diff --git a/packages/core/ios/Tests/DdLogsTests.swift b/packages/core/ios/Tests/DdLogsTests.swift index 390c947d4..253ec213e 100644 --- a/packages/core/ios/Tests/DdLogsTests.swift +++ b/packages/core/ios/Tests/DdLogsTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative import DatadogLogs diff --git a/packages/core/ios/Tests/DdRumTests.swift b/packages/core/ios/Tests/DdRumTests.swift index 0ede8766d..fa037e70e 100644 --- a/packages/core/ios/Tests/DdRumTests.swift +++ b/packages/core/ios/Tests/DdRumTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogCore @testable import DatadogRUM diff --git a/packages/core/ios/Tests/DdSdkNativeInitializationTests.swift b/packages/core/ios/Tests/DdSdkNativeInitializationTests.swift index cb6a6c500..eee47deb9 100644 --- a/packages/core/ios/Tests/DdSdkNativeInitializationTests.swift +++ b/packages/core/ios/Tests/DdSdkNativeInitializationTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-Present Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogCore @testable import DatadogSDKReactNative diff --git a/packages/core/ios/Tests/DdSdkSessionStartedListenerTests.swift b/packages/core/ios/Tests/DdSdkSessionStartedListenerTests.swift index c891dc8e4..5f6e2d8ca 100644 --- a/packages/core/ios/Tests/DdSdkSessionStartedListenerTests.swift +++ b/packages/core/ios/Tests/DdSdkSessionStartedListenerTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-Present Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative @testable import React diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index bc13c4f98..5642da954 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogCore diff --git a/packages/core/ios/Tests/DdTraceTests.swift b/packages/core/ios/Tests/DdTraceTests.swift index 3de9978ee..141fe93a2 100644 --- a/packages/core/ios/Tests/DdTraceTests.swift +++ b/packages/core/ios/Tests/DdTraceTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative @testable import DatadogCore diff --git a/packages/core/ios/Tests/GlobalStateTests.swift b/packages/core/ios/Tests/GlobalStateTests.swift index 1def8ad6a..f7f87e7fc 100644 --- a/packages/core/ios/Tests/GlobalStateTests.swift +++ b/packages/core/ios/Tests/GlobalStateTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-Present Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative diff --git a/packages/core/ios/Tests/MockDatadogCore.swift b/packages/core/ios/Tests/MockDatadogCore.swift index a7dcad130..81556fb52 100644 --- a/packages/core/ios/Tests/MockDatadogCore.swift +++ b/packages/core/ios/Tests/MockDatadogCore.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation @testable import DatadogCore @testable import DatadogInternal diff --git a/packages/core/ios/Tests/MockRUMMonitor.swift b/packages/core/ios/Tests/MockRUMMonitor.swift index ce1d2c6cd..3b25d9279 100644 --- a/packages/core/ios/Tests/MockRUMMonitor.swift +++ b/packages/core/ios/Tests/MockRUMMonitor.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation @testable import DatadogCore @testable import DatadogRUM @testable import DatadogInternal diff --git a/packages/core/ios/Tests/ModulesTest.swift b/packages/core/ios/Tests/ModulesTest.swift index d8f1f0358..8d1f47a9e 100644 --- a/packages/core/ios/Tests/ModulesTest.swift +++ b/packages/core/ios/Tests/ModulesTest.swift @@ -4,6 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative @testable import React diff --git a/packages/core/ios/Tests/RNDdSdkConfigurationTests.swift b/packages/core/ios/Tests/RNDdSdkConfigurationTests.swift index 00e73e399..65855fad6 100644 --- a/packages/core/ios/Tests/RNDdSdkConfigurationTests.swift +++ b/packages/core/ios/Tests/RNDdSdkConfigurationTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-Present Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNative @testable import DatadogInternal diff --git a/packages/core/ios/Tests/RUMMocks.swift b/packages/core/ios/Tests/RUMMocks.swift index c07f0fa7f..f8913e1b1 100644 --- a/packages/core/ios/Tests/RUMMocks.swift +++ b/packages/core/ios/Tests/RUMMocks.swift @@ -4,6 +4,7 @@ * Copyright 2019-Present Datadog, Inc. */ +import Foundation @testable import DatadogRUM @testable import DatadogCore @testable import DatadogInternal diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 381f79c9b..8588b735c 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -57,10 +57,20 @@ Pod::Spec.new do |s| products: ['DatadogSessionReplay'] ) - # The native test suite in ios/Tests relies on `@testable import DatadogSessionReplay` and on the - # Podfile injecting DD_SDK_COMPILED_FOR_TESTING into the Datadog pod targets. Neither is possible - # with the SDK resolved by SPM, as it is no longer built as a pod target, so no test spec is - # declared. + # React-RCTText is not repeated here: it is declared on the main spec above, which the test spec + # inherits. + s.test_spec 'Tests' do |test_spec| + test_spec.source_files = 'ios/Tests/*.swift' + test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } + + # The tests reference DatadogInternal protocol descriptors (Storage, Telemetry) directly. Unlike + # the SPM products, DatadogInternal is not on this target's link line, so name it explicitly -- + # and point the linker at PackageFrameworks, where SwiftPM writes non-product targets. + test_spec.pod_target_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', + 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' + } + end header_paths = %W[ $(inherited) diff --git a/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift b/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift index 741f8318a..dfb05c6ef 100644 --- a/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift +++ b/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNativeSessionReplay import DatadogSessionReplay diff --git a/packages/react-native-session-replay/ios/Tests/RCTTextViewRecorderTests.swift b/packages/react-native-session-replay/ios/Tests/RCTTextViewRecorderTests.swift index 3fd300c51..d27453546 100644 --- a/packages/react-native-session-replay/ios/Tests/RCTTextViewRecorderTests.swift +++ b/packages/react-native-session-replay/ios/Tests/RCTTextViewRecorderTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogSDKReactNativeSessionReplay @_spi(Internal) diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 3440eb22e..8bc1ba851 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -47,10 +47,20 @@ Pod::Spec.new do |s| products: ['DatadogWebViewTracking'] ) - # The native test suite in ios/Tests relies on `@testable import DatadogWebViewTracking` and on - # the Podfile injecting DD_SDK_COMPILED_FOR_TESTING into the Datadog pod targets. Neither is - # possible with the SDK resolved by SPM, as it is no longer built as a pod target, so no test - # spec is declared. + s.test_spec 'Tests' do |test_spec| + test_spec.dependency "react-native-webview" + test_spec.dependency "React-RCTText" + + test_spec.source_files = 'ios/Tests/*.swift' + test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } + + # The tests reach DatadogInternal directly, which is not on this target's link line because it + # is a target of dd-sdk-ios rather than one of the SPM products this pod requests. + test_spec.pod_target_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', + 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' + } + end # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so # SwiftPM builds it into PackageFrameworks/ instead of emitting a bare .swiftmodule alongside From fd15fea48fde8ae0b523e3fd499ba113b387ffb0 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Wed, 30 Sep 2026 09:38:26 +0200 Subject: [PATCH 04/19] Fix webview main target link failure and restore internal-testing-tools test spec The webview podspec only requested DatadogWebViewTracking via spm_dependency, relying on FRAMEWORK_SEARCH_PATHS to make DatadogInternal importable. That's enough to compile against it, but not to link it: unlike DatadogCore and DatadogSessionReplay, DatadogWebViewTracking's own autolink metadata doesn't pull DatadogInternal onto this target's link line, so RCTDatadogWebViewTracking.swift's direct references to it were left unresolved at link time. Verified with a full DerivedData wipe + clean build, not just a retry. Also documents the missing use_frameworks! :linkage => :dynamic requirement in the core, session-replay, and webview READMEs, and restores internal-testing-tools' test spec following the same pattern as the other three packages -- though unlike those, it could not be verified against a real build: no app in this repo installs this pod, and a local CocoaPods/Xcode compatibility issue corrupts Pods.xcodeproj when adding it as a fourth SPM-consuming target. --- example/ios/Podfile.lock | 2 +- packages/core/README.md | 8 +++++++- .../DatadogInternalTesting.podspec | 18 ++++++++++++++---- .../ios/Tests/DdInternalTestingTests.swift | 1 + packages/react-native-session-replay/README.md | 6 ++++++ .../DatadogSDKReactNativeWebView.podspec | 13 +++++++++---- packages/react-native-webview/README.md | 6 ++++++ 7 files changed, 44 insertions(+), 10 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a8cca838e..eda33a822 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1907,7 +1907,7 @@ SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 DatadogSDKReactNative: 0436a25ca50eb0feb28a69db28cb537ac518bf3e DatadogSDKReactNativeSessionReplay: 7ed882cd305f191988d9d8eff2ad57c9d736b21b - DatadogSDKReactNativeWebView: 34a534d31fef518cd26c205ea5679123f666a836 + DatadogSDKReactNativeWebView: 704642ca731507fdeb60ad31d8f29fe91460ca52 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/README.md b/packages/core/README.md index 6b61e7510..ecd93a410 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -16,7 +16,13 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native ``` -**Minimum React Native version**: SDK supports React Native version 0.63.4 or higher. Compatibility with older versions is not guaranteed out of the box. +**Minimum React Native version**: SDK supports React Native version 0.63.4 or higher on Android. On iOS, the native SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. + +**iOS setup**: your app's `Podfile` must link pods as dynamic frameworks: + +```ruby +use_frameworks! :linkage => :dynamic +``` Versions `1.0.0-rc5` and higher require you to have `compileSdkVersion = 31` in the Android application setup, which implies that you should use Build Tools version 31, Android Gradle Plugin version 7, and Gradle version 7 or higher. To modify the versions, change the values in the `buildscript.ext` block of your application's top-level `build.gradle` file. Datadog recommends using React Native version 0.67 or higher. diff --git a/packages/internal-testing-tools/DatadogInternalTesting.podspec b/packages/internal-testing-tools/DatadogInternalTesting.podspec index 0b60ed282..23989a9f9 100644 --- a/packages/internal-testing-tools/DatadogInternalTesting.podspec +++ b/packages/internal-testing-tools/DatadogInternalTesting.podspec @@ -41,10 +41,20 @@ Pod::Spec.new do |s| products: ['DatadogCore'] ) - # The test spec in ios/Tests does not `@testable import` anything from dd-sdk-ios, but it does - # plainly import DatadogCore and DatadogInternal. Test spec targets are separate from the main - # pod target and so do not receive the SWIFT_INCLUDE_PATHS entry above, which leaves those - # modules unresolvable, so no test spec is declared. + s.test_spec 'Tests' do |test_spec| + test_spec.source_files = 'ios/Tests/*.swift' + + # DatadogCore resolves the same way it does for DatadogSDKReactNative's own test spec: as a + # declared SPM product, its .framework sits at the top-level SYMROOT/CONFIGURATION directory, + # which Xcode searches implicitly for any target with no CONFIGURATION_BUILD_DIR override of + # its own -- true here since test specs don't get the per-pod-target override main pod targets + # do. DatadogInternal needs the explicit help below because it is not a product: it lives one + # level down, in PackageFrameworks/. + test_spec.pod_target_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', + 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' + } + end # This guard prevents installing the dependencies when we run `pod install` in the old architecture. # The `install_modules_dependencies` function is only available from RN 0.71, the new architecture is not diff --git a/packages/internal-testing-tools/ios/Tests/DdInternalTestingTests.swift b/packages/internal-testing-tools/ios/Tests/DdInternalTestingTests.swift index 50e93269c..419028f37 100644 --- a/packages/internal-testing-tools/ios/Tests/DdInternalTestingTests.swift +++ b/packages/internal-testing-tools/ios/Tests/DdInternalTestingTests.swift @@ -4,6 +4,7 @@ * Copyright 2019-2020 Datadog, Inc. */ +import Foundation import XCTest @testable import DatadogInternalTesting @testable import DatadogSDKReactNative diff --git a/packages/react-native-session-replay/README.md b/packages/react-native-session-replay/README.md index 4b019a86e..765f7fa98 100644 --- a/packages/react-native-session-replay/README.md +++ b/packages/react-native-session-replay/README.md @@ -18,6 +18,12 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native-session-replay ``` +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher and your app's `Podfile` to link pods as dynamic frameworks: + +```ruby +use_frameworks! :linkage => :dynamic +``` + ## Enable Session Replay To enable Session Replay, import and call the `enable` method with your configuration. Below is an example setup: diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 8bc1ba851..8317e5a9d 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -38,9 +38,13 @@ Pod::Spec.new do |s| s.dependency "react-native-webview" # DatadogInternal was previously declared explicitly here, but it is an internal target of - # dd-sdk-ios rather than an exported SPM product, so it cannot be requested. It is expected - # to stay importable via the SWIFT_INCLUDE_PATHS entry that React Native's `spm_dependency` - # helper adds to this target. + # dd-sdk-ios rather than an exported SPM product, so it cannot be requested. Making it + # importable takes an extra search path -- see the FRAMEWORK_SEARCH_PATHS note below. Compiling + # is not enough to link it, though: unlike DatadogCore and DatadogSessionReplay, the + # DatadogWebViewTracking product's own autolink metadata does not pull DatadogInternal onto this + # target's link line, so RCTDatadogWebViewTracking.swift's direct references to + # DatadogInternal.CoreRegistry and DatadogCoreProtocol are left unresolved at link time + # ("Undefined symbols ... DatadogInternal.CoreRegistry...") unless we link it explicitly too. spm_dependency(s, url: datadog_ios_spm_url, requirement: { kind: 'exactVersion', version: datadog_ios_version }, @@ -79,7 +83,8 @@ Pod::Spec.new do |s| } xcconfig = { - "HEADER_SEARCH_PATHS" => "$(PODS_ROOT)/react-native-webview/**" + "HEADER_SEARCH_PATHS" => "$(PODS_ROOT)/react-native-webview/**", + "OTHER_LDFLAGS" => "$(inherited) -framework DatadogInternal" } xcconfig.merge!(datadog_spm_xcconfig) diff --git a/packages/react-native-webview/README.md b/packages/react-native-webview/README.md index d4cc30ee4..eec23c73e 100644 --- a/packages/react-native-webview/README.md +++ b/packages/react-native-webview/README.md @@ -20,6 +20,12 @@ Set up the RUM Browser SDK on the web page you want rendered on your mobile Reac Add `react-native-webview` to your application following the [official installation documentation][4]. +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher and your app's `Podfile` to link pods as dynamic frameworks: + +```ruby +use_frameworks! :linkage => :dynamic +``` + ### Instrument your web views Import `WebView` from `@datadog/mobile-react-native-webview` instead of `react-native-webview`: From a79243d2d0657cf19dcaa9b269f33264e335d301 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Wed, 30 Sep 2026 10:31:20 +0200 Subject: [PATCH 05/19] Declare OpenTelemetry SPM products as BenchmarkRunner target dependencies The Frameworks build phase and the project's packageReferences already referenced OpenTelemetryApi/OpenTelemetrySdk, but the BenchmarkRunner PBXNativeTarget itself never listed them in packageProductDependencies -- the field Xcode actually uses to resolve and order the package build. Verified with a full DerivedData wipe. --- benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj index e57958af2..0d0f5fdb7 100644 --- a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj @@ -178,6 +178,10 @@ dependencies = ( ); name = BenchmarkRunner; + packageProductDependencies = ( + 10520E8B306BAEDB00BBFBFF /* OpenTelemetryApi */, + 10520E8D306BAEDB00BBFBFF /* OpenTelemetrySdk */, + ); productName = BenchmarkRunner; productReference = 13B07F961A680F5B00A75B9A /* BenchmarkRunner.app */; productType = "com.apple.product-type.application"; From a78a5d0cc48e15a846f4510fe13688796617f1c9 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Wed, 30 Sep 2026 11:24:36 +0200 Subject: [PATCH 06/19] Correct the tvOS compatibility test's stale claim about DatadogWebViewTracking --- .../core/ios/Tests/TvOSCompatibilityTests.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/core/ios/Tests/TvOSCompatibilityTests.swift b/packages/core/ios/Tests/TvOSCompatibilityTests.swift index 19434248d..16884980a 100644 --- a/packages/core/ios/Tests/TvOSCompatibilityTests.swift +++ b/packages/core/ios/Tests/TvOSCompatibilityTests.swift @@ -7,12 +7,20 @@ import Foundation import XCTest -/// `DatadogWebViewTracking` and the `consumeWebviewEvent` bridge method are iOS-only (the -/// framework isn't published for tvOS, see the podspec's `s.ios.dependency 'DatadogWebViewTracking'`). +/// `DatadogWebViewTracking` and the `consumeWebviewEvent` bridge method are iOS-only in our own +/// code. This used to also be true one level down: the podspec's `s.ios.dependency +/// 'DatadogWebViewTracking'` meant the pod dependency itself was never pulled in on tvOS. Now that +/// the native SDK is resolved through SwiftPM, `spm_dependency` cannot be scoped per platform (see +/// the podspec), so the product is requested unconditionally instead. Confirmed with a standalone +/// scratch SPM package (outside this repo, since it has no tvOS build target of its own) that +/// `DatadogWebViewTracking` 3.16.0 itself still compiles cleanly for tvOS -- but that only checks +/// dd-sdk-ios's own product in isolation, not this whole pod (React-Core, the FRAMEWORK_SEARCH_PATHS +/// and OTHER_LDFLAGS workarounds in the podspec, ...) built and linked for tvOS end to end. /// /// This test statically enforces that every reference to these symbols in `Sources` is wrapped in /// a platform guard (`#if os(iOS)` for Swift, `#if TARGET_OS_IOS` for Objective-C++), as a -/// lightweight substitute for an actual tvOS build. +/// lightweight substitute for an actual tvOS build. It only covers our own code, not whether the +/// dependency resolves for tvOS in the first place. final class TvOSCompatibilityTests: XCTestCase { private static let iOSOnlySymbols = ["DatadogWebViewTracking", "WebViewTracking", "consumeWebviewEvent"] From 09d011eb288ad9f2f9bd09b2d7eee6e43a1eada2 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Fri, 2 Oct 2026 14:50:18 +0200 Subject: [PATCH 07/19] Fix release scripts to read datadog_ios_version from the new SPM podspecs --- bump-native-dd-sdk.sh | 3 ++- update-native-sdk-versions.sh | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bump-native-dd-sdk.sh b/bump-native-dd-sdk.sh index fabaf9600..d7d01d6ab 100755 --- a/bump-native-dd-sdk.sh +++ b/bump-native-dd-sdk.sh @@ -22,9 +22,10 @@ podspec_files=( "packages/core/DatadogSDKReactNative.podspec" "packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec" "packages/react-native-webview/DatadogSDKReactNativeWebView.podspec" + "packages/internal-testing-tools/DatadogInternalTesting.podspec" ) -ios_pattern="('Datadog[^']+', ')[0-9.]+'" +ios_pattern="(datadog_ios_version = ')[0-9.]+'" android_pattern='(com\.datadoghq:dd-sdk-android-[^:"]+):[0-9.]+' if [[ "$sdk" == "ios" ]]; then diff --git a/update-native-sdk-versions.sh b/update-native-sdk-versions.sh index 1c944f708..36b51b409 100755 --- a/update-native-sdk-versions.sh +++ b/update-native-sdk-versions.sh @@ -12,6 +12,7 @@ podspec_files=( "packages/core/DatadogSDKReactNative.podspec" "packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec" "packages/react-native-webview/DatadogSDKReactNativeWebView.podspec" + "packages/internal-testing-tools/DatadogInternalTesting.podspec" ) # Android build.gradle files @@ -83,7 +84,7 @@ else fi # Get iOS version -extract_and_validate_version podspec_files[@] "dependency 'Datadog.*' *, *'" "s/.*dependency *'Datadog.*, *'\([0-9.]*\).*/\1/" "iOS" ios_version +extract_and_validate_version podspec_files[@] "datadog_ios_version *= *'" "s/.*datadog_ios_version *= *'\([0-9.]*\)'.*/\1/" "iOS" ios_version # Get Android version extract_and_validate_version build_gradle_files[@] "com.datadoghq:dd-sdk-android" 's/.*:\([0-9.]*\).*/\1/' "Android" android_version From 08b6ad44292c7f60e693a0ef2ea2fe1a957ddb24 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Fri, 2 Oct 2026 15:31:27 +0200 Subject: [PATCH 08/19] Assign pod_target_xcconfig before install_modules_dependencies in the Datadog podspecs --- benchmarks/ios/Podfile.lock | 4 ++-- example-new-architecture/ios/Podfile.lock | 2 +- packages/core/DatadogSDKReactNative.podspec | 9 +++++++-- .../DatadogInternalTesting.podspec | 9 +++++++-- .../DatadogSDKReactNativeWebView.podspec | 9 +++++++-- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index e4a9de75e..2c9b34420 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -2079,9 +2079,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogSDKReactNative: 2240b4c5d33aaaa998e0860c394b5be4f035ca5f + DatadogSDKReactNative: 625c5d19a50227bb96959703619fed06d13dee89 DatadogSDKReactNativeSessionReplay: 4fe2c3e274def3ecb04435a87630c923673fce0e - DatadogSDKReactNativeWebView: 085a91fb7af197766f2c33620cec662ddf237637 + DatadogSDKReactNativeWebView: 57eefb783b439f9d098bd681a252e1bda7fea8ed DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index a0e8a8786..ae2e41348 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1812,7 +1812,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogSDKReactNative: afaa7219416aa9d26c723604215e4c7b91c49ec5 + DatadogSDKReactNative: dd4f9107346e91abb88dc29d264725e3d5f3eae4 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index c154f32cc..841ad0d47 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -85,13 +85,18 @@ Pod::Spec.new do |s| "OTHER_CPLUSPLUSFLAGS" => "-DRCT_NEW_ARCH_ENABLED=1" }) + # Assign before install_modules_dependencies: the helper reads the spec's current + # pod_target_xcconfig, merges React Native's own header search paths and C++ settings into it + # and assigns the result back, so assigning afterwards would drop everything it added. + s.pod_target_xcconfig = xcconfig + # install_modules_dependencies is only available on RN >= 0.71 if respond_to?(:install_modules_dependencies, true) install_modules_dependencies(s) else Pod::UI.warn "Using Datadog React Native SDK with new architecture on RN < 0.71 is discouraged and not officially supported." end + else + s.pod_target_xcconfig = xcconfig end - - s.pod_target_xcconfig = xcconfig end diff --git a/packages/internal-testing-tools/DatadogInternalTesting.podspec b/packages/internal-testing-tools/DatadogInternalTesting.podspec index 23989a9f9..72adfac4b 100644 --- a/packages/internal-testing-tools/DatadogInternalTesting.podspec +++ b/packages/internal-testing-tools/DatadogInternalTesting.podspec @@ -83,8 +83,13 @@ Pod::Spec.new do |s| "OTHER_CPLUSPLUSFLAGS" => "-DRCT_NEW_ARCH_ENABLED=1" }) + # Assign before install_modules_dependencies: the helper reads the spec's current + # pod_target_xcconfig, merges React Native's own header search paths and C++ settings into it + # and assigns the result back, so assigning afterwards would drop everything it added. + s.pod_target_xcconfig = xcconfig + install_modules_dependencies(s) + else + s.pod_target_xcconfig = xcconfig end - - s.pod_target_xcconfig = xcconfig end diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 8317e5a9d..b6b36e417 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -100,8 +100,13 @@ Pod::Spec.new do |s| "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" }) + # Assign before install_modules_dependencies: the helper reads the spec's current + # pod_target_xcconfig, merges React Native's own header search paths and C++ settings into it + # and assigns the result back, so assigning afterwards would drop everything it added. + s.pod_target_xcconfig = xcconfig + install_modules_dependencies(s) + else + s.pod_target_xcconfig = xcconfig end - - s.pod_target_xcconfig = xcconfig end From bc2310ff5348ffabe5ce6ce8385f52a90d256d0c Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Fri, 9 Oct 2026 11:22:08 +0200 Subject: [PATCH 09/19] Add missing space in the WebView header comment --- .../ios/Sources/DatadogSDKReactNativeWebView.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h b/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h index 1fc7489a6..77751174b 100644 --- a/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h +++ b/packages/react-native-webview/ios/Sources/DatadogSDKReactNativeWebView.h @@ -12,7 +12,7 @@ // react-native-webview is a static library under CocoaPods' default linkage, where its public // headers land flat in Pods/Headers/Public and resolve as a quoted import. When the pod is built // as a dynamic framework instead -- which is mandatory when the native Datadog iOS SDK is resolved -// through Swift Package Manager --the same header is only reachable +// through Swift Package Manager -- the same header is only reachable // as . Support both layouts. #if __has_include() #import From 9c7865cc53f396e6689a5bb28505fd85e2b7dad3 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Wed, 21 Oct 2026 12:48:34 +0200 Subject: [PATCH 10/19] Search the products directory for DatadogInternal in archive builds --- benchmarks/ios/Podfile.lock | 6 +++--- example-new-architecture/ios/Podfile.lock | 2 +- example/ios/Podfile.lock | 6 +++--- packages/core/DatadogSDKReactNative.podspec | 5 ++++- .../internal-testing-tools/DatadogInternalTesting.podspec | 5 ++++- .../DatadogSDKReactNativeSessionReplay.podspec | 5 ++++- .../DatadogSDKReactNativeWebView.podspec | 5 ++++- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 501a2968c..30940f65e 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -2079,9 +2079,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogSDKReactNative: e82c62e41c7ee681ea28c3d68cebb179fc97cef1 - DatadogSDKReactNativeSessionReplay: 40e79a36e92221b9e28ae17928fe2722bd923f34 - DatadogSDKReactNativeWebView: da965f998511f4aad38616de6edacd78001b9897 + DatadogSDKReactNative: b7c70a7ab111b2a99e8b7aa9c49de41e398d1af6 + DatadogSDKReactNativeSessionReplay: 3370297e46f7183afc1e384b73d328e1331d21f1 + DatadogSDKReactNativeWebView: 0af069739f9427d9511b3f14c5836111680f888d DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 16bde8228..50f417a9c 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1812,7 +1812,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogSDKReactNative: 0202da1da86bfe88f94325e06fc94766453df392 + DatadogSDKReactNative: 86d591357c66b9bd5d0714702cae93a21bb1664d DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index b63182886..07521b433 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1905,9 +1905,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogSDKReactNative: c8d763826fba47968d28aa7947022b9e00091ac4 - DatadogSDKReactNativeSessionReplay: 719afc386d385473924c45ea1b72a439782fe400 - DatadogSDKReactNativeWebView: ddcef966890c5a0751b222237a8599fa406040ac + DatadogSDKReactNative: 2764bf00d35df024f1c87fdb9ff5a135676b41b5 + DatadogSDKReactNativeSessionReplay: 66ad1c183f6e6275bb81abdc07b1e49d6412617e + DatadogSDKReactNativeWebView: 3349a0842b697603ddf8d13ded95c817ce567a6d DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index edad3a0d8..f8434ebd5 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -73,8 +73,11 @@ Pod::Spec.new do |s| # //DatadogSDKReactNative, one level below where SwiftPM actually # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + # + # Archive builds lay this out differently: PackageFrameworks/ stays empty and the package + # frameworks are linked straight into the products directory itself, so search that too. datadog_spm_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks" "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"' } xcconfig = datadog_spm_xcconfig.dup diff --git a/packages/internal-testing-tools/DatadogInternalTesting.podspec b/packages/internal-testing-tools/DatadogInternalTesting.podspec index c2af8ddfa..44f60d035 100644 --- a/packages/internal-testing-tools/DatadogInternalTesting.podspec +++ b/packages/internal-testing-tools/DatadogInternalTesting.podspec @@ -71,8 +71,11 @@ Pod::Spec.new do |s| # //DatadogSDKReactNative, one level below where SwiftPM actually # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + # + # Archive builds lay this out differently: PackageFrameworks/ stays empty and the package + # frameworks are linked straight into the products directory itself, so search that too. datadog_spm_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks" "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"' } xcconfig = datadog_spm_xcconfig.dup diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 046c32e2e..2ad985d57 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -95,8 +95,11 @@ Pod::Spec.new do |s| # //DatadogSDKReactNative, one level below where SwiftPM actually # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + # + # Archive builds lay this out differently: PackageFrameworks/ stays empty and the package + # frameworks are linked straight into the products directory itself, so search that too. datadog_spm_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks" "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"' } xcconfig = { diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index dd823ab53..4ec4cb4ae 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -78,8 +78,11 @@ Pod::Spec.new do |s| # //DatadogSDKReactNative, one level below where SwiftPM actually # writes PackageFrameworks/. Spelling it as SYMROOT/CONFIGURATION+EFFECTIVE_PLATFORM_NAME # matches what `spm_dependency` itself uses for SWIFT_INCLUDE_PATHS. + # + # Archive builds lay this out differently: PackageFrameworks/ stays empty and the package + # frameworks are linked straight into the products directory itself, so search that too. datadog_spm_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"' + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks" "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"' } xcconfig = { From 63d59d557b7e8c18a9f6d3e642098512bb9a48b3 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Wed, 21 Oct 2026 15:17:43 +0200 Subject: [PATCH 11/19] Embed the Datadog Swift package frameworks that Xcode builds dynamically --- packages/core/DatadogSDKReactNative.podspec | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index f8434ebd5..a9de5fbfd 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -17,6 +17,68 @@ if !respond_to?(:spm_dependency, true) "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." end +# Xcode builds some of the package's frameworks as dynamic frameworks: DatadogInternal, a target +# shared by every product, and a `__PackageProduct` framework for any product that +# more than one pod requests (e.g. DatadogWebViewTracking). The pods link them, but CocoaPods' +# "[CP] Embed Pods Frameworks" phase only embeds pod frameworks, and `spm_dependency` does not +# embed them either, so a Release or archived app crashes at launch with dyld "Library not +# loaded". Debug builds hide it because Xcode adds an rpath to the build folder. +# This extends React Native's SPM post-install step, which every React Native Podfile already +# runs through `react_native_post_install`, so the app embeds them without any Podfile change. +unless defined?(SPM) && SPM.respond_to?(:apply_on_post_install) + raise "Datadog: could not find React Native's Swift Package Manager integration " \ + "(SPM.apply_on_post_install), which is needed to embed the native iOS SDK frameworks." +end + +unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) + SPM.singleton_class.prepend(Module.new do + def datadog_embeds_spm_frameworks? + true + end + + def apply_on_post_install(installer) + super + embed = <<~'SH' + # Embeds the Datadog Swift package frameworks that Xcode builds dynamically. Looks where Xcode + # writes them: the products dir, PackageFrameworks, or UninstalledProducts when archiving. + embed_datadog_spm_frameworks() + { + local dir framework found + for dir in "${PODS_CONFIGURATION_BUILD_DIR}" "${PODS_CONFIGURATION_BUILD_DIR}/PackageFrameworks" "${OBJROOT}/UninstalledProducts/${PLATFORM_NAME}"; do + found=false + for framework in "${dir}"/$1.framework; do + [ -d "${framework}" ] || continue + found=true + if file -b "${framework}/$(basename "${framework}" .framework)" | grep -q "dynamically linked"; then + install_framework "${framework}" + fi + done + [ "${found}" = true ] && return 0 + done + # Nothing to embed (e.g. every Datadog product is linked statically) is fine; returning the + # last test's status instead would abort the script, which runs with `set -e`. + return 0 + } + embed_datadog_spm_frameworks "DatadogInternal" + embed_datadog_spm_frameworks "Datadog*_PackageProduct" + SH + anchor = /^if \[ "\$\{COCOAPODS_PARALLEL_CODE_SIGN\}" == "true" \]; then$/ + installer.aggregate_targets.each do |target| + next unless target.pod_targets.any? { |pod| pod.name == 'DatadogSDKReactNative' } + script_path = target.embed_frameworks_script_path + next unless File.exist?(script_path) + script = File.read(script_path) + next if script.include?('embed_datadog_spm_frameworks()') + unless script.match?(anchor) + raise "Datadog: could not add the native iOS SDK frameworks to #{script_path}, " \ + "so the app would crash at launch in Release builds." + end + File.write(script_path, script.sub(anchor) { "#{embed}#{$&}" }) + end + end + end) +end + Pod::Spec.new do |s| s.name = "DatadogSDKReactNative" s.version = package["version"] From fd6568e5ee13af98e3745489b1b235b2f47b6d67 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Wed, 21 Oct 2026 16:06:18 +0200 Subject: [PATCH 12/19] Migrate PodfileForSRTests to the Swift Package Manager setup --- example/ios/PodfileForSRTests | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/example/ios/PodfileForSRTests b/example/ios/PodfileForSRTests index ea0508561..5c1c9b997 100644 --- a/example/ios/PodfileForSRTests +++ b/example/ios/PodfileForSRTests @@ -8,11 +8,9 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -linkage = ENV['USE_FRAMEWORKS'] -if linkage != nil - Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green - use_frameworks! :linkage => linkage.to_sym -end +# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires +# pods to be linked as dynamic frameworks. +use_frameworks! :linkage => :dynamic use_modular_headers! @@ -47,10 +45,9 @@ target 'ddSdkReactnativeExample' do config[:reactNativePath], :mac_catalyst_enabled => false ) - # Enable `DD_SDK_COMPILED_FOR_TESTING` condition when compiling `DatadogSDK` dependency: - datadog_sdk_target = installer.pods_project.targets.detect {|t| ["DatadogCore", "DatadogRUM", "DatadogLogs", "DatadogInternal", "DatadogTrace", "DatadogCrashReporting"].include?(t.name) } - datadog_sdk_target.build_configurations.each do |config| - config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = '$(inherited) DD_SDK_COMPILED_FOR_TESTING' - end + # `DD_SDK_COMPILED_FOR_TESTING` is no longer injected. There is no pod target to set it on now + # that the SDK comes from SPM, and the native tests never needed it: none of them touch the + # three declarations it guards (`Datadog.flushAndDeinitialize` and its ObjC counterpart, and + # `DatadogContextProvider.replace(context:)`). end end From a5a298cfd409ba27ae33b653375df898598da1ab Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 10:05:55 +0100 Subject: [PATCH 13/19] Support static linking after SPM migration --- benchmarks/ios/Podfile | 4 +- benchmarks/ios/Podfile.lock | 4 +- example-new-architecture/ios/Podfile | 8 +- example-new-architecture/ios/Podfile.lock | 2 +- .../project.pbxproj | 8 +- example/ios/Podfile | 8 +- example/ios/Podfile.lock | 78 +++++++++---------- example/ios/PodfileForSRTests | 8 +- packages/core/DatadogSDKReactNative.podspec | 45 ++++++++++- packages/core/README.md | 6 -- .../DatadogInternalTesting.podspec | 22 ++++-- ...DatadogSDKReactNativeSessionReplay.podspec | 41 +++++++--- .../react-native-session-replay/README.md | 6 +- .../DatadogSDKReactNativeWebView.podspec | 39 +++++++--- packages/react-native-webview/README.md | 6 +- 15 files changed, 178 insertions(+), 107 deletions(-) diff --git a/benchmarks/ios/Podfile b/benchmarks/ios/Podfile index 829d1b642..57c582748 100644 --- a/benchmarks/ios/Podfile +++ b/benchmarks/ios/Podfile @@ -10,8 +10,8 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires -# pods to be linked as dynamic frameworks. +# The Datadog podspecs work with any pod linkage, but BenchmarkRunner, which links the OpenTelemetry +# SPM products directly, has only been set up and verified with dynamic frameworks. use_frameworks! :linkage => :dynamic target 'BenchmarkRunner' do diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 30940f65e..2f54dff04 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -2080,7 +2080,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DatadogSDKReactNative: b7c70a7ab111b2a99e8b7aa9c49de41e398d1af6 - DatadogSDKReactNativeSessionReplay: 3370297e46f7183afc1e384b73d328e1331d21f1 + DatadogSDKReactNativeSessionReplay: a5bdec54f72562604398235db389dea5bb6f324d DatadogSDKReactNativeWebView: 0af069739f9427d9511b3f14c5836111680f888d DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 @@ -2156,6 +2156,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 6eb60fc2c0eef63e7d2ef4a56e0a3353534143a2 -PODFILE CHECKSUM: 26bbffd54a9dc71f8787dc1ed59dcb5c1fc2e42e +PODFILE CHECKSUM: 5c25964fabe795dbb68c83429f039f0c339e4a17 COCOAPODS: 1.16.2 diff --git a/example-new-architecture/ios/Podfile b/example-new-architecture/ios/Podfile index 48dbc648d..2adb5a702 100644 --- a/example-new-architecture/ios/Podfile +++ b/example-new-architecture/ios/Podfile @@ -10,12 +10,8 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires -# pods to be linked as dynamic frameworks: dd-sdk-ios declares its SPM products without an explicit -# `type:`, so SwiftPM builds them as static libraries, and combining those with CocoaPods' default -# static linkage produces duplicate symbols at link time. Dynamic frameworks are the only -# combination that works -- see https://github.com/facebook/react-native/pull/44627 for the full -# matrix. +# The Datadog podspecs work with any pod linkage. This app links pods as dynamic frameworks so that +# CI covers that setup, while example/ covers React Native's default static linkage. use_frameworks! :linkage => :dynamic target 'DdSdkReactNativeExample' do diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 50f417a9c..479fb798f 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1878,6 +1878,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 1259c7a8cbaccf7b4c3ddf8ee36ca11be9dee407 -PODFILE CHECKSUM: 65bae30d106f4e0fed15150fb60695cc8cddcf1b +PODFILE CHECKSUM: 593214c784746ea2fbcfc84767829e60cf27f722 COCOAPODS: 1.16.2 diff --git a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj index 30a7df2d0..75d805ada 100644 --- a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj @@ -8,10 +8,10 @@ /* Begin PBXBuildFile section */ 04ACF1F72ED5D0B600602CDD /* datadog-configuration.json in Resources */ = {isa = PBXBuildFile; fileRef = 04ACF1F62ED5D0B600602CDD /* datadog-configuration.json */; }; + FB483A2F5418999CE4813EF0 /* libPods-ddSdkReactnativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE41272558F8A75D64B58C34 /* libPods-ddSdkReactnativeExample.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 2789DEF2415D78452154A27B /* Pods_ddSdkReactnativeExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF25158637ACC88517B07D7D /* Pods_ddSdkReactnativeExample.framework */; }; 7115D38EB0DCB0BDB39D62A2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A54EC6889135AAF4EFAD7EF0 /* PrivacyInfo.xcprivacy */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ @@ -30,7 +30,7 @@ 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ddSdkReactnativeExample/LaunchScreen.storyboard; sourceTree = ""; }; A54EC6889135AAF4EFAD7EF0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = ddSdkReactnativeExample/PrivacyInfo.xcprivacy; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; - EF25158637ACC88517B07D7D /* Pods_ddSdkReactnativeExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ddSdkReactnativeExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CE41272558F8A75D64B58C34 /* libPods-ddSdkReactnativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ddSdkReactnativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -38,7 +38,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2789DEF2415D78452154A27B /* Pods_ddSdkReactnativeExample.framework in Frameworks */, + FB483A2F5418999CE4813EF0 /* libPods-ddSdkReactnativeExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -64,7 +64,7 @@ children = ( 04ACF1F52ED5D05F00602CDD /* datadog-configuration.json */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - EF25158637ACC88517B07D7D /* Pods_ddSdkReactnativeExample.framework */, + CE41272558F8A75D64B58C34 /* libPods-ddSdkReactnativeExample.a */, ); name = Frameworks; sourceTree = ""; diff --git a/example/ios/Podfile b/example/ios/Podfile index 20104baa9..b61bc1595 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -10,9 +10,11 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires -# pods to be linked as dynamic frameworks. -use_frameworks! :linkage => :dynamic +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end target 'ddSdkReactnativeExample' do pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec', :testspecs => ['Tests'] diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 07521b433..5a6053dba 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -7,7 +7,6 @@ PODS: - DatadogSDKReactNativeSessionReplay (3.11.0): - DatadogSDKReactNative - React-Core - - React-RCTText - DatadogSDKReactNativeSessionReplay/Tests (3.11.0): - DatadogSDKReactNative - React-Core @@ -15,7 +14,6 @@ PODS: - DatadogSDKReactNativeWebView (3.11.0): - DatadogSDKReactNative - React-Core - - react-native-webview - DatadogSDKReactNativeWebView/Tests (3.11.0): - DatadogSDKReactNative - React-Core @@ -1906,8 +1904,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 DatadogSDKReactNative: 2764bf00d35df024f1c87fdb9ff5a135676b41b5 - DatadogSDKReactNativeSessionReplay: 66ad1c183f6e6275bb81abdc07b1e49d6412617e - DatadogSDKReactNativeWebView: 3349a0842b697603ddf8d13ded95c817ce567a6d + DatadogSDKReactNativeSessionReplay: ca4fb29224cb139ded3b8fba1595c913a869f4f9 + DatadogSDKReactNativeWebView: 569eba919326fa2139d4702950f841d7375197ab DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -1924,63 +1922,63 @@ SPEC CHECKSUMS: React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d - React-debug: f1956672cf545729afb71ef838a9789c2a9088f5 - React-defaultsnativemodule: f5e33b59be56f54f0e6c1991db55ddbc6de39181 - React-domnativemodule: 73f26e6bc782ca358497fbed427035ea01fcc297 - React-Fabric: 80d7bc9d0ea7981a188b1ea6a67df072af164489 - React-FabricComponents: 1887b9027e7da5679f099b999dc56b44dbc7628c - React-FabricImage: 27996e41c769616bb68f011362bf69c472a6b2f7 - React-featureflags: dc9c91fcd6a75cc95bd7fec184d0be8ad0f26db5 - React-featureflagsnativemodule: 1a0c73dca4158da552f074d469066d317c6a0570 - React-graphics: fa15bab1a7d44a57eeb54e3185117729b141ed4b + React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 + React-defaultsnativemodule: a965cb39fb0a79276ab611793d39f52e59a9a851 + React-domnativemodule: d647f94e503c62c44f54291334b1aa22a30fa08b + React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b + React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb + React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f + React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c + React-featureflagsnativemodule: 95a02d895475de8ace78fedd76143866838bb720 + React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 - React-idlecallbacksnativemodule: 1e13269b40e163fe92cb1774a24bbe607beb0242 - React-ImageManager: 1a6f5a858f86bc93bf210a88ec5575ff22b69aaa - React-jserrorhandler: ea750869c2aa5497b3d9322afe02eb7f756b9696 + React-idlecallbacksnativemodule: 0c1ae840cc5587197cd926a3cb76828ad059d116 + React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 + React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 React-jsi: 95f7676103137861b79b0f319467627bcfa629ee React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 - React-jsinspector: 74c73f2b385b6a7979eddeba055961e9acc3cc42 - React-jsitracing: 182a6d4af2273f847daa8a3f841fd3ff8212d3f8 + React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 + React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 - React-Mapbuffer: 129fa9634f42d88a0c3761d2829db85175b985ee - React-microtasksnativemodule: 5aeec323cb452dba293815d82bf08d7076e295d0 + React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc + React-microtasksnativemodule: 8732b71aa66045da4bb341ddee1bb539f71e5f38 react-native-crash-tester: 3ffaa64141427ca362079cb53559fe9a532487ae react-native-safe-area-context: 04803a01f39f31cc6605a5531280b477b48f8a88 - react-native-webview: f0a8c96e34ec192f88eaf48c00fbefe415dd6ed2 - React-nativeconfig: 415626a63057638759bcc75e0a96e2e07771a479 - React-NativeModulesApple: bffc60f55895c2723b1e5472fa40567fe3df4923 + react-native-webview: 1e12de2fad74c17b4f8b1b53ebd1e3baa0148d71 + React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 + React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d - React-performancetimeline: 128acbcdacb8a5ee73aa4a2bf28db4e8627f111b + React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 React-RCTAppDelegate: 6c0377d9c4058773ea7073bb34bb9ebd6ddf5a84 React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 - React-RCTFabric: dba2f65bcfcede5e0b2ed7df48247cdb16f21f20 + React-RCTFabric: 7eb6dd2c8fda98cb860a572e3f4e4eb60d62c89e React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec - React-rendererconsistency: b89c074e22ca2b9eaa8013e1310c69db85364893 - React-rendererdebug: 383e6c8c8d9ee45e88e5d461ad1c6a4a7a0f9282 - React-rncore: 2a6efd857e10a3b299f8a7fe912fd332aa7e515a - React-RuntimeApple: f07537b48b715b6dd7a8d6145f4f6684d78984cc - React-RuntimeCore: cce02c6ade4d7e8d1854d275c9b367b913ed1fb3 + React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 + React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 + React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 + React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 + React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: ec8b23b1a86022e9831ab775d1634fcbc7dfc500 - React-runtimescheduler: 222c73a654f32e3544a1384b2ced809bd51df2af - React-timing: a693c531e5627dcc200fc7286cbbebf73d73469d - React-utils: 52cb73e127a39fc2d9f02f503b2a7b3b0abd23dd - ReactCodegen: 31fcff227d0035956575be0c013a2edcc687a53c - ReactCommon: 78c49c7cf7df16983ebc3c646b4f47398437f2ec + React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 + React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe + React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 + React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e + ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c + ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd ReactNativeNavigation: 50c1eef68b821e7265eff3a391d27ed18fdce459 RNCAsyncStorage: 23e56519cc41d3bade3c8d4479f7760cb1c11996 - RNGestureHandler: 8d00cc737b38b7b67be2d9438242850182291fb4 - RNScreens: da5922094c3a1d9ce10625888b185798523b58ed + RNGestureHandler: 950dfa674dbf481460ca389c65b9036ac4ab8ada + RNScreens: 606ab1cf68162f7ba0d049a31f2a84089a6fffb4 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: 1259c7a8cbaccf7b4c3ddf8ee36ca11be9dee407 + Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a -PODFILE CHECKSUM: 04d9739a3e9c4afbe3a81d5f7ddf602c423f0e9a +PODFILE CHECKSUM: f9df4e0afa2f5576617ec8ed84f5dfc9e5bf2ced COCOAPODS: 1.16.2 diff --git a/example/ios/PodfileForSRTests b/example/ios/PodfileForSRTests index 5c1c9b997..1044d4fbc 100644 --- a/example/ios/PodfileForSRTests +++ b/example/ios/PodfileForSRTests @@ -8,9 +8,11 @@ require Pod::Executable.execute_command('node', ['-p', platform :ios, min_ios_version_supported prepare_react_native_project! -# The Datadog podspecs resolve the native iOS SDK through Swift Package Manager, which requires -# pods to be linked as dynamic frameworks. -use_frameworks! :linkage => :dynamic +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end use_modular_headers! diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index a9de5fbfd..bbc7f50ce 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -10,8 +10,8 @@ datadog_ios_version = '3.16.1' datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' # The native iOS SDK is resolved through Swift Package Manager, using React Native's -# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links -# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +# `spm_dependency` podspec helper. This requires React Native >= 0.75. Pods can be linked statically +# or as frameworks: see the post-install step below for what each linkage needs. if !respond_to?(:spm_dependency, true) raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." @@ -36,7 +36,48 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) true end + # When pods are linked statically, Xcode merges the object files of every package product a pod + # requests, DatadogInternal included, into that pod's static archive. With more than one Datadog + # pod each archive carries its own copy, and the app fails to link with duplicate symbols. So + # the core pod, which every other Datadog pod depends on and which is therefore built first, + # requests all of their products, and the others keep only the package reference and the + # include path they compile against. + def datadog_request_static_products_from_core(installer) + core = installer.pod_targets.find { |pod| pod.name == 'DatadogSDKReactNative' } + return if core.nil? || core.build_as_dynamic? + + dependencies_by_pod = instance_variable_get(:@dependencies_by_pod) + if dependencies_by_pod.nil? + raise "Datadog: could not read React Native's Swift Package Manager dependencies, which is " \ + "needed to link the native iOS SDK statically." + end + core_dependencies = dependencies_by_pod['DatadogSDKReactNative'] || [] + datadog_urls = core_dependencies.map { |dependency| dependency[:url] } + dependencies_by_pod.each do |pod_name, dependencies| + next if pod_name == 'DatadogSDKReactNative' + dependencies.each do |dependency| + next unless datadog_urls.include?(dependency[:url]) + core_dependency = core_dependencies.find { |candidate| candidate[:url] == dependency[:url] } + core_dependency[:products] |= dependency[:products] + dependency[:products] = [] + end + end + end + + # CocoaPods numbers the Pods project's UUIDs from a counter without checking for collisions, + # which only holds while it creates every object itself. By the time post-install hooks run it + # has made the UUIDs deterministic, and once the batch it had left runs out the counter + # restarts, so the package objects added below can reuse a taken UUID -- the project root's + # first -- and Xcode then reports the Pods project as damaged. Whether that happens depends on + # how many objects the project has. Queue collision-checked UUIDs, generated by Xcodeproj's own + # implementation, so the objects created from here on never take one that is already in use. + def datadog_reserve_unique_uuids(project) + Xcodeproj::Project.instance_method(:generate_available_uuid_list).bind(project).call(100) + end + def apply_on_post_install(installer) + datadog_reserve_unique_uuids(installer.pods_project) + datadog_request_static_products_from_core(installer) super embed = <<~'SH' # Embeds the Datadog Swift package frameworks that Xcode builds dynamically. Looks where Xcode diff --git a/packages/core/README.md b/packages/core/README.md index ecd93a410..4bd06bd89 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -18,12 +18,6 @@ yarn add @datadog/mobile-react-native **Minimum React Native version**: SDK supports React Native version 0.63.4 or higher on Android. On iOS, the native SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. -**iOS setup**: your app's `Podfile` must link pods as dynamic frameworks: - -```ruby -use_frameworks! :linkage => :dynamic -``` - Versions `1.0.0-rc5` and higher require you to have `compileSdkVersion = 31` in the Android application setup, which implies that you should use Build Tools version 31, Android Gradle Plugin version 7, and Gradle version 7 or higher. To modify the versions, change the values in the `buildscript.ext` block of your application's top-level `build.gradle` file. Datadog recommends using React Native version 0.67 or higher. ### Specify application details in UI diff --git a/packages/internal-testing-tools/DatadogInternalTesting.podspec b/packages/internal-testing-tools/DatadogInternalTesting.podspec index 44f60d035..6b4d10781 100644 --- a/packages/internal-testing-tools/DatadogInternalTesting.podspec +++ b/packages/internal-testing-tools/DatadogInternalTesting.podspec @@ -7,13 +7,21 @@ datadog_ios_version = '3.16.1' datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' # The native iOS SDK is resolved through Swift Package Manager, using React Native's -# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links -# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +# `spm_dependency` podspec helper. This requires React Native >= 0.75. Pods can be linked statically +# or as frameworks (see DatadogSDKReactNative.podspec for how static linkage is handled). if !respond_to?(:spm_dependency, true) raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." end +# Only with dynamic frameworks does Xcode build DatadogInternal as a framework of its own. When pods +# are linked statically its code is in DatadogSDKReactNative's archive instead, which requests +# every Datadog product then (see DatadogSDKReactNative.podspec). The Podfile is read as well as +# USE_FRAMEWORKS because apps can call `use_frameworks!` without setting the env var. +podfile = Pod::Config.instance.podfile rescue nil +uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' || + (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.dynamic_framework? }) + Pod::Spec.new do |s| s.name = "DatadogInternalTesting" s.version = package["version"] @@ -50,10 +58,12 @@ Pod::Spec.new do |s| # its own -- true here since test specs don't get the per-pod-target override main pod targets # do. DatadogInternal needs the explicit help below because it is not a product: it lives one # level down, in PackageFrameworks/. - test_spec.pod_target_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', - 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' - } + if uses_dynamic_frameworks + test_spec.pod_target_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', + 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' + } + end end # This guard prevents installing the dependencies when we run `pod install` in the old architecture. diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 2ad985d57..beb15dd85 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -7,13 +7,24 @@ datadog_ios_version = '3.16.1' datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' # The native iOS SDK is resolved through Swift Package Manager, using React Native's -# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links -# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +# `spm_dependency` podspec helper. This requires React Native >= 0.75. Pods can be linked statically +# or as frameworks (see DatadogSDKReactNative.podspec for how static linkage is handled). if !respond_to?(:spm_dependency, true) raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." end +# How the app links pods (`use_frameworks!`). The Podfile is read as well as USE_FRAMEWORKS because +# apps can call `use_frameworks!` without setting the env var. +podfile = Pod::Config.instance.podfile rescue nil +uses_frameworks = !ENV['USE_FRAMEWORKS'].nil? || + (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.framework? }) +# Only with dynamic frameworks does Xcode build DatadogInternal as a framework of its own. When pods +# are linked statically its code is in DatadogSDKReactNative's archive instead, which requests +# every Datadog product then (see DatadogSDKReactNative.podspec). +uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' || + (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.dynamic_framework? }) + Pod::Spec.new do |s| s.name = "DatadogSDKReactNativeSessionReplay" s.version = package["version"] @@ -42,10 +53,13 @@ Pod::Spec.new do |s| s.dependency "React-Core" # RCTTextExtractor.mm references RCTTextView and the RCTText shadow view classes directly, so - # this pod has always had a link-time dependency on React-RCTText. It was only declared on the - # test spec, which went unnoticed while pods were linked statically and undefined symbols were - # deferred to the app link. - s.dependency "React-RCTText" + # this pod has a link-time dependency on React-RCTText. A framework has to resolve it when it is + # linked, so declare it then. Static libraries defer it to the app link, and declaring it there + # fails `pod install`: React-RCTText does not define modules, which a Swift static library's + # dependencies must. + if uses_frameworks + s.dependency "React-RCTText" + end s.dependency 'DatadogSDKReactNative' # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so it @@ -57,19 +71,22 @@ Pod::Spec.new do |s| products: ['DatadogSessionReplay'] ) - # React-RCTText is not repeated here: it is declared on the main spec above, which the test spec - # inherits. + # The tests reference the React-RCTText classes directly. The main spec only declares it when + # pods are built as frameworks, so declare it here too. s.test_spec 'Tests' do |test_spec| + test_spec.dependency "React-RCTText" test_spec.source_files = 'ios/Tests/*.swift' test_spec.platforms = { :ios => "13.4", :tvos => "13.4" } # The tests reference DatadogInternal protocol descriptors (Storage, Telemetry) directly. Unlike # the SPM products, DatadogInternal is not on this target's link line, so name it explicitly -- # and point the linker at PackageFrameworks, where SwiftPM writes non-product targets. - test_spec.pod_target_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', - 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' - } + if uses_dynamic_frameworks + test_spec.pod_target_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', + 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' + } + end end header_paths = %W[ diff --git a/packages/react-native-session-replay/README.md b/packages/react-native-session-replay/README.md index 765f7fa98..3a2aca155 100644 --- a/packages/react-native-session-replay/README.md +++ b/packages/react-native-session-replay/README.md @@ -18,11 +18,7 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native-session-replay ``` -**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher and your app's `Podfile` to link pods as dynamic frameworks: - -```ruby -use_frameworks! :linkage => :dynamic -``` +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. ## Enable Session Replay diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 4ec4cb4ae..dacd8280e 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -7,13 +7,24 @@ datadog_ios_version = '3.16.1' datadog_ios_spm_url = 'https://github.com/DataDog/dd-sdk-ios.git' # The native iOS SDK is resolved through Swift Package Manager, using React Native's -# `spm_dependency` podspec helper. This requires React Native >= 0.75 and an app that links -# pods as dynamic frameworks (`use_frameworks! :linkage => :dynamic`). +# `spm_dependency` podspec helper. This requires React Native >= 0.75. Pods can be linked statically +# or as frameworks (see DatadogSDKReactNative.podspec for how static linkage is handled). if !respond_to?(:spm_dependency, true) raise "Datadog: the native iOS SDK is resolved through Swift Package Manager, which requires " \ "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." end +# How the app links pods (`use_frameworks!`). The Podfile is read as well as USE_FRAMEWORKS because +# apps can call `use_frameworks!` without setting the env var. +podfile = Pod::Config.instance.podfile rescue nil +uses_frameworks = !ENV['USE_FRAMEWORKS'].nil? || + (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.framework? }) +# Only with dynamic frameworks does Xcode build DatadogInternal as a framework of its own. When pods +# are linked statically its code is in DatadogSDKReactNative's archive instead, which requests +# every Datadog product then (see DatadogSDKReactNative.podspec). +uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' || + (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.dynamic_framework? }) + Pod::Spec.new do |s| s.name = "DatadogSDKReactNativeWebView" s.version = package["version"] @@ -34,8 +45,12 @@ Pod::Spec.new do |s| # Our headers subclass RNCWebViewImpl / RNCWebViewManager. Under framework linkage those headers # are only reachable as , which requires react-native-webview to be a # declared dependency so that CocoaPods puts its build directory on this target's - # FRAMEWORK_SEARCH_PATHS. - s.dependency "react-native-webview" + # FRAMEWORK_SEARCH_PATHS. Static libraries find them through HEADER_SEARCH_PATHS below instead, + # and declaring it there fails `pod install`: react-native-webview does not define modules, which + # a Swift static library's dependencies must. + if uses_frameworks + s.dependency "react-native-webview" + end # DatadogInternal was previously declared explicitly here, but it is an internal target of # dd-sdk-ios rather than an exported SPM product, so it cannot be requested. Making it @@ -60,10 +75,12 @@ Pod::Spec.new do |s| # The tests reach DatadogInternal directly, which is not on this target's link line because it # is a target of dd-sdk-ios rather than one of the SPM products this pod requests. - test_spec.pod_target_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', - 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' - } + if uses_dynamic_frameworks + test_spec.pod_target_xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/PackageFrameworks"', + 'OTHER_LDFLAGS' => '$(inherited) -framework DatadogInternal' + } + end end # DatadogInternal is an internal target of dd-sdk-ios rather than an exported product, so @@ -86,9 +103,11 @@ Pod::Spec.new do |s| } xcconfig = { - "HEADER_SEARCH_PATHS" => "$(PODS_ROOT)/react-native-webview/**", - "OTHER_LDFLAGS" => "$(inherited) -framework DatadogInternal" + "HEADER_SEARCH_PATHS" => "$(PODS_ROOT)/react-native-webview/**" } + if uses_dynamic_frameworks + xcconfig["OTHER_LDFLAGS"] = "$(inherited) -framework DatadogInternal" + end xcconfig.merge!(datadog_spm_xcconfig) diff --git a/packages/react-native-webview/README.md b/packages/react-native-webview/README.md index eec23c73e..13af9d9d4 100644 --- a/packages/react-native-webview/README.md +++ b/packages/react-native-webview/README.md @@ -20,11 +20,7 @@ Set up the RUM Browser SDK on the web page you want rendered on your mobile Reac Add `react-native-webview` to your application following the [official installation documentation][4]. -**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher and your app's `Podfile` to link pods as dynamic frameworks: - -```ruby -use_frameworks! :linkage => :dynamic -``` +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. ### Instrument your web views From c2b7045f75243524fafd1e1d682e376b77d17cd4 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 12:10:21 +0100 Subject: [PATCH 14/19] Build the statically linked example with Xcode 26 --- .gitlab-ci.yml | 9 +++++++++ packages/core/README.md | 2 +- packages/react-native-session-replay/README.md | 2 +- packages/react-native-webview/README.md | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 576b454cb..e11558b93 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,6 +45,12 @@ stages: - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_EMULATOR_IMAGE" - yes | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --licenses || true - echo "no" | ~/android_sdk/cmdline-tools/latest/bin/avdmanager --verbose create avd --force --name "$EMULATOR_NAME" --package "$ANDROID_EMULATOR_IMAGE" + # example/ links pods statically, which needs Xcode 26: with older versions the native SDK's Swift + # packages fail to link with duplicate symbols. Apps uploaded to the App Store must be built with + # Xcode 26 since April 2026, and example-new-architecture/ keeps covering Xcode 16 with dynamic frameworks. + select-xcode-26: + - export DEVELOPER_DIR="$(ls -d /Applications/Xcode-26*.app | sort -V | tail -1)/Contents/Developer" + - xcodebuild -version # TESTS @@ -104,6 +110,7 @@ test:native-ios: - if: '$BUILD_BENCHMARK != "true"' timeout: 1h script: + - !reference [.snippets, select-xcode-26] - yarn - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNative test -destination "$IOS_SIMULATOR_DESTINATION" -derivedDataPath "$IOS_DERIVED_DATA_PATH" | xcbeautify @@ -115,6 +122,7 @@ test:native-ios-sr: - if: '$BUILD_BENCHMARK != "true"' timeout: 1h script: + - !reference [.snippets, select-xcode-26] - yarn - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNativeSessionReplay test -destination "$IOS_SIMULATOR_DESTINATION" -derivedDataPath "$IOS_DERIVED_DATA_PATH" | xcbeautify @@ -163,6 +171,7 @@ build-examples:ios: - if: '$BUILD_BENCHMARK != "true"' timeout: 1h script: + - !reference [.snippets, select-xcode-26] - yarn - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DdSdkReactNativeExample -configuration Debug -sdk iphonesimulator -destination "$IOS_SIMULATOR_DESTINATION" -derivedDataPath "$IOS_DERIVED_DATA_PATH" build | xcbeautify diff --git a/packages/core/README.md b/packages/core/README.md index 4bd06bd89..495a93468 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -16,7 +16,7 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native ``` -**Minimum React Native version**: SDK supports React Native version 0.63.4 or higher on Android. On iOS, the native SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. +**Minimum React Native version**: SDK supports React Native version 0.63.4 or higher on Android. On iOS, the native SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Pods can be linked statically (React Native's default) with Xcode 26 or later; with older Xcode versions, link them as dynamic frameworks (`use_frameworks! :linkage => :dynamic` in your `Podfile`). Versions `1.0.0-rc5` and higher require you to have `compileSdkVersion = 31` in the Android application setup, which implies that you should use Build Tools version 31, Android Gradle Plugin version 7, and Gradle version 7 or higher. To modify the versions, change the values in the `buildscript.ext` block of your application's top-level `build.gradle` file. Datadog recommends using React Native version 0.67 or higher. diff --git a/packages/react-native-session-replay/README.md b/packages/react-native-session-replay/README.md index 3a2aca155..c07a7aea6 100644 --- a/packages/react-native-session-replay/README.md +++ b/packages/react-native-session-replay/README.md @@ -18,7 +18,7 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native-session-replay ``` -**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Pods can be linked statically (React Native's default) with Xcode 26 or later; with older Xcode versions, link them as dynamic frameworks (`use_frameworks! :linkage => :dynamic` in your `Podfile`). ## Enable Session Replay diff --git a/packages/react-native-webview/README.md b/packages/react-native-webview/README.md index 13af9d9d4..11369e163 100644 --- a/packages/react-native-webview/README.md +++ b/packages/react-native-webview/README.md @@ -20,7 +20,7 @@ Set up the RUM Browser SDK on the web page you want rendered on your mobile Reac Add `react-native-webview` to your application following the [official installation documentation][4]. -**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Pods can be linked statically (React Native's default) with Xcode 26 or later; with older Xcode versions, link them as dynamic frameworks (`use_frameworks! :linkage => :dynamic` in your `Podfile`). ### Instrument your web views From 47482e81615c20620660359167ee96f741631928 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 12:11:43 +0100 Subject: [PATCH 15/19] Revert "Build the statically linked example with Xcode 26" --- .gitlab-ci.yml | 9 --------- packages/core/README.md | 2 +- packages/react-native-session-replay/README.md | 2 +- packages/react-native-webview/README.md | 2 +- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e11558b93..576b454cb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,12 +45,6 @@ stages: - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_EMULATOR_IMAGE" - yes | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --licenses || true - echo "no" | ~/android_sdk/cmdline-tools/latest/bin/avdmanager --verbose create avd --force --name "$EMULATOR_NAME" --package "$ANDROID_EMULATOR_IMAGE" - # example/ links pods statically, which needs Xcode 26: with older versions the native SDK's Swift - # packages fail to link with duplicate symbols. Apps uploaded to the App Store must be built with - # Xcode 26 since April 2026, and example-new-architecture/ keeps covering Xcode 16 with dynamic frameworks. - select-xcode-26: - - export DEVELOPER_DIR="$(ls -d /Applications/Xcode-26*.app | sort -V | tail -1)/Contents/Developer" - - xcodebuild -version # TESTS @@ -110,7 +104,6 @@ test:native-ios: - if: '$BUILD_BENCHMARK != "true"' timeout: 1h script: - - !reference [.snippets, select-xcode-26] - yarn - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNative test -destination "$IOS_SIMULATOR_DESTINATION" -derivedDataPath "$IOS_DERIVED_DATA_PATH" | xcbeautify @@ -122,7 +115,6 @@ test:native-ios-sr: - if: '$BUILD_BENCHMARK != "true"' timeout: 1h script: - - !reference [.snippets, select-xcode-26] - yarn - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNativeSessionReplay test -destination "$IOS_SIMULATOR_DESTINATION" -derivedDataPath "$IOS_DERIVED_DATA_PATH" | xcbeautify @@ -171,7 +163,6 @@ build-examples:ios: - if: '$BUILD_BENCHMARK != "true"' timeout: 1h script: - - !reference [.snippets, select-xcode-26] - yarn - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DdSdkReactNativeExample -configuration Debug -sdk iphonesimulator -destination "$IOS_SIMULATOR_DESTINATION" -derivedDataPath "$IOS_DERIVED_DATA_PATH" build | xcbeautify diff --git a/packages/core/README.md b/packages/core/README.md index 495a93468..4bd06bd89 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -16,7 +16,7 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native ``` -**Minimum React Native version**: SDK supports React Native version 0.63.4 or higher on Android. On iOS, the native SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Pods can be linked statically (React Native's default) with Xcode 26 or later; with older Xcode versions, link them as dynamic frameworks (`use_frameworks! :linkage => :dynamic` in your `Podfile`). +**Minimum React Native version**: SDK supports React Native version 0.63.4 or higher on Android. On iOS, the native SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Versions `1.0.0-rc5` and higher require you to have `compileSdkVersion = 31` in the Android application setup, which implies that you should use Build Tools version 31, Android Gradle Plugin version 7, and Gradle version 7 or higher. To modify the versions, change the values in the `buildscript.ext` block of your application's top-level `build.gradle` file. Datadog recommends using React Native version 0.67 or higher. diff --git a/packages/react-native-session-replay/README.md b/packages/react-native-session-replay/README.md index c07a7aea6..3a2aca155 100644 --- a/packages/react-native-session-replay/README.md +++ b/packages/react-native-session-replay/README.md @@ -18,7 +18,7 @@ To install with Yarn, run: yarn add @datadog/mobile-react-native-session-replay ``` -**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Pods can be linked statically (React Native's default) with Xcode 26 or later; with older Xcode versions, link them as dynamic frameworks (`use_frameworks! :linkage => :dynamic` in your `Podfile`). +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. ## Enable Session Replay diff --git a/packages/react-native-webview/README.md b/packages/react-native-webview/README.md index 11369e163..13af9d9d4 100644 --- a/packages/react-native-webview/README.md +++ b/packages/react-native-webview/README.md @@ -20,7 +20,7 @@ Set up the RUM Browser SDK on the web page you want rendered on your mobile Reac Add `react-native-webview` to your application following the [official installation documentation][4]. -**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. Pods can be linked statically (React Native's default) with Xcode 26 or later; with older Xcode versions, link them as dynamic frameworks (`use_frameworks! :linkage => :dynamic` in your `Podfile`). +**iOS setup**: the native iOS SDK is resolved through Swift Package Manager, which requires React Native 0.75 or higher. ### Instrument your web views From 8e605f84aeebf3b802a482a1a5bba18b35987295 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 14:22:28 +0100 Subject: [PATCH 16/19] Remove duplicate Swift package objects from the static core archive --- packages/core/DatadogSDKReactNative.podspec | 40 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index bbc7f50ce..3635b0570 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -64,6 +64,36 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) end end + # Xcode versions before 26 hand each package object to libtool twice when they archive a pod that + # requests package products, so the core pod's static archive holds two copies of every Datadog + # object, and the -ObjC flag CocoaPods links apps and tests with loads both: duplicate symbols. + # This drops the extra copies once the archive is built. Xcode 26 archives each object once, so + # it finds nothing to remove there. + def datadog_dedupe_static_archive(installer) + core = installer.pod_targets.find { |pod| pod.name == 'DatadogSDKReactNative' } + return if core.nil? || core.build_as_dynamic? + + phase_name = '[Datadog] Remove duplicate Swift package objects' + target = installer.pods_project.targets.find { |t| t.name == 'DatadogSDKReactNative' } + return if target.nil? || target.shell_script_build_phases.any? { |phase| phase.name == phase_name } + + phase = installer.pods_project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) + phase.name = phase_name + phase.shell_script = <<~'SH' + archive="${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}" + [ -n "$(ar -t "${archive}" | sort | uniq -d)" ] || exit 0 + ar -t "${archive}" | sort | uniq -c | while read -r count member; do + while [ "${count}" -gt 1 ]; do + ar -d "${archive}" "${member}" + count=$((count - 1)) + done + done + ranlib "${archive}" + SH + phase.always_out_of_date = '1' + target.build_phases << phase + end + # CocoaPods numbers the Pods project's UUIDs from a counter without checking for collisions, # which only holds while it creates every object itself. By the time post-install hooks run it # has made the UUIDs deterministic, and once the batch it had left runs out the counter @@ -78,6 +108,7 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) def apply_on_post_install(installer) datadog_reserve_unique_uuids(installer.pods_project) datadog_request_static_products_from_core(installer) + datadog_dedupe_static_archive(installer) super embed = <<~'SH' # Embeds the Datadog Swift package frameworks that Xcode builds dynamically. Looks where Xcode @@ -103,7 +134,12 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) embed_datadog_spm_frameworks "DatadogInternal" embed_datadog_spm_frameworks "Datadog*_PackageProduct" SH - anchor = /^if \[ "\$\{COCOAPODS_PARALLEL_CODE_SIGN\}" == "true" \]; then$/ + # The embed phase's file lists only name the pod frameworks. Listing the package requirement makes + # an SDK version change rewrite this script, an input of the phase, so Xcode runs it again and + # copies the new frameworks, as React Native does for the frameworks it embeds itself. + requirements = (instance_variable_get(:@dependencies_by_pod) || {}).fetch('DatadogSDKReactNative', []) + .map { |dependency| "# #{dependency[:url]} #{dependency[:requirement]}\n" }.uniq.join + anchor =/^if \[ "\$\{COCOAPODS_PARALLEL_CODE_SIGN\}" == "true" \]; then$/ installer.aggregate_targets.each do |target| next unless target.pod_targets.any? { |pod| pod.name == 'DatadogSDKReactNative' } script_path = target.embed_frameworks_script_path @@ -114,7 +150,7 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) raise "Datadog: could not add the native iOS SDK frameworks to #{script_path}, " \ "so the app would crash at launch in Release builds." end - File.write(script_path, script.sub(anchor) { "#{embed}#{$&}" }) + File.write(script_path, script.sub(anchor) { "#{embed}#{requirements}#{$&}" }) end end end) From a9d1373240cca4950dafb4233947214b0b68858b Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 14:22:29 +0100 Subject: [PATCH 17/19] Read pod linkage from the app target only --- .../DatadogInternalTesting.podspec | 8 +++----- .../DatadogSDKReactNativeSessionReplay.podspec | 11 ++++------- .../DatadogSDKReactNativeWebView.podspec | 11 ++++------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/internal-testing-tools/DatadogInternalTesting.podspec b/packages/internal-testing-tools/DatadogInternalTesting.podspec index 6b4d10781..69430941c 100644 --- a/packages/internal-testing-tools/DatadogInternalTesting.podspec +++ b/packages/internal-testing-tools/DatadogInternalTesting.podspec @@ -16,11 +16,9 @@ end # Only with dynamic frameworks does Xcode build DatadogInternal as a framework of its own. When pods # are linked statically its code is in DatadogSDKReactNative's archive instead, which requests -# every Datadog product then (see DatadogSDKReactNative.podspec). The Podfile is read as well as -# USE_FRAMEWORKS because apps can call `use_frameworks!` without setting the env var. -podfile = Pod::Config.instance.podfile rescue nil -uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' || - (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.dynamic_framework? }) +# every Datadog product then (see DatadogSDKReactNative.podspec). React Native's +# `use_react_native!` records how the app's target links pods in USE_FRAMEWORKS. +uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' Pod::Spec.new do |s| s.name = "DatadogInternalTesting" diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index beb15dd85..0c7649ce0 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -14,16 +14,13 @@ if !respond_to?(:spm_dependency, true) "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." end -# How the app links pods (`use_frameworks!`). The Podfile is read as well as USE_FRAMEWORKS because -# apps can call `use_frameworks!` without setting the env var. -podfile = Pod::Config.instance.podfile rescue nil -uses_frameworks = !ENV['USE_FRAMEWORKS'].nil? || - (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.framework? }) +# How the app links pods (`use_frameworks!`): React Native's `use_react_native!` records it for the +# app's target in USE_FRAMEWORKS, which React Native's own podspecs read too. +uses_frameworks = !ENV['USE_FRAMEWORKS'].nil? # Only with dynamic frameworks does Xcode build DatadogInternal as a framework of its own. When pods # are linked statically its code is in DatadogSDKReactNative's archive instead, which requests # every Datadog product then (see DatadogSDKReactNative.podspec). -uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' || - (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.dynamic_framework? }) +uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' Pod::Spec.new do |s| s.name = "DatadogSDKReactNativeSessionReplay" diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index dacd8280e..fc83f695d 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -14,16 +14,13 @@ if !respond_to?(:spm_dependency, true) "React Native >= 0.75 -- the first version to ship the `spm_dependency` podspec helper." end -# How the app links pods (`use_frameworks!`). The Podfile is read as well as USE_FRAMEWORKS because -# apps can call `use_frameworks!` without setting the env var. -podfile = Pod::Config.instance.podfile rescue nil -uses_frameworks = !ENV['USE_FRAMEWORKS'].nil? || - (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.framework? }) +# How the app links pods (`use_frameworks!`): React Native's `use_react_native!` records it for the +# app's target in USE_FRAMEWORKS, which React Native's own podspecs read too. +uses_frameworks = !ENV['USE_FRAMEWORKS'].nil? # Only with dynamic frameworks does Xcode build DatadogInternal as a framework of its own. When pods # are linked statically its code is in DatadogSDKReactNative's archive instead, which requests # every Datadog product then (see DatadogSDKReactNative.podspec). -uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' || - (!podfile.nil? && podfile.target_definition_list.any? { |target| target.build_type.dynamic_framework? }) +uses_dynamic_frameworks = ENV['USE_FRAMEWORKS'] == 'dynamic' Pod::Spec.new do |s| s.name = "DatadogSDKReactNativeWebView" From 7529206b4bbca1bba242d9832fa52b37014ee989 Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 15:07:46 +0100 Subject: [PATCH 18/19] Handle universal archives when removing duplicate Swift package objects --- packages/core/DatadogSDKReactNative.podspec | 45 +++++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index 3635b0570..7388a121c 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -67,8 +67,9 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) # Xcode versions before 26 hand each package object to libtool twice when they archive a pod that # requests package products, so the core pod's static archive holds two copies of every Datadog # object, and the -ObjC flag CocoaPods links apps and tests with loads both: duplicate symbols. - # This drops the extra copies once the archive is built. Xcode 26 archives each object once, so - # it finds nothing to remove there. + # This drops the extra copies once the archive is built, slice by slice when it is a universal + # archive, which ar cannot read. Xcode 26 archives each object once, so it finds nothing to remove + # there and leaves the archive untouched. def datadog_dedupe_static_archive(installer) core = installer.pod_targets.find { |pod| pod.name == 'DatadogSDKReactNative' } return if core.nil? || core.build_as_dynamic? @@ -80,15 +81,43 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) phase = installer.pods_project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) phase.name = phase_name phase.shell_script = <<~'SH' + set -e archive="${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}" - [ -n "$(ar -t "${archive}" | sort | uniq -d)" ] || exit 0 - ar -t "${archive}" | sort | uniq -c | while read -r count member; do - while [ "${count}" -gt 1 ]; do - ar -d "${archive}" "${member}" - count=$((count - 1)) + has_duplicates() { + [ -n "$(ar -t "$1" | sort | uniq -d)" ] + } + dedupe() { + ar -t "$1" | sort | uniq -c | while read -r count member; do + while [ "${count}" -gt 1 ]; do + ar -d "$1" "${member}" + count=$((count - 1)) + done done + ranlib "$1" + } + archs="$(lipo -archs "${archive}")" + if [ "$(echo ${archs} | wc -w)" -eq 1 ]; then + ar -t "${archive}" > /dev/null + has_duplicates "${archive}" || exit 0 + dedupe "${archive}" + exit 0 + fi + # Universal archive: ar only reads thin archives, so work on each architecture's slice. + mkdir -p "${DERIVED_FILE_DIR}" + found=false + slices="" + for arch in ${archs}; do + slice="${DERIVED_FILE_DIR}/datadog-dedupe-${arch}.a" + lipo -thin "${arch}" "${archive}" -output "${slice}" + ar -t "${slice}" > /dev/null + if has_duplicates "${slice}"; then + found=true + dedupe "${slice}" + fi + slices="${slices} ${slice}" done - ranlib "${archive}" + [ "${found}" = true ] || exit 0 + lipo -create ${slices} -output "${archive}" SH phase.always_out_of_date = '1' target.build_phases << phase From 619d526fa2af8c638bc76635f1410fb71320cc3d Mon Sep 17 00:00:00 2001 From: Sara Susano Date: Mon, 26 Oct 2026 15:26:27 +0100 Subject: [PATCH 19/19] Quote the slice paths when rebuilding universal archives --- packages/core/DatadogSDKReactNative.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index 7388a121c..ba9356d7b 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -105,7 +105,7 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) # Universal archive: ar only reads thin archives, so work on each architecture's slice. mkdir -p "${DERIVED_FILE_DIR}" found=false - slices="" + set -- for arch in ${archs}; do slice="${DERIVED_FILE_DIR}/datadog-dedupe-${arch}.a" lipo -thin "${arch}" "${archive}" -output "${slice}" @@ -114,10 +114,10 @@ unless SPM.singleton_class.method_defined?(:datadog_embeds_spm_frameworks?) found=true dedupe "${slice}" fi - slices="${slices} ${slice}" + set -- "$@" "${slice}" done [ "${found}" = true ] || exit 0 - lipo -create ${slices} -output "${archive}" + lipo -create "$@" -output "${archive}" SH phase.always_out_of_date = '1' target.build_phases << phase