diff --git a/packages/react-native/scripts/cocoapods/rncore.rb b/packages/react-native/scripts/cocoapods/rncore.rb
index 7108f147cf1ddb..71930859197fa2 100644
--- a/packages/react-native/scripts/cocoapods/rncore.rb
+++ b/packages/react-native/scripts/cocoapods/rncore.rb
@@ -66,7 +66,6 @@ def self.setup_rncore(react_native_path, react_native_version)
rncore_log("No prebuilt artifacts found, reverting to building from source.")
end
rncore_log("Building from source: #{@@build_from_source}")
- rncore_log("Source: #{self.resolve_podspec_source()}")
end
end
@@ -89,7 +88,6 @@ def self.resolve_podspec_source()
if ENV["RCT_USE_PREBUILT_RNCORE"] == "1"
if @@use_nightly
- rncore_log("Using nightly tarball")
begin
return self.podspec_source_download_prebuilt_nightly_tarball(@@react_native_version)
rescue => e
@@ -122,7 +120,6 @@ def self.podspec_source_download_prebuild_stable_tarball()
if @@build_from_source
return
end
-
url = stable_tarball_url(@@react_native_version, :debug)
rncore_log("Using tarball from URL: #{url}")
download_stable_rncore(@@react_native_path, @@react_native_version, :debug)
@@ -130,6 +127,154 @@ def self.podspec_source_download_prebuild_stable_tarball()
return {:http => url}
end
+ def self.process_dsyms(frameworkTarball, dSymsTarball)
+ if !@@download_dsyms
+ return
+ end
+
+ if @@react_native_path == ""
+ rncore_log("react_native_path is not set", :error)
+ return
+ end
+
+ if @@react_native_version == ""
+ rncore_log("react_native_version is not set", :error)
+ return
+ end
+
+ if @@build_from_source
+ return
+ end
+
+ # gunzip the dSymsTarball and the frameworkTarball into a temporary folder
+ # and then copy the dSYMs into the framework folder and then tar/gz the framework folder again
+ # into the same location as the original frameworkTarball
+
+ rncore_log("Adding symbols #{Pathname.new(dSymsTarball).relative_path_from(Pathname.pwd).to_s} to framework tarball #{Pathname.new(frameworkTarball).relative_path_from(Pathname.pwd).to_s}")
+
+ FileUtils.mkdir_p(File.dirname(frameworkTarball))
+ FileUtils.cp(frameworkTarball, "#{frameworkTarball}.orig")
+
+ rncore_log(" Backed up original tarballs")
+
+ begin
+ # Now let's gunzip the framework tarball into a .tar file
+ # Get filename and foldername from the tarball path
+ frameworkFolder = File.dirname(frameworkTarball)
+ frameworkFilename = File.basename(frameworkTarball, ".tar.gz")
+ frameworkTarPath = File.join(frameworkFolder, frameworkFilename + ".tar")
+
+ # Now gunzip the tarball into the frameworkFolder - this will remove the .gz file and leave us with a .tar file
+ rncore_log(" Unpacking framework tarball")
+ `gunzip "#{frameworkTarball}"`
+
+ # Now let's untar the dSyms tarball into a temporary folder / dSYMs subfolder
+ dsyms_tmp_dir = "#{artifacts_dir}/dSYMs"
+ rncore_log(" Unpacking dSYMs to temporary folder")
+ `mkdir -p "#{dsyms_tmp_dir}" && tar -xzf "#{dSymsTarball}" -C "#{dsyms_tmp_dir}"`
+
+ # Now we need to remap the symbol files to be relative to the framework folder
+ remap_sourcemaps_for_symbols(dsyms_tmp_dir)
+
+ # Add the dSYMs folder to the framework folder
+ rncore_log(" Adding dSYMs to framework tarball")
+ `(cd "$(dirname "#{dsyms_tmp_dir}")" && mkdir -p React.xcframework && cp -r "$(basename "#{dsyms_tmp_dir}")" React.xcframework/dSYMs && tar -rf "#{frameworkTarPath}" React.xcframework/dSYMs && rm -rf React.xcframework)`
+
+ # Now gzip the framework tarball again - remember to use the .tar file and not the .gz file
+ rncore_log(" Packing #{Pathname.new(frameworkTarPath).relative_path_from(Pathname.pwd).to_s}")
+ `gzip -1 "#{frameworkTarPath}"`
+
+ # Clean up the temporary folder
+ FileUtils.remove_entry(dsyms_tmp_dir)
+ rncore_log(" Processed dSYMs into framework tarball #{Pathname.new(frameworkTarball).relative_path_from(Pathname.pwd).to_s}")
+
+ # Remove backup of original tarballs
+ FileUtils.rm_f("#{frameworkTarball}.orig")
+
+ rescue => e
+ rncore_log("Failed to process dSYMs: #{e.message}", :error)
+ # Restore the original tarballs
+ FileUtils.mv("#{frameworkTarball}.orig", frameworkTarball) if File.exist?("#{frameworkTarball}.orig")
+ rncore_log("Restored original tarballs", :error)
+ abort "Couldn't process dSYMs: #{e.message}"
+ end
+ end
+
+ def self.remap_sourcemaps_for_symbols(symbolsPath)
+ rncore_log(" Remapping dSYMs to be relative to framework folder")
+
+ # Find all .dSYM bundles in the symbols path
+ dsym_bundles = []
+ Dir.glob(File.join(symbolsPath, "**", "*.dSYM")).each do |path|
+ if File.directory?(path)
+ # Check if it's a valid dSYM bundle with Info.plist
+ info_plist = File.join(path, 'Contents', 'Info.plist')
+ dsym_bundles << path if File.exist?(info_plist)
+ end
+ end
+
+ return if dsym_bundles.empty?
+
+ # Define source path mappings - from absolute build paths to relative framework paths
+ mappings = [
+ # Make sure to make react_native_path absolute
+ ["/Users/runner/work/react-native/react-native/packages/react-native", "#{File.expand_path(@@react_native_path)}"],
+ ]
+
+ dsym_bundles.each do |dsym_path| begin
+ # Get UUIDs for this dSYM bundle
+ uuid_output = `dwarfdump --uuid "#{dsym_path}" 2>/dev/null`
+ uuids = uuid_output.scan(/UUID:\s+([0-9A-F-]{36})/i).flatten
+
+ next if uuids.empty?
+
+ # Create Resources directory if it doesn't exist
+ resources_dir = File.join(dsym_path, 'Contents', 'Resources')
+ FileUtils.mkdir_p(resources_dir)
+
+ # Generate plist content with path mappings
+ plist_content = generate_plist_content(mappings)
+
+ # Write plist for each UUID
+ uuids.each do |uuid|
+ plist_path = File.join(resources_dir, "#{uuid}.plist")
+ File.write(plist_path, plist_content)
+ end
+
+ rescue => e
+ rncore_log(" Failed to process dSYM #{dsym_path}: #{e.message}", :error)
+ end
+ end
+
+ rncore_log(" Completed dSYM remapping for #{dsym_bundles.length} bundles")
+ end
+
+ def self.generate_plist_content(mappings)
+ # Generate the source path remapping entries
+ remapping_entries = mappings.map do |from, to|
+ " #{from}#{to}"
+ end.join("\n")
+
+ # Use the first mapping for legacy keys
+ first_from, first_to = mappings.first
+
+ return <<~PLIST
+
+
+
+
+ DBGVersion3
+ DBGBuildSourcePath#{first_from}
+ DBGSourcePath#{first_to}
+ DBGSourcePathRemapping
+
+ #{remapping_entries}
+
+
+
+ PLIST
+ end
+
def self.stable_tarball_url(version, build_type)
## You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded.
## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central.
@@ -210,14 +355,14 @@ def self.rncore_log(message, level = :info)
if !Object.const_defined?("Pod::UI")
return
end
- log_message = '[ReactNativeCore] ' + message
+ log_message = '[ReactNativeCore] '
case level
when :info
- Pod::UI.puts log_message.green
+ Pod::UI.puts log_message.green + message
when :error
- Pod::UI.puts log_message.red
+ Pod::UI.puts log_message.red + message
else
- Pod::UI.puts log_message.yellow
+ Pod::UI.puts log_message.yellow + message
end
end
diff --git a/packages/react-native/scripts/cocoapods/rndependencies.rb b/packages/react-native/scripts/cocoapods/rndependencies.rb
index 2717ab09e6b7a8..33a13c96f4f983 100644
--- a/packages/react-native/scripts/cocoapods/rndependencies.rb
+++ b/packages/react-native/scripts/cocoapods/rndependencies.rb
@@ -75,7 +75,6 @@ def self.resolve_podspec_source()
if ENV["RCT_USE_RN_DEP"] && ENV["RCT_USE_RN_DEP"] == "1"
if @@use_nightly
- rndeps_log("Using nightly tarball")
begin
return self.podspec_source_download_prebuilt_nightly_tarball(@@react_native_version)
rescue => e
@@ -84,7 +83,6 @@ def self.resolve_podspec_source()
end
end
- rndeps_log("Using release tarball")
begin
return self.podspec_source_download_prebuild_release_tarball()
rescue => e
@@ -160,9 +158,10 @@ def self.podspec_source_download_prebuild_release_tarball()
url = release_tarball_url(@@react_native_version, :debug)
rndeps_log("Using tarball from URL: #{url}")
- download_stable_rndeps(@@react_native_path, @@react_native_version, :debug)
+ destinationDebug = download_stable_rndeps(@@react_native_path, @@react_native_version, :debug)
download_stable_rndeps(@@react_native_path, @@react_native_version, :release)
- return {:http => url}
+
+ return {:http => URI::File.build(path: destinationDebug).to_s }
end
def self.release_tarball_url(version, build_type)
@@ -204,7 +203,6 @@ def self.download_stable_rndeps(react_native_path, version, configuration)
def self.podspec_source_download_prebuilt_nightly_tarball(version)
url = nightly_tarball_url(version)
- rndeps_log("Using nightly tarball from URL: #{url}")
return {:http => url}
end
@@ -245,14 +243,13 @@ def self.rndeps_log(message, level = :info)
if !Object.const_defined?("Pod::UI")
return
end
- log_message = '[ReactNativeDependencies] ' + message
case level
when :info
- Pod::UI.puts log_message.green
+ Pod::UI.puts '[ReactNativeDependencies] '.green + message
when :error
- Pod::UI.puts log_message.red
+ Pod::UI.puts '[ReactNativeDependencies] '.red + message
else
- Pod::UI.puts log_message.yellow
+ Pod::UI.puts '[ReactNativeDependencies] '.yellow + message
end
end