diff --git a/example/ios/Podfile b/example/ios/Podfile index 0306fededd..81edb13339 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -9,6 +9,8 @@ platform :ios, '15.1' prepare_react_native_project! $RNMapboxMapsImpl = 'mapbox' +# RNMBX_SPM=1 pod install: get MapboxMaps through Swift Package Manager instead of CocoaPods +$RNMapboxMapsSwiftPackageManager = true if ENV['RNMBX_SPM'] == '1' if ENV['RNMBX10'] $RNMapboxMapsVersion = '10.19.0' end diff --git a/ios/install.md b/ios/install.md index 3b45a69d48..2f691da56f 100644 --- a/ios/install.md +++ b/ios/install.md @@ -58,6 +58,28 @@ $RNMapboxMapsVersion = '= 11.16.2' If using expo managed workflow, set the "RNMapboxMapsVersion" variable. See the [expo guide](/plugin/install.md) +## Using Swift Package Manager (experimental) + +By default the Mapbox SDK comes from CocoaPods. To get it through Swift Package Manager instead, set this at the top of your `ios/Podfile`: + +```ruby +$RNMapboxMapsSwiftPackageManager = true +``` + +The package requirement is derived from `$RNMapboxMapsVersion` (or the default version): `~> 11.23.1` becomes "up to next minor" from `11.23.1`, `= 11.23.1` an exact version. Your Podfile must call `react_native_post_install`, which adds the package. To override parts of the setup, pass a hash instead: + +```ruby +$RNMapboxMapsSwiftPackageManager = { + url: 'https://github.com/mapbox/mapbox-maps-ios.git', + requirement: { kind: 'exactVersion', version: '11.23.1' }, + product_name: 'MapboxMaps', +} +``` + +The `rnmapbox-maps` pod links `MapboxMaps`, and `MapboxCommon`, `MapboxCoreMaps` and `Turf` are embedded by CocoaPods' `[CP] Embed Pods Frameworks` phase. Don't add the `mapbox-maps-ios` package to your app target as well, that links a second copy; `pod install` removes it if an earlier `@rnmapbox/maps` version added it. + +With Expo, set `"RNMapboxMapsSwiftPackageManager": true` (or the hash as an object) in the plugin options. See the [expo guide](/plugin/install.md). + ## Troubleshooting ### Pod install fails on upgrade of @rnmapbox/maps with `could not find compatible versions for pod "MapboxMaps"` diff --git a/ios/rnmapbox_spm.rb b/ios/rnmapbox_spm.rb new file mode 100644 index 0000000000..e0cf50f87d --- /dev/null +++ b/ios/rnmapbox_spm.rb @@ -0,0 +1,62 @@ +# CocoaPods helpers for pods that get Mapbox frameworks through Swift Package Manager. +module RNMapboxSPM + @frameworks_by_pod ||= {} + @embedded_by_react_native ||= [] + + # CocoaPods doesn't embed the dynamic frameworks of a pod's Swift packages, so the app would crash at launch + # with dyld "Library not loaded: @rpath/.framework". Listing them among the frameworks CocoaPods embeds + # also makes it create the embed phase in apps without any dynamic pod. + def self.embed_frameworks(pod_name, framework_names) + @frameworks_by_pod[pod_name] = framework_names + end + + # facebook/react-native#58781 makes `spm_dependency` embed package frameworks itself, but only into an existing + # embed script. + def self.spm_dependency_options(pod_name, framework_names) + return {} unless defined?(::SPMManager) && + ::SPMManager.instance_method(:dependency).parameters.include?([:key, :embed_frameworks]) + @embedded_by_react_native << pod_name + { embed_frameworks: framework_names } + end + + def self.frameworks_to_embed(aggregate_target, embed_script_exists) + aggregate_target.pod_targets.flat_map do |pod| + next [] if embed_script_exists && @embedded_by_react_native.include?(pod.pod_name) + @frameworks_by_pod.fetch(pod.pod_name, []) + end.uniq + end + + # Xcode 26 archives collect xcframework signatures into one folder, and the copies Xcode writes to both the + # shared products dir and the pod's own build dir fail the archive with ".xcframework-ios.signature + # already exists". From react-native 0.87 a static pod with Swift packages builds into the shared dir, which + # then holds the only copy. + def self.signature_cleanup_script_phase(pod_name) + { + :name => "[#{pod_name}] Remove duplicate xcframework signatures", + :script => '[ "${CONFIGURATION_BUILD_DIR}" = "${PODS_CONFIGURATION_BUILD_DIR}" ] || ' \ + 'rm -f "${CONFIGURATION_BUILD_DIR}"/*.xcframework-*.signature', + :execution_position => :after_compile, + :always_out_of_date => '1' + } + end + + module AggregateTarget + def framework_paths_by_config + @rnmapbox_spm_framework_paths_by_config ||= begin + paths_by_config = super + embed_script_exists = paths_by_config.values.any?(&:any?) || + xcframeworks_by_config.values.flatten.any? { |xcframework| xcframework.build_type.dynamic_framework? } + frameworks = RNMapboxSPM.frameworks_to_embed(self, embed_script_exists) + paths_by_config.transform_values do |paths| + missing = frameworks.reject do |name| + paths.any? { |path| path.source_path.end_with?("/#{name}.framework") } + end + # Swift package binary targets are copied to the shared products dir whatever the pod's build dir is. + paths + missing.map { |name| Pod::Xcode::FrameworkPaths.new("${PODS_CONFIGURATION_BUILD_DIR}/#{name}.framework") } + end + end + end + end +end + +Pod::AggregateTarget.prepend(RNMapboxSPM::AggregateTarget) unless Pod::AggregateTarget.ancestors.include?(RNMapboxSPM::AggregateTarget) diff --git a/plugin/build/withMapbox.d.ts b/plugin/build/withMapbox.d.ts index 74aa188dde..1361e6983e 100644 --- a/plugin/build/withMapbox.d.ts +++ b/plugin/build/withMapbox.d.ts @@ -11,10 +11,24 @@ export type MapboxPlugProps = { */ RNMapboxMapsDownloadToken?: string; RNMapboxMapsUseV11?: boolean; + /** + * Get the Mapbox Maps SDK through Swift Package Manager instead of CocoaPods on iOS. + * `true`, or the options of `$RNMapboxMapsSwiftPackageManager`, see ios/install.md. + */ + RNMapboxMapsSwiftPackageManager?: boolean | SwiftPackageManagerOptions; +}; +export type SwiftPackageManagerOptions = { + url?: string; + requirement?: { + kind: string; + version?: string; + minimumVersion?: string; + }; + product_name?: string; }; export declare const addInstallerBlock: (src: string, blockName: InstallerBlockName) => string; -export declare const addConstantBlock: (src: string, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, }: MapboxPlugProps) => string; -export declare const applyCocoaPodsModifications: (contents: string, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, }: MapboxPlugProps) => string; +export declare const addConstantBlock: (src: string, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, RNMapboxMapsSwiftPackageManager, }: MapboxPlugProps) => string; +export declare const applyCocoaPodsModifications: (contents: string, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, RNMapboxMapsSwiftPackageManager, }: MapboxPlugProps) => string; export declare const addMapboxInstallerBlock: (src: string, blockName: InstallerBlockName) => string; export declare const addMapboxMavenRepo: (src: string) => string; declare const _default: ConfigPlugin; diff --git a/plugin/build/withMapbox.js b/plugin/build/withMapbox.js index c226cec57c..5318a68bbe 100644 --- a/plugin/build/withMapbox.js +++ b/plugin/build/withMapbox.js @@ -17,6 +17,13 @@ try { catch { // empty catch block } +const toRubyLiteral = (value) => { + if (value !== null && typeof value === 'object') { + const entries = Object.entries(value).map(([key, item]) => `${key}: ${toRubyLiteral(item)}`); + return `{ ${entries.join(', ')} }`; + } + return JSON.stringify(value); +}; const addInstallerBlock = (src, blockName) => { const matchBlock = new RegExp(`${blockName}_install do \\|installer\\|`); const tag = `${blockName}_installer`; @@ -46,11 +53,12 @@ const addInstallerBlock = (src, blockName) => { }).contents; }; exports.addInstallerBlock = addInstallerBlock; -const addConstantBlock = (src, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, }) => { +const addConstantBlock = (src, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, RNMapboxMapsSwiftPackageManager, }) => { const tag = `@rnmapbox/maps-rnmapboxmapsimpl`; if (RNMapboxMapsVersion == null && RNMapboxMapsDownloadToken == null && - RNMapboxMapsUseV11 == null) { + RNMapboxMapsUseV11 == null && + !RNMapboxMapsSwiftPackageManager) { const modified = (0, generateCode_1.removeGeneratedContents)(src, tag); if (!modified) { return src; @@ -74,6 +82,9 @@ const addConstantBlock = (src, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapbox if (RNMapboxMapsUseV11) { newSrc.push(`$RNMapboxMapsUseV11 = true`); } + if (RNMapboxMapsSwiftPackageManager) { + newSrc.push(`$RNMapboxMapsSwiftPackageManager = ${toRubyLiteral(RNMapboxMapsSwiftPackageManager)}`); + } return (0, generateCode_1.mergeContents)({ tag, src, @@ -85,15 +96,14 @@ const addConstantBlock = (src, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapbox }).contents; }; exports.addConstantBlock = addConstantBlock; -// Only the preinstaller block is required, the post installer block is -// used for spm (swift package manager) which Expo doesn't currently support. -const applyCocoaPodsModifications = (contents, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, }) => { +const applyCocoaPodsModifications = (contents, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, RNMapboxMapsSwiftPackageManager, }) => { // Ensure installer blocks exist let src = (0, exports.addConstantBlock)(contents, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }); src = (0, exports.addInstallerBlock)(src, 'pre'); src = (0, exports.addInstallerBlock)(src, 'post'); @@ -117,7 +127,7 @@ exports.addMapboxInstallerBlock = addMapboxInstallerBlock; * * https://github.com/rnmapbox/maps/blob/main/ios/install.md#react-native--0600 */ -const withCocoaPodsInstallerBlocks = (config, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, } = {}) => (0, config_plugins_1.withDangerousMod)(config, [ +const withCocoaPodsInstallerBlocks = (config, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, RNMapboxMapsSwiftPackageManager, } = {}) => (0, config_plugins_1.withDangerousMod)(config, [ 'ios', async (exportedConfig) => { const file = path_1.default.join(exportedConfig.modRequest.platformProjectRoot, 'Podfile'); @@ -127,6 +137,7 @@ const withCocoaPodsInstallerBlocks = (config, { RNMapboxMapsImpl, RNMapboxMapsVe RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }), 'utf-8'); return exportedConfig; }, @@ -283,7 +294,7 @@ const withMapboxAndroid = (config, { RNMapboxMapsImpl, RNMapboxMapsDownloadToken config = withAndroidAppGradle(config, { RNMapboxMapsImpl }); return config; }; -const withMapbox = (config, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, } = {}) => { +const withMapbox = (config, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, RNMapboxMapsSwiftPackageManager, } = {}) => { config = withMapboxAndroid(config, { RNMapboxMapsImpl, RNMapboxMapsVersion, @@ -295,6 +306,7 @@ const withMapbox = (config, { RNMapboxMapsImpl, RNMapboxMapsVersion, RNMapboxMap RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }); return config; }; diff --git a/plugin/install.md b/plugin/install.md index c96b68b948..40d2957edb 100644 --- a/plugin/install.md +++ b/plugin/install.md @@ -66,6 +66,23 @@ It's possible to overwrite the native SDK version with `RNMapboxMapsVersion`: } ``` +To get the Mapbox SDK through Swift Package Manager on iOS, set `RNMapboxMapsSwiftPackageManager` to `true`, or to the options described in the [iOS guide](/ios/install.md#using-swift-package-manager-experimental): + +```json +{ + "expo": { + "plugins": [ + [ + "@rnmapbox/maps", + { + "RNMapboxMapsSwiftPackageManager": true + } + ] + ] + } +} +``` + ## Manual Setup For bare workflow projects, you can follow the manual setup guides: diff --git a/plugin/src/__tests__/withMapbox-test.ts b/plugin/src/__tests__/withMapbox-test.ts index 29adc2aea0..8a0eb0a492 100644 --- a/plugin/src/__tests__/withMapbox-test.ts +++ b/plugin/src/__tests__/withMapbox-test.ts @@ -42,6 +42,23 @@ describe('applyCocoaPodsModifications', () => { }), ).toMatchSnapshot(); }); + it('sets $RNMapboxMapsSwiftPackageManager', () => { + expect( + applyCocoaPodsModifications(iosFixtures.expoTemplatePodfile, { + RNMapboxMapsSwiftPackageManager: true, + }), + ).toContain('$RNMapboxMapsSwiftPackageManager = true\n'); + expect( + applyCocoaPodsModifications(iosFixtures.expoTemplatePodfile, { + RNMapboxMapsSwiftPackageManager: { + requirement: { kind: 'exactVersion', version: '11.23.1' }, + product_name: 'MapboxMaps', + }, + }), + ).toContain( + `$RNMapboxMapsSwiftPackageManager = { requirement: { kind: "exactVersion", version: "11.23.1" }, product_name: "MapboxMaps" }\n`, + ); + }); it('adds blocks to a expo prebuild template podfile', () => { expect( applyCocoaPodsModifications(iosFixtures.expoTemplatePodfile, {}), diff --git a/plugin/src/withMapbox.ts b/plugin/src/withMapbox.ts index f14caf61d2..6cac78a165 100644 --- a/plugin/src/withMapbox.ts +++ b/plugin/src/withMapbox.ts @@ -43,6 +43,28 @@ export type MapboxPlugProps = { RNMapboxMapsDownloadToken?: string; RNMapboxMapsUseV11?: boolean; + + /** + * Get the Mapbox Maps SDK through Swift Package Manager instead of CocoaPods on iOS. + * `true`, or the options of `$RNMapboxMapsSwiftPackageManager`, see ios/install.md. + */ + RNMapboxMapsSwiftPackageManager?: boolean | SwiftPackageManagerOptions; +}; + +export type SwiftPackageManagerOptions = { + url?: string; + requirement?: { kind: string; version?: string; minimumVersion?: string }; + product_name?: string; +}; + +const toRubyLiteral = (value: unknown): string => { + if (value !== null && typeof value === 'object') { + const entries = Object.entries(value).map( + ([key, item]) => `${key}: ${toRubyLiteral(item)}`, + ); + return `{ ${entries.join(', ')} }`; + } + return JSON.stringify(value); }; export const addInstallerBlock = ( @@ -86,6 +108,7 @@ export const addConstantBlock = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }: MapboxPlugProps, ): string => { const tag = `@rnmapbox/maps-rnmapboxmapsimpl`; @@ -93,7 +116,8 @@ export const addConstantBlock = ( if ( RNMapboxMapsVersion == null && RNMapboxMapsDownloadToken == null && - RNMapboxMapsUseV11 == null + RNMapboxMapsUseV11 == null && + !RNMapboxMapsSwiftPackageManager ) { const modified = removeGeneratedContents(src, tag); if (!modified) { @@ -128,6 +152,12 @@ export const addConstantBlock = ( newSrc.push(`$RNMapboxMapsUseV11 = true`); } + if (RNMapboxMapsSwiftPackageManager) { + newSrc.push( + `$RNMapboxMapsSwiftPackageManager = ${toRubyLiteral(RNMapboxMapsSwiftPackageManager)}`, + ); + } + return mergeContents({ tag, src, @@ -139,8 +169,6 @@ export const addConstantBlock = ( }).contents; }; -// Only the preinstaller block is required, the post installer block is -// used for spm (swift package manager) which Expo doesn't currently support. export const applyCocoaPodsModifications = ( contents: string, { @@ -148,6 +176,7 @@ export const applyCocoaPodsModifications = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }: MapboxPlugProps, ): string => { // Ensure installer blocks exist @@ -156,6 +185,7 @@ export const applyCocoaPodsModifications = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }); src = addInstallerBlock(src, 'pre'); src = addInstallerBlock(src, 'post'); @@ -191,6 +221,7 @@ const withCocoaPodsInstallerBlocks: ConfigPlugin = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }: MapboxPlugProps = {}, ) => withDangerousMod(config, [ @@ -209,6 +240,7 @@ const withCocoaPodsInstallerBlocks: ConfigPlugin = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }), 'utf-8', ); @@ -464,6 +496,7 @@ const withMapbox: ConfigPlugin = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }: MapboxPlugProps = {}, ) => { config = withMapboxAndroid(config, { @@ -477,6 +510,7 @@ const withMapbox: ConfigPlugin = ( RNMapboxMapsVersion, RNMapboxMapsDownloadToken, RNMapboxMapsUseV11, + RNMapboxMapsSwiftPackageManager, }); return config; diff --git a/rnmapbox-maps.podspec b/rnmapbox-maps.podspec index 78bc391484..209d640528 100644 --- a/rnmapbox-maps.podspec +++ b/rnmapbox-maps.podspec @@ -2,14 +2,16 @@ # $RNMapboxMapsVersion - version specification ("~> 10.4.3", "~> 5.9.0" or "exactVersion 5.12.1" mapblibre/SPM) # $RNMapboxMapsSwiftPackageManager can be either # "manual" - you're responsible for the Mapbox lib dependency either using cocoapods or SPM -# Hash - ``` +# true - get MapboxMaps from https://github.com/mapbox/mapbox-maps-ios.git through Swift Package Manager, +# with the requirement derived from $RNMapboxMapsVersion +# Hash - same as true, with any of these keys overridden: ``` # { -# url: "https://github.com/maplibre/maplibre-gl-native-distribution", +# url: "https://github.com/mapbox/mapbox-maps-ios.git", # requirement: { # kind: 'exactVersion', -# version: 5.12.1, +# version: '11.23.1', # }, -# product_name: "Mapbox" +# product_name: "MapboxMaps", # } # ``` # $RNMapboxMapsDownloadToken - *deprecated* download token is no longer required @@ -114,22 +116,44 @@ def $RNMapboxMaps._check_no_mapbox_spm(project) end end -def $RNMapboxMaps._add_spm_to_target(project, target, url, requirement, product_name) - pkg_class = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference - ref_class = Xcodeproj::Project::Object::XCSwiftPackageProductDependency - pkg = project.root_object.package_references.find { |p| p.class == pkg_class && p.repositoryURL == url } - if !pkg - pkg = project.new(pkg_class) - pkg.repositoryURL = url - pkg.requirement = requirement - project.root_object.package_references << pkg +def $RNMapboxMaps._spm_requirement(version) + case version.strip + when /\A~>\s*(\d+\.\d+\.\d+)\z/ then { kind: 'upToNextMinorVersion', minimumVersion: $1 } + when /\A~>\s*(\d+\.\d+)\z/ then { kind: 'upToNextMajorVersion', minimumVersion: "#{$1}.0" } + when /\A=?\s*(\d+\.\d+\.\d+)\z/ then { kind: 'exactVersion', version: $1 } + else + raise "[RNMapbox] Can't turn $RNMapboxMapsVersion '#{version}' into a Swift package requirement, " \ + "set `requirement:` in $RNMapboxMapsSwiftPackageManager" end - ref = target.package_product_dependencies.find { |r| r.class == ref_class && r.package == pkg && r.product_name == product_name } - if !ref - ref = project.new(ref_class) - ref.package = pkg - ref.product_name = product_name - target.package_product_dependencies << ref +end + +def $RNMapboxMaps._spm_spec + return nil if !$RNMapboxMapsSwiftPackageManager || $RNMapboxMapsSwiftPackageManager == "manual" + options = $RNMapboxMapsSwiftPackageManager == true ? {} : $RNMapboxMapsSwiftPackageManager + { + url: 'https://github.com/mapbox/mapbox-maps-ios.git', + product_name: 'MapboxMaps' + }.merge(options).tap { |spec| spec[:requirement] ||= self._spm_requirement($MapboxImplVersion) } +end + +# @rnmapbox/maps 10.3.8 and earlier also added the package product to the app targets, which now links a second +# copy next to the pod's and embeds its frameworks twice ("Multiple commands produce"). +def $RNMapboxMaps._remove_spm_from_app_targets(installer, url) + installer.aggregate_targets.group_by(&:user_project).each do |project, targets| + targets.flat_map(&:user_targets).uniq.each do |target| + stale = target.package_product_dependencies.select { |r| r.package.respond_to?(:repositoryURL) && r.package.repositoryURL == url } + next if stale.empty? + Pod::UI.warn "[RNMapbox] Removing #{stale.map(&:product_name).join(', ')} (#{url}) from #{target.name}, it is linked through the pods" + stale.each do |ref| + target.frameworks_build_phase.files.select { |f| f.product_ref == ref }.each(&:remove_from_project) + target.package_product_dependencies.delete(ref) + ref.remove_from_project + end + end + project.root_object.package_references.select { |p| p.respond_to?(:repositoryURL) && p.repositoryURL == url }.each do |pkg| + in_use = project.targets.any? { |t| t.package_product_dependencies.any? { |r| r.package == pkg } } + pkg.remove_from_project unless in_use + end end end @@ -159,33 +183,10 @@ def $RNMapboxMaps.post_install(installer) end end - if $RNMapboxMapsSwiftPackageManager - return if $RNMapboxMapsSwiftPackageManager == "manual" - - spm_spec = $RNMapboxMapsSwiftPackageManager - project = installer.pods_project - self._add_spm_to_target( - project, - project.targets.find { |t| t.name == "rnmapbox-maps"}, - spm_spec[:url], - spm_spec[:requirement], - spm_spec[:product_name] - ) + spm_spec = self._spm_spec + self._remove_spm_from_app_targets(installer, spm_spec[:url]) if spm_spec - installer.aggregate_targets.group_by(&:user_project).each do |project, targets| - targets.each do |target| - target.user_targets.each do |user_target| - self._add_spm_to_target( - project, - user_target, - spm_spec[:url], - spm_spec[:requirement], - spm_spec[:product_name] - ) - end - end - end - else + if !$RNMapboxMapsSwiftPackageManager self._check_no_mapbox_spm(installer.pods_project) installer.aggregate_targets.group_by(&:user_project).each do |project, targets| targets.each do |target| @@ -197,6 +198,12 @@ def $RNMapboxMaps.post_install(installer) end end +rnMapboxMapsSPMSpec = $RNMapboxMaps._spm_spec + +if rnMapboxMapsSPMSpec + require_relative 'ios/rnmapbox_spm' +end + $rnMapboxMapsTargetsToChangeToDynamic = rnMapboxMapsTargetsToChangeToDynamic def $RNMapboxMaps._expo_precompiled_pipeline? @@ -263,6 +270,18 @@ Pod::Spec.new do |s| end s.header_dir = "rnmapbox_maps" + if rnMapboxMapsSPMSpec + spm_frameworks = ['MapboxCommon', 'MapboxCoreMaps', 'Turf'] + spm_dependency(s, + url: rnMapboxMapsSPMSpec[:url], + requirement: rnMapboxMapsSPMSpec[:requirement], + products: [rnMapboxMapsSPMSpec[:product_name]], + **RNMapboxSPM.spm_dependency_options(s.name, spm_frameworks) + ) + RNMapboxSPM.embed_frameworks(s.name, spm_frameworks) + s.script_phase = RNMapboxSPM.signature_cleanup_script_phase(s.name) + end + unless $RNMapboxMapsSwiftPackageManager if $RNMapboxMapsCustomPods $RNMapboxMapsCustomPods.each do |dependecy_spec|