sentry-cocoa
sentry-cocoa copied to clipboard
feat: Add support for dynamic library
:scroll: Description
This PR adds support for using a dynamic library. Keeping it an additive change, and not breaking, I added a new library product that generates Sentry-Dynamic.
:bulb: Motivation and Context
The motivation behind this work is personal. I am working on a project that utilizes a private framework within the same Xcode project. With nested frameworks like this, Xcode fails to compile the duplication.
Relevant Swift forum thread: https://forums.swift.org/t/swift-packages-in-multiple-targets-results-in-this-will-result-in-duplication-of-library-code-errors/34892
:green_heart: How did you test it?
After adding in the project there are two frameworks now listed under the Sentry category: Sentry and Sentry-Dynamic

:pencil: Checklist
- [x] I reviewed the submitted code
- [ ] I added tests to verify the changes
- [ ] I updated the docs if needed
- [x] Review from the native team if needed
- [x] No breaking changes
:crystal_ball: Next steps
Thanks, @mrtnrst, for opening this PR. After reading the thread you pointed out I'm not convinced that adding a new .dynamic target is the solution. I don't find this in any other open-source libraries supporting SPM. It seems to me that this is more of an issue with Xcode. Can you maybe be more specific, about why you think your change is necessary?
Thanks, @mrtnrst, for opening this PR. After reading the thread you pointed out I'm not convinced that adding a new
.dynamictarget is the solution. I don't find this in any other open-source libraries supporting SPM. It seems to me that this is more of an issue with Xcode. Can you maybe be more specific, about why you think your change is necessary?
I can get a sample application tonight to help demonstrate what I am talking about. For other repos that support this, here are two that my team is actively using: https://github.com/DataDog/dd-sdk-ios/blob/1c3e2b0395864c8764812226b74797866d7ff0d4/Package.swift#L11-L37 https://github.com/ReactiveX/RxSwift/blob/693a6218e0800753cb54e55f278d050ae9a15938/Package.swift#L46-L60
Thanks for the update, @mrtnrst. A sample application would be excellent. Ideally, we would like to validate the dynamic library in CI similar to https://github.com/getsentry/sentry-cocoa/blob/2e5882cec6275de1c4fc0c7e47ff6a54da7dfe9c/.github/workflows/build.yml#L109-L124
Your sample app could maybe be a starting point to achieve this.
@philipphofmann sorry for the delay here, work is a little busy. I will try to get back to this later in the week 🙏🏽
That's actually the only way to support dynamic frameworks via SPM:
- Carthage: it is possible to modify build settings for the Sentry target by manually changing
MACH_O_TYPEtodylib - CocoaPods: AFAIK they build dynamic frameworks by default, unless you specify
static_framework: truefor those targets, where you expect to have static linkage, or by providing some global parameter instead of!use_frameworks - Swift Package Manager: ???
typecan only be specified in thePackage.swiftfile and can't be overridden by a consumer- no way to modify build settings
- not an easy way to maintain a separate repository with source files, but with a modified
Package.swiftthat hasdynamictype
We're using a dynamic library in Unity, for macOS: https://github.com/getsentry/sentry-unity/pull/710 I wonder if this would simplify things there. @vaind would know best
We're using a dynamic library in Unity, for macOS: getsentry/sentry-unity#710 I wonder if this would simplify things there. @vaind would know best
Yeah I've had a look at this PR but didn't get what this actually changes - the Sentry library that's inside a built Sentry.framework is already a dynamic library - e.g. in the Unity SDK, I'm just copying it & renaming - needs to be a plain *.dylib file, not a .framework for Unity to be willing to include it in a project build.
This pull request has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!
"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀
Hey @mrtnrst, do you have time to add the sample application for validation in CI, maybe?
This pull request has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!
"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀
Hey @mrtnrst, do you have time to add the sample application for validation in CI, maybe?
Hi! Apologies for the terrible delay (I kept staring at this notification and just scared myself into not opening it 😅).
What kind of example project were you wanting? Something that passes and runs through CI? Or something that demonstrates the issue I am having?
Hey @mrtnrst, please see my comment above https://github.com/getsentry/sentry-cocoa/pull/1726#issuecomment-1084727579.
Thanks, @mrtnrst, for adding the sample. I will get back to this PR later.
Hi @mrtnrst, I'm just looking for some clarification on how you have your project set up (and per https://github.com/getsentry/sentry-cocoa/pull/1726#issuecomment-1183546409, I think it would be helpful to have a MVP that mimics your actual setup, which can then also be used to validate).
AIUI, you have an app target and a static library target, and both of them link in Sentry, so that statically linking your library into your app results in duplicate Sentry symbols from both targets. You'd like to be able to declare your app and library to link Sentry dynamically at runtime instead of at build time to avoid the duplication. Is that right?
graph LR;
App--static-->Lib;
App--static-->Sentry;
Lib--static-->Sentry;
I tried setting this up using only Xcode targets but couldn't force a duplicate symbol error, so it must be something specific to how SPM does things. I tried using SPM based on the example you provided but the project it creates for me crashes Xcode as soon as I try to build 😰
Hi @mrtnrst, I'm just looking for some clarification on how you have your project set up (and per #1726 (comment), I think it would be helpful to have a MVP that mimics your actual setup, which can then also be used to validate).
AIUI, you have an app target and a static library target, and both of them link in Sentry, so that statically linking your library into your app results in duplicate Sentry symbols from both targets. You'd like to be able to declare your app and library to link Sentry dynamically at runtime instead of at build time to avoid the duplication. Is that right?
I tried setting this up using only Xcode targets but couldn't force a duplicate symbol error, so it must be something specific to how SPM does things. I tried using SPM based on the example you provided but the project it creates for me crashes Xcode as soon as I try to build 😰
I'll see if I can get a more exact replica of what I am experiencing here. And to answer you other question, that is correct. The framework project we create cannot import the Sentry target without creating the duplicate references so the change to make it dynamic (to allow the import without embed) gives us that freedom. We would still want to use the static embedded framework on the main project, not the dynamic library.
This pull request has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!
"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀
I'm going to merge this after releasing the hotfix 7.24.1.
It seems to me that Sentry-Dynamic is building an empty framework?
$ ( cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework; find . )
.
./_CodeSignature
./_CodeSignature/CodeResources
./_CodeSignature/CodeDirectory
./_CodeSignature/CodeRequirements-1
./_CodeSignature/CodeSignature
./_CodeSignature/CodeRequirements
./Info.plist
Build of Sentry-Dynamic:
Showing All Messages
Build target Sentry-Dynamic
MkDir /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework (in target 'Sentry-Dynamic' from project 'Sentry')
cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/SourcePackages/checkouts/sentry-cocoa
/bin/mkdir -p /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework
WriteAuxiliaryFile /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/Sentry.build/Debug-iphonesimulator/Sentry-Dynamic\ product.build/empty-Sentry-Dynamic.plist (in target 'Sentry-Dynamic' from project 'Sentry')
cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/SourcePackages/checkouts/sentry-cocoa
write-file /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/Sentry.build/Debug-iphonesimulator/Sentry-Dynamic\ product.build/empty-Sentry-Dynamic.plist
ProcessInfoPlistFile /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework/Info.plist /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/Sentry.build/Debug-iphonesimulator/Sentry-Dynamic\ product.build/empty-Sentry-Dynamic.plist (in target 'Sentry-Dynamic' from project 'Sentry')
cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/SourcePackages/checkouts/sentry-cocoa
builtin-infoPlistUtility /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/Sentry.build/Debug-iphonesimulator/Sentry-Dynamic\ product.build/empty-Sentry-Dynamic.plist -producttype com.apple.product-type.framework -expandbuildsettings -format binary -platform iphonesimulator -o /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework/Info.plist
CodeSign /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework (in target 'Sentry-Dynamic' from project 'Sentry')
cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/SourcePackages/checkouts/sentry-cocoa
Signing Identity: "-"
/usr/bin/codesign --force --sign - --timestamp\=none --generate-entitlement-der /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework
RegisterExecutionPolicyException /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework (in target 'Sentry-Dynamic' from project 'Sentry')
cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/SourcePackages/checkouts/sentry-cocoa
builtin-RegisterExecutionPolicyException /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework
Touch /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework (in target 'Sentry-Dynamic' from project 'Sentry')
cd /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/SourcePackages/checkouts/sentry-cocoa
/usr/bin/touch -c /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework
Causes a failure trying to use the framework:
Showing All Messages
Ld /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/LoggingCore.framework/LoggingCore normal (in target 'LoggingCore' from project 'hubstaff-ios')
cd /Users/hubstaff/Developer/hubstaff/ios
/Applications/Xcode-14.1.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -target arm64-apple-ios15.0-simulator -dynamiclib -isysroot /Applications/Xcode-14.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator16.1.sdk -L/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/EagerLinkingTBDs -L/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/EagerLinkingTBDs -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks -F/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator -filelist /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/hubstaff-ios.build/Debug-iphonesimulator/LoggingCore.build/Objects-normal/arm64/LoggingCore.LinkFileList -install_name @rpath/LoggingCore.framework/LoggingCore -dead_strip -Xlinker -object_path_lto -Xlinker /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/hubstaff-ios.build/Debug-iphonesimulator/LoggingCore.build/Objects-normal/arm64/LoggingCore_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -fobjc-link-runtime -L/Applications/Xcode-14.1.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -L/usr/lib/swift -Xlinker -add_ast_path -Xlinker /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/hubstaff-ios.build/Debug-iphonesimulator/LoggingCore.build/Objects-normal/arm64/LoggingCore.swiftmodule -lc++ -framework UIKit -framework Security -framework StoreKit -lsqlite3 -lc++ -lz -lz -framework StoreKit -lsqlite3 -lc++ -lz -lz -lc++ -framework SystemConfiguration -framework SystemConfiguration -framework CoreTelephony /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework/Sentry-Dynamic -framework HubstaffCore -framework FirebaseAnalytics -framework GoogleAppMeasurement -Xlinker -no_adhoc_codesign -compatibility_version 1 -current_version 1 -Xlinker -dependency_info -Xlinker /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/hubstaff-ios.build/Debug-iphonesimulator/LoggingCore.build/Objects-normal/arm64/LoggingCore_dependency_info.dat -o /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/LoggingCore.framework/LoggingCore -Xlinker -add_ast_path -Xlinker /Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Intermediates.noindex/Firebase.build/Debug-iphonesimulator/FirebaseCoreInternal.build/Objects-normal/arm64/FirebaseCoreInternal.swiftmodule
clang: error: no such file or directory: '/Users/hubstaff/Library/Developer/Xcode/DerivedData/hubstaff-gzrfwrxonhprdsgrwcthjbfooayp/Build/Products/Debug-iphonesimulator/PackageFrameworks/Sentry-Dynamic.framework/Sentry-Dynamic'
Command Ld failed with a nonzero exit code
Command Ld failed with a nonzero exit code
@lhunath, please open a new issue for your problem above.
I tried yesterday, but half-way through collecting facts around the issue my problem disappeared and the Sentry-Dynamic framework started receiving its binary. I could not find out what the repro is. I will come back to a new issue if I have more reliable details.
I'm happy that the problem disappeared. Thanks for the update, @lhunath 🙏.