Skip to content

Commit 6f6567f

Browse files
committed
Look for magic file in xcframework instead of of node-api.xcframework
1 parent 2388b41 commit 6f6567f

File tree

3 files changed

+80
-31
lines changed

3 files changed

+80
-31
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include/
22
hermes/
3+
vendored-xcframeworks/
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
def find_node_api_xcframeworks(podfile_path, podspec_path)
2-
output = `npx react-native-node-api-modules print-xcframework-paths #{podfile_path}`
2+
real_podspec_path = Pathname.new(podspec_path).realpath
3+
output = `npx react-native-node-api-modules link-xcframework-paths #{podfile_path}`
34
paths = JSON.parse(output)
45

56
unless paths.is_a?(Array)
67
raise "Expected a list of paths"
78
end
89

9-
paths.map { |path| Pathname.new(path).relative_path_from(Pathname.new(podspec_path)).to_s }
10+
paths.map { |path| Pathname.new(path).relative_path_from(real_podspec_path).to_s }
1011
end

packages/react-native-node-api-modules/src/cli/index.ts

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import { createRequire } from "node:module";
55

66
import { Command } from "@commander-js/extra-typings";
77

8-
const XCFRAMEWORK_NAME = "node-api.xcframework";
8+
// Must be in all xcframeworks to be considered as Node-API modules
9+
const MAGIC_FILENAME = "react-native-node-api-module";
910

1011
/**
1112
* Search upwards from a directory to find a package.json and
1213
* return a list of the resolved paths of all dependencies of that package.
1314
*/
14-
export function findPackageDependencyPaths(from: string): string[] {
15+
export function findPackageDependencyPaths(
16+
from: string
17+
): Record<string, string> {
1518
const candidatePath = path.join(from, "package.json");
1619
const parentDir = path.dirname(from);
1720
if (fs.existsSync(candidatePath)) {
@@ -28,19 +31,22 @@ export function findPackageDependencyPaths(from: string): string[] {
2831
typeof json.dependencies === "object" &&
2932
json.dependencies !== null
3033
) {
31-
return Object.keys(json.dependencies)
32-
.map((dependencyName) => {
33-
try {
34-
return path.dirname(
35-
require.resolve(`${dependencyName}/package.json`)
36-
);
37-
} catch {
38-
return undefined;
39-
}
40-
})
41-
.filter((p) => typeof p === "string");
34+
return Object.fromEntries(
35+
Object.keys(json.dependencies)
36+
.map((dependencyName) => {
37+
try {
38+
return [
39+
dependencyName,
40+
path.dirname(require.resolve(`${dependencyName}/package.json`)),
41+
];
42+
} catch {
43+
return undefined;
44+
}
45+
})
46+
.filter((item) => typeof item !== "undefined")
47+
);
4248
} else {
43-
return [];
49+
return {};
4450
}
4551
} else if (parentDir === from) {
4652
throw new Error("package.json not found in any parent directory");
@@ -53,32 +59,73 @@ export function findXCFrameworkPaths(dependencyPath: string): string[] {
5359
return fs
5460
.readdirSync(dependencyPath, { withFileTypes: true })
5561
.flatMap((file) => {
56-
if (file.isDirectory()) {
57-
if (file.name === XCFRAMEWORK_NAME) {
58-
return [path.join(dependencyPath, file.name)];
59-
} else {
60-
// Traverse into the child directory
61-
return findXCFrameworkPaths(path.join(dependencyPath, file.name));
62-
}
63-
} else {
64-
return [];
62+
if (
63+
file.isFile() &&
64+
file.name === MAGIC_FILENAME &&
65+
path.extname(dependencyPath) === ".xcframework"
66+
) {
67+
return [dependencyPath];
68+
} else if (file.isDirectory()) {
69+
// Traverse into the child directory
70+
return findXCFrameworkPaths(path.join(dependencyPath, file.name));
6571
}
72+
return [];
6673
});
6774
}
6875

6976
export const program = new Command("react-native-node-api-modules");
7077

7178
program
72-
.command("print-xcframework-paths")
79+
.command("link-xcframework-paths")
7380
.argument("<installation-root>", "Parent directory of the Podfile", (p) =>
7481
path.resolve(process.cwd(), p)
7582
)
7683
.action((installationRoot: string) => {
77-
// Find the package.json of the app
78-
const dependencyPaths = findPackageDependencyPaths(installationRoot);
79-
const xcframeworkPaths = dependencyPaths.flatMap(findXCFrameworkPaths);
80-
// Find all node-api.xcframeworks files in the dependencies
81-
console.log(JSON.stringify(xcframeworkPaths, null, 2));
84+
// Find the location of each dependency
85+
const dependencyPathsByName = findPackageDependencyPaths(installationRoot);
86+
// Find all their xcframeworks
87+
const dependenciesByName = Object.fromEntries(
88+
Object.entries(dependencyPathsByName)
89+
.map(([dependencyName, dependencyPath]) => {
90+
// Make all the xcframeworks relative to the dependency path
91+
const xcframeworkPaths = findXCFrameworkPaths(dependencyPath).map(
92+
(p) => path.relative(dependencyPath, p)
93+
);
94+
return [
95+
dependencyName,
96+
{
97+
path: dependencyPath,
98+
xcframeworkPaths,
99+
},
100+
] as const;
101+
})
102+
// Remove any dependencies without xcframeworks
103+
.filter(([, { xcframeworkPaths }]) => xcframeworkPaths.length > 0)
104+
);
105+
// To be able to reference the xcframeworks from the Podspec,
106+
// we need them as sub-directories of the Podspec parent directory.
107+
const outputPath = path.resolve(
108+
__dirname,
109+
"..",
110+
"..",
111+
"vendored-xcframeworks"
112+
);
113+
// Create or clean the output directory
114+
fs.rmSync(outputPath, { recursive: true, force: true });
115+
fs.mkdirSync(outputPath, { recursive: true });
116+
// Create symbolic links for each xcframework found in dependencies
117+
const linkedXcframeworkPaths = Object.entries(dependenciesByName).flatMap(
118+
([name, dependency]) => {
119+
return dependency.xcframeworkPaths.map((xcframeworkPath) => {
120+
const fromPath = path.join(dependency.path, xcframeworkPath);
121+
const linkedPath = path.join(outputPath, name, xcframeworkPath);
122+
fs.mkdirSync(path.dirname(linkedPath), { recursive: true });
123+
fs.symlinkSync(fromPath, linkedPath, "dir");
124+
return linkedPath;
125+
});
126+
}
127+
);
128+
console.log(JSON.stringify(linkedXcframeworkPaths, null, 2));
82129
});
83130

84131
export function run(argv: string[]) {

0 commit comments

Comments
 (0)