问题
I'm making my app modularized using Swift Package Manager
by separating various parts of the app into different layers (packages): Presentation, Business and Data to make it as clean as possible, and I link those manually created packages with the project in project settings -> Frameworks, Libraries and Embedded Content section. However, I'm still in need for Cocoa Pods
in some parts of the project, for simplicity my pod file contains the following:
target 'SampleApp' do
use_frameworks!
pod 'Localize-Swift'
end
when I import the Localize-Swift
into one of those packages' source files I get the error: No such module
, however Pods import works well in non-packaged parts of the app like SceneDelegate
.
I know that SPM
dependencies must be Swift Packages only, but is there any known workaround to link pods into swift packages ?
回答1:
It's possible but it's not useful because Swift Packages don't have weak linking to frameworks as XCode project does with -weak_framework <framework_name>
so you need to implement non trivial steps.
In swift package you can specify a framework to link with linkedFramework
:
.target(
name: "MyPackage",
dependencies: [],
linkerSettings: [
.linkedFramework("Localize_Swift")
.unsafeFlags(["-F/Users/user/.../Localize-Swift"])
]
),
Where unsafeFlags
specifies the full path to dir with the framework. But unexpectedly then you can not use your package with your app because of next issue:
The package product 'MyPackage' cannot be used as a dependency of this target because it uses unsafe build flags.
To compile Swift Package with your framework you should copy Localize_Swift.framework to target build dir of your package and then you can omit unsafe build flags of the package because the compiler sees all dependencies on the dir's root level.
.target(
name: "MyPackage",
dependencies: [],
linkerSettings: [
.linkedFramework("Localize_Swift")
]
),
The same you can do with your app after adding your package. If you copy Localize_Swift.framework to the app's target build dir then your linked swift package can be compiled because it looks for linkedFramework
in the current build dir.
By default pods are generated to separate folders in target build dir e.g.: $TARGET_BUILD_DIR/Localize-Swift/Localize_Swift.framework
so you can change CONFIGURATION_BUILD_DIR
for Localise-Swift
target in Pods project to generate the framework to the root of the target build dir or make a script to copy etc. But there is a problem that swift package dependencies are started compiling at the early begin of compilation process when you don't have any compiled pod frameworks. So at the first stage you should compile your Localize_Swift.framework before (better to make a fat framework) and then add a Pre-actions
Run Script
under Build
in your target scheme that copies the framework from your destination to target build dir.
cp -r $PROJECT_DIR/Localize_Swift.framework $TARGET_BUILD_DIR/Localize_Swift.framework
Now both your app and your swift package can be compiled with Localize_Swift framework.
As I say in the begin it's not useful because you need to compile Localize_Swift.framework manually (or with an additional script) before the general compilation process that neutralizes convenience of cocoa pods at all.
Consider using next preferred options:
- Pod is avaliable as a swift package. You can make a dependency in your package and in this case both your package and the dependency will be also available in your app. By the way Localize_Swift supports swift packages.
Pod has swift sources You can make your own swift package with the sources files and then link it to your package.
Pod has binaries From Swift 5.3 swift package can embed
xcframework
so you can build this xcframework from pod's binaries and then make binary target dependency in your swift package:.binaryTarget(name: "MyLib", path: "MyLib.xcframework")
(see How can I add a local library as a dependency in Swift Package Manager)
来源:https://stackoverflow.com/questions/63700091/using-a-pod-from-inside-a-swift-package