Skip to content

Instantly share code, notes, and snippets.

@schriker
Last active December 31, 2025 08:34
Show Gist options
  • Select an option

  • Save schriker/fb78fa819ecbbb976d232e3b2d60de12 to your computer and use it in GitHub Desktop.

Select an option

Save schriker/fb78fa819ecbbb976d232e3b2d60de12 to your computer and use it in GitHub Desktop.

Issue

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

My solution

This worked for my case but it might not work for your dependecies.

  1. Create local .podspec files for your dependency pointing to github repo. I had to create two files one for FITSwiftSDK and second one for SwiftCollections becuse FITSwiftSDK depends on SwiftCollections.
# 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
  1. 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
  1. Create expo plugins. To make it work with expo I needed to copy those podspecs files to ios/ folder and modify my app Podfile:

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 withAddXcodeSourceFile

And 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
  1. Added to my plugins array 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'"
                ]
            }
        ],
   //....
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment