Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolving a service registered in a framework fails if Swinject is integrated via Swift Package Manager #425

Closed
chkpnt opened this issue Jul 22, 2019 · 4 comments

Comments

@chkpnt
Copy link

commented Jul 22, 2019

I'm just playing around with the integration of Swinject using Swift Package Manager in Xcode 11 beta 4 and observing an issue I can't reproduce if Swinject is integrated with Carthage.

I have an App-Target as well as a Framework-target, both using Swinject. The framework registers its service SomeFrameworkStuff to the app's container using an assembly. Logging the container's content shows that the registration succeeded:

Available through Swinject Container: [
    { Service: Bla, Factory: Resolver -> Bla, ObjectScope: graph },
    { Service: SomeFrameworkStuff, Factory: Resolver -> SomeFrameworkStuff, ObjectScope: graph }
]

But when I try to resolve SomeFrameworkStuff.self, I get

Swinject: Resolution failed. Expected registration:
	{ Service: SomeFrameworkStuff, Factory: Resolver -> SomeFrameworkStuff }

I have various duplicate class warnings, too:

[...]
objc[34972]: Class _TtC8Swinject8SpinLock is implemented in both /Users/ich/Library/Developer/Xcode/DerivedData/SwinjectDemo-dujsuddxiashuwezjwqwxafkvchr/Build/Products/Debug-iphonesimulator/SomeFramework.framework/SomeFramework (0x102ea18e8) and /Users/ich/Library/Developer/CoreSimulator/Devices/2CAB296B-2A4B-47A7-9E76-682BA1E6FA4A/data/Containers/Bundle/Application/7D3C3CCC-67BC-44F1-A57C-769083060488/SwinjectDemo.app/SwinjectDemo (0x102b08520). One of the two will be used. Which one is undefined.
objc[34972]: Class _TtC8Swinject20SynchronizedResolver is implemented in both /Users/ich/Library/Developer/Xcode/DerivedData/SwinjectDemo-dujsuddxiashuwezjwqwxafkvchr/Build/Products/Debug-iphonesimulator/SomeFramework.framework/SomeFramework (0x102ea1980) and /Users/ich/Library/Developer/CoreSimulator/Devices/2CAB296B-2A4B-47A7-9E76-682BA1E6FA4A/data/Containers/Bundle/Application/7D3C3CCC-67BC-44F1-A57C-769083060488/SwinjectDemo.app/SwinjectDemo (0x102b085b8). One of the two will be used. Which one is undefined.
objc[34972]: Class _TtGCs18_DictionaryStorageV8Swinject10ServiceKeyPS0_20ServiceEntryProtocol__$ is implemented in both /Applications/Xcode-11-beta4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/libswiftCore.dylib (0x7fff899aeb78) and /Applications/Xcode-11-beta4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/
[...]
objc[34972]: Class _TtGC8Swinject12ServiceEntryP13SomeFramework18SomeFrameworkStuff__ is implemented in both /Applications/Xcode-11-beta4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/libswiftCore.dylib (0x7fff899aeda8) and /Applications/Xcode-11-beta4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/libswiftCore.dylib (0x7fff899b49f0). One of the two will be used. Which one is undefined.

The Xcode project demonstrating the issue is available at chkpnt/SwinjectDemo.

@jakubvano

This comment has been minimized.

Copy link
Member

commented Jul 22, 2019

Looks like this is an issue with linking static libs to dynamic frameworks. If I remove Swinject from SwinjectDemo's link with libraries build phase (so that it uses transitively linked lib), it works OK.

@chkpnt

This comment has been minimized.

Copy link
Author

commented Jul 22, 2019

I can't compile the framework if Swinject is removed from the build phase. Is there a step I'm missing?

@jakubvano

This comment has been minimized.

Copy link
Member

commented Jul 23, 2019

I removed it only from the SwinjectDemo target, kept it in SwinjectFramework build phases.

@chkpnt

This comment has been minimized.

Copy link
Author

commented Jul 25, 2019

Okay, the static lib is indeed causing this issue. Your workaround works, but only if there is not more than one framework involved. (I've added a second framwork to my demonstrator).

The only way I've found Xcode to build Swinject as a dynamic library is by modifying its Package.swift to

   ...
    products: [
        .library(name: "Swinject", type: .dynamic, targets: ["Swinject"])
    ],
   ...

This way, everything is working as expected. But in my opinion, this shouldn't be needed. In the documentation of SPM, the following is written:

A library's product can either be statically or dynamically linked. It is recommended to not declare the type of library explicitly to let the Swift Package Manager choose between static or dynamic linking depending on the consumer of the package.

-> There should be an option in Xcode to define how to consume the package.

@chkpnt chkpnt closed this Jul 25, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.