I have expo module where I was trying to add package: https://github.com/garmin/fit-swift-sdk as depnedency but it only supports SPM. When trying to use:
spm_dependency(s,
url: 'https://github.com/garmin/fit-swift-sdk.git',
requirement: {kind: 'upToNextMajorVersion', minimumVersion: '21.178.0'},
products: ['FITSwiftSDK']
)Inside my module .podspec file it was throwing an error on build: x duplicate symbols
This worked for my case but it might not work for your dependecies.
- Create local .podspec files for your dependency pointing to github repo. I had to create two files one for
FITSwiftSDKand second one forSwiftCollectionsbecuseFITSwiftSDKdepends onSwiftCollections.
# FITSwiftSDK.podspec
Pod::Spec.new do |s|
s.name = 'FITSwiftSDK'
s.version = '21.178.0'
s.summary = 'Garmin FIT SDK for Swift'
s.homepage = 'https://github.com/garmin/fit-swift-sdk'
s.license = { :type => 'Apache 2.0' }
s.author = 'Garmin'
s.source = {
:git => 'https://github.com/garmin/fit-swift-sdk.git',
:tag => s.version.to_s
}
s.ios.deployment_target = '15.1'
s.swift_version = '5.9'
s.source_files = 'Sources/FITSwiftSDK/**/*.swift'
s.module_name = 'FITSwiftSDK'
s.dependency 'SwiftCollections' # <- other module dependency decalered in second podspec
end# SwiftCollections.podspec
Pod::Spec.new do |s|
s.name = 'SwiftCollections'
s.version = '1.2.0'
s.summary = 'Swift Collections - OrderedCollections module only'
s.homepage = 'https://github.com/apple/swift-collections'
s.license = { :type => 'Apache 2.0' }
s.author = 'Apple Inc.'
s.source = {
:git => 'https://github.com/apple/swift-collections.git',
:tag => s.version.to_s
}
s.ios.deployment_target = '15.1'
s.swift_version = '5.9'
# Including only modules I need in FITSwiftSDK
s.source_files = [
'Sources/OrderedCollections/**/*.swift',
'Sources/Collections/**/*.swift',
'Sources/InternalCollectionsUtilities/**/*.swift',
'Sources/_CollectionsUtilities/**/*.swift'
]
s.module_name = 'OrderedCollections'
# Exclude everything else
s.exclude_files = [
'Sources/DequeModule/**/*',
'Sources/HashTreeCollections/**/*',
'Sources/BitCollections/**/*',
'**/Tests/**/*'
]
s.pod_target_xcconfig = {
'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => 'COLLECTIONS_SINGLE_MODULE'
}
end- I have placed both files in root of my app
podspecs/folder. And then inside my expo module podspec i have added regular dependecny:
Pod::Spec.new do |s|
s.name = 'ExpoAppleHealthModule'
s.version = '1.0.0'
s.summary = 'A sample project summary'
s.description = 'A sample project description'
s.author = ''
s.homepage = 'https://docs.expo.dev/modules/'
s.platforms = { :ios => '15.1', :tvos => '15.1' }
s.source = { git: '' }
s.static_framework = true
s.dependency 'ExpoModulesCore'
s.dependency 'FITSwiftSDK' # <- My SDK I need but imported as cocoapods
# Swift/Objective-C compatibility
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
'SWIFT_COMPILATION_MODE' => 'wholemodule'
}
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
end- Create expo plugins. To make it work with expo I needed to copy those podspecs files to
ios/folder and modify my appPodfile:
This will copy FITSwiftSDK.podspec and SwiftCollections.podspec from my podspecs/ folder to ios/ folder.
// withAddXcodeSourceFile.ts
import fs from "fs"
import path from "path"
import { ExpoConfig } from "@expo/config"
import { withXcodeProject, ConfigPlugin } from "@expo/config-plugins"
type WithAddXcodeSourceFileProps = {
files: Array<string>
}
const withAddXcodeSourceFile: ConfigPlugin<WithAddXcodeSourceFileProps> = (config: ExpoConfig, { files }) => withXcodeProject(config, async (config) => {
const iosProjectFolder = path.join(__dirname, "../ios")
const podspecsFolder = path.join(__dirname, "../podspecs")
files.forEach(file => {
fs.copyFileSync(`${podspecsFolder}/${file}`, `${iosProjectFolder}/${file}`)
})
return config
})
export default withAddXcodeSourceFileAnd this will modify my main Podfile to inlcude my custom podspecs:
// withCustomPods.ts
// This plugin will add:
// pod 'FITSwiftSDK', :podspec => './FITSwiftSDK.podspec'
// pod 'SwiftCollections', :podspec => './SwiftCollections.podspec'
// To ios/Podfile
/* eslint-disable no-restricted-imports */
import { ExpoConfig } from "expo/config"
import { withPodfile, ConfigPlugin } from "@expo/config-plugins"
import { mergeContents } from "@expo/config-plugins/build/utils/generateCode"
type WithCustomPodsProps = {
pods: Array<string>
}
const withCustomPods: ConfigPlugin<WithCustomPodsProps> = (config: ExpoConfig, { pods }) => withPodfile(config, async (config) => {
config.modResults.contents = mergeContents({
tag: "custom-pods",
src: config.modResults.contents,
newSrc: pods.join("\n"),
anchor: /use_native_modules/,
offset: 0,
comment: "#"
}).contents
return config
})
export default withCustomPods- Added to my
pluginsarray in app.config.ts
//....
plugins: [
[
"./plugins/withAddXcodeSourceFile.ts",
{
files: [
"FITSwiftSDK.podspec",
"SwiftCollections.podspec"
]
}
],
[
"./plugins/withCustomPods.ts",
{
pods: [
"pod 'FITSwiftSDK', :podspec => './FITSwiftSDK.podspec'",
"pod 'SwiftCollections', :podspec => './SwiftCollections.podspec'"
]
}
],
//....