Skip to content

Commit e99cf68

Browse files
authored
refactor(apple): move host and autolinking resolution to JS (#2428)
1 parent 3fca9c7 commit e99cf68

File tree

7 files changed

+162
-98
lines changed

7 files changed

+162
-98
lines changed

ios/app.mjs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
isMain,
99
readTextFile,
1010
toVersionNumber,
11+
v,
1112
} from "../scripts/helpers.js";
1213
import { cp_r, mkdir_p, rm_r } from "../scripts/utils/filesystem.mjs";
1314
import { generateAssetsCatalogs } from "./assetsCatalog.mjs";
@@ -16,7 +17,7 @@ import { generateInfoPlist } from "./infoPlist.mjs";
1617
import { generateLocalizations, getProductName } from "./localizations.mjs";
1718
import { isBridgelessEnabled, isNewArchEnabled } from "./newArch.mjs";
1819
import { generatePrivacyManifest } from "./privacyManifest.mjs";
19-
import { isObject, isString, projectPath } from "./utils.mjs";
20+
import { isObject, isString, projectPath, resolveResources } from "./utils.mjs";
2021
import {
2122
PRODUCT_DISPLAY_NAME,
2223
PRODUCT_VERSION,
@@ -66,6 +67,45 @@ function exportNodeBinaryPath(projectRoot, destination, fs = nodefs) {
6667
);
6768
}
6869

70+
/**
71+
* @param {string} reactNativePath
72+
* @param {number} reactNativeVersion
73+
* @returns {string | undefined}
74+
*/
75+
function findCommunityAutolinkingScriptPath(
76+
reactNativePath,
77+
reactNativeVersion,
78+
fs = nodefs
79+
) {
80+
// As of 0.75, we should use `use_native_modules!` from `react-native` instead
81+
if (reactNativeVersion < v(0, 75, 0)) {
82+
const pkgPath = findFile(
83+
"node_modules/@react-native-community/cli-platform-ios",
84+
reactNativePath,
85+
fs
86+
);
87+
if (pkgPath) {
88+
return path.join(pkgPath, "native_modules.rb");
89+
}
90+
}
91+
92+
return undefined;
93+
}
94+
95+
/**
96+
* @param {string} projectRoot
97+
* @returns {string}
98+
*/
99+
function findReactNativeHostPath(projectRoot, fs = nodefs) {
100+
const dir = fileURLToPath(import.meta.url);
101+
const rnhPath = findFile("node_modules/@rnx-kit/react-native-host", dir, fs);
102+
if (!rnhPath) {
103+
throw new Error("Cannot find module '@rnx-kit/react-native-host'");
104+
}
105+
106+
return path.relative(projectRoot, rnhPath);
107+
}
108+
69109
/**
70110
* @param {JSONValue} platformConfig
71111
* @param {string} projectRoot
@@ -188,11 +228,20 @@ export function generateProject(
188228
xcodeprojPath: path.resolve(xcodeprojDst),
189229
reactNativePath: path.resolve(reactNativePath),
190230
reactNativeVersion,
231+
reactNativeHostPath: findReactNativeHostPath(projectRoot, fs),
232+
communityAutolinkingScriptPath: findCommunityAutolinkingScriptPath(
233+
reactNativePath,
234+
reactNativeVersion,
235+
fs
236+
),
191237
useNewArch,
192238
useBridgeless,
193239
buildSettings: {},
194240
testsBuildSettings: {},
195241
uitestsBuildSettings: {},
242+
resources: resolveResources(appConfig, targetPlatform)?.filter(
243+
(item) => typeof item === "string"
244+
),
196245
};
197246

198247
applyBuildSettings(platformConfig, project, projectRoot, destination, fs);

ios/pod_helpers.rb

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
11
require('json')
22

3-
def app_manifest(project_root)
4-
@app_manifest ||= {}
5-
return @app_manifest[project_root] if @app_manifest.key?(project_root)
6-
7-
manifest_path = find_file('app.json', project_root)
8-
return if manifest_path.nil?
9-
10-
@app_manifest[project_root] = JSON.parse(File.read(manifest_path))
11-
end
12-
133
def assert(condition, message)
144
raise message unless condition
155
end
@@ -50,41 +40,10 @@ def new_architecture_enabled?(options, react_native_version)
5040
ENV.fetch('RCT_NEW_ARCH_ENABLED', options[:fabric_enabled] ? '1' : '0') != '0'
5141
end
5242

53-
def resolve_module(request, start_dir = Pod::Config.instance.installation_root)
54-
@module_cache ||= {}
55-
return @module_cache[request] if @module_cache.key?(request)
56-
57-
@module_cache[request] = resolve_module_uncached(request, start_dir).to_s
58-
end
59-
60-
def resolve_module_relative(request)
61-
path = resolve_module_uncached(request, Pathname.new(__dir__))
62-
path.relative_path_from(Pod::Config.instance.installation_root).to_s
63-
end
64-
65-
def resolve_module_uncached(request, start_dir)
66-
# Always resolve `start_dir` as it may be a symlink
67-
package_json = find_file("node_modules/#{request}/package.json", start_dir.realdirpath)
68-
raise "Cannot find module '#{request}'" if package_json.nil?
69-
70-
package_json.dirname
71-
end
72-
73-
def resolve_resources(manifest, target_platform)
74-
resources = manifest['resources']
75-
return if !resources || resources.empty?
76-
77-
resources.instance_of?(Array) ? resources : resources[target_platform.to_s]
78-
end
79-
8043
def supports_new_architecture?(react_native_version)
8144
react_native_version.zero? || react_native_version >= v(0, 71, 0)
8245
end
8346

84-
def try_pod(name, podspec, project_root)
85-
pod name, :podspec => podspec if File.exist?(File.join(project_root, podspec))
86-
end
87-
8847
def use_hermes?(options)
8948
use_hermes = ENV.fetch('USE_HERMES', nil)
9049
return use_hermes == '1' unless use_hermes.nil?

ios/test_app.rb

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,15 @@
1414
WARNING_CFLAGS = 'WARNING_CFLAGS'.freeze
1515

1616
def apply_config_plugins(project_root, target_platform)
17-
begin
18-
resolve_module('@expo/config-plugins')
19-
rescue StandardError
20-
# Skip if `@expo/config-plugins` cannot be found
21-
return
22-
end
17+
# Skip if `@expo/config-plugins` cannot be found
18+
config_plugins_dir = find_file('node_modules/@expo/config-plugins', project_root)
19+
return if config_plugins_dir.nil?
2320

2421
apply_config_plugins = File.join(__dir__, '..', 'scripts', 'apply-config-plugins.mjs')
2522
result = system("node \"#{apply_config_plugins}\" \"#{project_root}\" --#{target_platform}")
2623
raise 'Failed to apply config plugins' unless result
2724
end
2825

29-
def autolink_script_path(project_root, react_native_path, react_native_version)
30-
start_dir = if react_native_version >= v(0, 76, 0)
31-
project_root
32-
else
33-
react_native_path
34-
end
35-
package_path = resolve_module('@react-native-community/cli-platform-ios', start_dir)
36-
File.join(package_path, 'native_modules')
37-
end
38-
3926
def target_product_type(target)
4027
target.product_type if target.respond_to?(:product_type)
4128
end
@@ -79,13 +66,13 @@ def validate_resources(resources, app_dir)
7966
resources
8067
end
8168

82-
def resources_pod(project_root, target_platform, platforms)
69+
def resources_pod(project_root, platforms, resources)
70+
return if resources.nil? || resources.empty?
71+
8372
app_manifest = find_file('app.json', project_root)
8473
return if app_manifest.nil?
8574

8675
app_dir = File.dirname(app_manifest)
87-
resources = resolve_resources(app_manifest(project_root), target_platform)
88-
return if resources.nil? || resources.empty?
8976

9077
spec = {
9178
'name' => 'ReactTestApp-Resources',
@@ -175,9 +162,12 @@ def make_project!(project_root, target_platform, options)
175162
},
176163
:react_native_path => project['reactNativePath'],
177164
:react_native_version => project['reactNativeVersion'],
165+
:react_native_host_path => project['reactNativeHostPath'],
166+
:community_autolinking_script_path => project['communityAutolinkingScriptPath'],
178167
:use_new_arch => project['useNewArch'],
179168
:code_sign_identity => build_settings[CODE_SIGN_IDENTITY] || '',
180169
:development_team => build_settings[DEVELOPMENT_TEAM] || '',
170+
:resources => project['resources'],
181171
}
182172
end
183173

@@ -198,8 +188,8 @@ def use_test_app_internal!(target_platform, options)
198188
end
199189

200190
# As of 0.75, we should use `use_native_modules!` from `react-native` instead
201-
if react_native_version < v(0, 75, 0)
202-
require_relative(autolink_script_path(project_root, react_native_path, react_native_version))
191+
if project_target[:community_autolinking_script_path].is_a? String
192+
require_relative(project_target[:community_autolinking_script_path])
203193
end
204194

205195
begin
@@ -220,9 +210,9 @@ def use_test_app_internal!(target_platform, options)
220210
react_native_version,
221211
options)
222212

223-
pod 'ReactNativeHost', :path => resolve_module_relative('@rnx-kit/react-native-host')
213+
pod 'ReactNativeHost', :path => project_target[:react_native_host_path]
224214

225-
if (resources_pod_path = resources_pod(project_root, target_platform, platforms))
215+
if (resources_pod_path = resources_pod(project_root, platforms, project_target[:resources]))
226216
pod 'ReactTestApp-Resources', :path => resources_pod_path
227217
end
228218

scripts/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,15 @@ export type ProjectConfiguration = {
136136
xcodeprojPath: string;
137137
reactNativePath: string;
138138
reactNativeVersion: number;
139+
reactNativeHostPath: string;
140+
communityAutolinkingScriptPath?: string;
139141
singleApp?: string;
140142
useNewArch: boolean;
141143
useBridgeless: boolean;
142144
buildSettings: Record<string, string | string[]>;
143145
testsBuildSettings: Record<string, string>;
144146
uitestsBuildSettings: Record<string, string>;
147+
resources?: string[];
145148
};
146149

147150
export type XmlOptions = Pick<

0 commit comments

Comments
 (0)