Skip to content

[IOS][FIXED] - Keep the quotes on header search paths - #57981

Open
Kudo wants to merge 2 commits into
react:mainfrom
Kudo:kudo/fix-swift-header-import
Open

[IOS][FIXED] - Keep the quotes on header search paths#57981
Kudo wants to merge 2 commits into
react:mainfrom
Kudo:kudo/fix-swift-header-import

Conversation

@Kudo

@Kudo Kudo commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary:

a regression from a8156ac and breaks react-native nightly build at expo: https://github.com/expo/expo/actions/runs/31990917142/job/95274214849

the shellsplit will stripe quotes and break paths with spaces like Swift Compatibility Header. this pr tries to re-quote.

here's small demo script

require 'shellwords'

# What main does today: shellsplit the existing value, append, write it back.
def main_behaviour(existing, add)
  paths = existing || []
  paths = Shellwords.shellsplit(paths) if paths.is_a?(String)
  (paths + add).uniq
end

# What this PR does: quote only the paths we add, never touch what is there.
def this_pr(existing, add)
  quoted = add.map { |path| "\"#{path}\"" }
  case existing
  when nil
    quoted
  when Array
    existing + quoted.reject { |path| existing.include?(path) }
  else
    ([existing] + quoted.reject { |path| existing.include?(path) }).join(" ")
  end
end

# Xcode joins an Array setting with spaces, then splits it on whitespace while
# honouring quotes. This is what the compiler ends up with.
def as_xcode_reads_it(value)
  Shellwords.shellsplit(value.is_a?(Array) ? value.join(" ") : value)
end

ADD = ['$(PODS_ROOT)/ReactNativeDependencies/Headers']

# A pod that exports a Swift compatibility header. The directory name has
# spaces, so the podspec quotes it. Podspecs write this as a String or as an
# Array, and both forms reach add_rn_third_party_dependencies.
SWIFT_HEADER = '${PODS_CONFIGURATION_BUILD_DIR}/MyPod/Swift Compatibility Header'

CASES = {
  'String' => "\"$(PODS_ROOT)/DoubleConversion\" \"#{SWIFT_HEADER}\"",
  'Array'  => ['"$(PODS_ROOT)/DoubleConversion"', "\"#{SWIFT_HEADER}\""],
}

CASES.each do |label, existing|
  puts "#{label} HEADER_SEARCH_PATHS"
  { 'main' => method(:main_behaviour), 'this PR' => method(:this_pr) }.each do |name, fn|
    paths = as_xcode_reads_it(fn.call(existing, ADD))
    verdict = paths.include?(SWIFT_HEADER) ? 'ok' : 'BROKEN'
    puts "  #{name.ljust(7)} -> #{paths.size} paths, #{verdict}: #{paths.inspect}"
  end
  puts
end

output

String HEADER_SEARCH_PATHS
  main    -> 5 paths, BROKEN: ["$(PODS_ROOT)/DoubleConversion", "${PODS_CONFIGURATION_BUILD_DIR}/MyPod/Swift", "Compatibility", "Header", "$(PODS_ROOT)/ReactNativeDependencies/Headers"]
  this PR -> 3 paths, ok: ["$(PODS_ROOT)/DoubleConversion", "${PODS_CONFIGURATION_BUILD_DIR}/MyPod/Swift Compatibility Header", "$(PODS_ROOT)/ReactNativeDependencies/Headers"]

Array HEADER_SEARCH_PATHS
  main    -> 3 paths, ok: ["$(PODS_ROOT)/DoubleConversion", "${PODS_CONFIGURATION_BUILD_DIR}/MyPod/Swift Compatibility Header", "$(PODS_ROOT)/ReactNativeDependencies/Headers"]
  this PR -> 3 paths, ok: ["$(PODS_ROOT)/DoubleConversion", "${PODS_CONFIGURATION_BUILD_DIR}/MyPod/Swift Compatibility Header", "$(PODS_ROOT)/ReactNativeDependencies/Headers"]

Changelog:

[IOS][FIXED] - Keep the quotes on header search paths containing spaces in add_rn_third_party_dependencies

Test Plan:

apply the patch on create-expo-nightly and the ios build should pass expo/expo#49023

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 17, 2026
@facebook-github-tools facebook-github-tools Bot added Contributor A React Native contributor. p: Expo Partner: Expo Partner labels Aug 17, 2026
@Kudo
Kudo marked this pull request as ready for review August 17, 2026 19:07
@Kudo

Kudo commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

@chrfalch @cipolleschi a fix toward the shellsplit breaking change. not sure if there's a better fix though

@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Aug 17, 2026

@chrfalch chrfalch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @Kudo!

It fixes string values, but there is a slight problem with the fix that will cause Array xcconfigs to fail (it previously worked).

What about just removing shellsplit since we're really just appending - and wrap this in a simpler function on the class itself:

def self.append_header_search_paths(xcconfig, paths)
  add = paths.map { |p| "\"#{p}\"" }
  existing = xcconfig["HEADER_SEARCH_PATHS"]
  fresh = ->(cur) { add.reject { |q| cur.include?(q) } }
  case existing
  when nil   then xcconfig["HEADER_SEARCH_PATHS"] = add
  when Array then xcconfig["HEADER_SEARCH_PATHS"] = existing + fresh.(existing)
  else            xcconfig["HEADER_SEARCH_PATHS"] = ([existing] + fresh.(existing)).join(" ")
  end
end

And then use this function when setting HEADER_SEARCH_PATHS?

Shellsplit dropped the quotes an Array xcconfig already carried, so
re-quoting every entry double-quoted the ones with spaces. Only quote
the paths we add, and leave the podspec's own entries alone.
@Kudo
Kudo requested a review from chrfalch August 18, 2026 13:28

@chrfalch chrfalch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thanks!!

@meta-codesync

meta-codesync Bot commented Aug 19, 2026

Copy link
Copy Markdown

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D116600347.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants