Skip to content

Commit eab4cfc

Browse files
authored
Default out path to {build}/{configuration} directory and refactored pathSuffix naming strategy (#150)
* Default out path to {build}/{configuration} directory * Adjust weak-node-api output directory * Call findNodeAddonForBindings in plugin * Refactor babel plugin tests * Refactor naming strategy
1 parent dce454d commit eab4cfc

File tree

9 files changed

+419
-268
lines changed

9 files changed

+419
-268
lines changed

packages/cmake-rn/src/cli.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ const cleanOption = new Option(
8282
const outPathOption = new Option(
8383
"--out <path>",
8484
"Specify the output directory to store the final build artifacts"
85-
);
85+
).default(false, "./{build}/{configuration}");
8686

8787
const ndkVersionOption = new Option(
8888
"--ndk-version <version>",
@@ -113,12 +113,12 @@ export const program = new Command("cmake-rn")
113113
.description("Build React Native Node API modules with CMake")
114114
.addOption(verboseOption)
115115
.addOption(sourcePathOption)
116+
.addOption(buildPathOption)
117+
.addOption(outPathOption)
116118
.addOption(configurationOption)
117119
.addOption(tripletOption)
118120
.addOption(androidOption)
119121
.addOption(appleOption)
120-
.addOption(buildPathOption)
121-
.addOption(outPathOption)
122122
.addOption(cleanOption)
123123
.addOption(ndkVersionOption)
124124
.addOption(androidSdkVersionOption)
@@ -169,6 +169,10 @@ export const program = new Command("cmake-rn")
169169
}
170170
}
171171

172+
if (!globalContext.out) {
173+
globalContext.out = path.join(buildPath, globalContext.configuration);
174+
}
175+
172176
const tripletContext = [...triplets].map((triplet) => {
173177
const tripletBuildPath = getTripletBuildPath(buildPath, triplet);
174178
return {

packages/host/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
"copy-node-api-headers": "tsx scripts/copy-node-api-headers.ts",
4545
"generate-weak-node-api": "tsx scripts/generate-weak-node-api.ts",
4646
"generate-weak-node-api-injector": "tsx scripts/generate-weak-node-api-injector.ts",
47-
"build-weak-node-api": "cmake-rn --no-auto-link --no-weak-node-api-linkage --xcframework-extension --source ./weak-node-api",
48-
"build-weak-node-api:all-triplets": "cmake-rn --android --apple --no-auto-link --no-weak-node-api-linkage --xcframework-extension --source ./weak-node-api",
47+
"build-weak-node-api": "cmake-rn --no-auto-link --no-weak-node-api-linkage --xcframework-extension --source ./weak-node-api --out ./weak-node-api",
48+
"build-weak-node-api:all-triplets": "cmake-rn --android --apple --no-auto-link --no-weak-node-api-linkage --xcframework-extension --source ./weak-node-api --out ./weak-node-api",
4949
"test": "tsx --test --test-reporter=@reporters/github --test-reporter-destination=stdout --test-reporter=spec --test-reporter-destination=stdout src/node/**/*.test.ts src/node/*.test.ts",
5050
"bootstrap": "npm run copy-node-api-headers && npm run generate-weak-node-api-injector && npm run generate-weak-node-api && npm run build-weak-node-api"
5151
},

packages/host/react-native-node-api.podspec

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ require_relative "./scripts/patch-hermes"
66

77
NODE_PATH ||= `which node`.strip
88
CLI_COMMAND ||= "'#{NODE_PATH}' '#{File.join(__dir__, "dist/node/cli/run.js")}'"
9-
STRIP_PATH_SUFFIX ||= ENV['NODE_API_MODULES_STRIP_PATH_SUFFIX'] === "true"
10-
COPY_FRAMEWORKS_COMMAND ||= "#{CLI_COMMAND} link --apple '#{Pod::Config.instance.installation_root}' #{STRIP_PATH_SUFFIX ? '--strip-path-suffix' : ''}"
9+
COPY_FRAMEWORKS_COMMAND ||= "#{CLI_COMMAND} link --apple '#{Pod::Config.instance.installation_root}'"
1110

1211
# We need to run this now to ensure the xcframeworks are copied vendored_frameworks are considered
1312
XCFRAMEWORKS_DIR ||= File.join(__dir__, "xcframeworks")
Lines changed: 188 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,208 @@
11
import assert from "node:assert/strict";
2-
import { describe, it } from "node:test";
2+
import { describe, it, TestContext } from "node:test";
33
import path from "node:path";
44

55
import { transformFileSync } from "@babel/core";
66

7-
import { plugin } from "./plugin.js";
7+
import { plugin, PluginOptions } from "./plugin.js";
88
import { setupTempDirectory } from "../test-utils.js";
9-
import { getLibraryName } from "../path-utils.js";
109

11-
describe("plugin", () => {
12-
it("transforms require calls, regardless", (context) => {
13-
const tempDirectoryPath = setupTempDirectory(context, {
14-
"package.json": `{ "name": "my-package" }`,
15-
"addon-1.apple.node/addon-1.node":
16-
"// This is supposed to be a binary file",
17-
"addon-2.apple.node/addon-2.node":
18-
"// This is supposed to be a binary file",
19-
"addon-1.js": `
20-
const addon = require('./addon-1.node');
21-
console.log(addon);
22-
`,
23-
"addon-2.js": `
24-
const addon = require('./addon-2.node');
25-
console.log(addon);
26-
`,
27-
"sub-directory/addon-1.js": `
28-
const addon = require('../addon-1.node');
29-
console.log(addon);
30-
`,
31-
"addon-1-bindings.js": `
32-
const addon = require('bindings')('addon-1');
33-
console.log(addon);
34-
`,
35-
"require-js-file.js": `
36-
const addon = require('./addon-1.js');
37-
console.log(addon);
38-
`,
39-
});
10+
type TestTransformationOptions = {
11+
files: Record<string, string>;
12+
inputFilePath: string;
13+
assertion(code: string): void;
14+
options?: PluginOptions;
15+
};
4016

41-
const ADDON_1_REQUIRE_ARG = getLibraryName(
42-
path.join(tempDirectoryPath, "addon-1"),
43-
{ stripPathSuffix: false }
44-
);
45-
const ADDON_2_REQUIRE_ARG = getLibraryName(
46-
path.join(tempDirectoryPath, "addon-2"),
47-
{ stripPathSuffix: false }
17+
function itTransforms(
18+
title: string,
19+
{ files, inputFilePath, assertion, options = {} }: TestTransformationOptions
20+
) {
21+
it(`transforms ${title}`, (context: TestContext) => {
22+
const tempDirectoryPath = setupTempDirectory(context, files);
23+
const result = transformFileSync(
24+
path.join(tempDirectoryPath, inputFilePath),
25+
{ plugins: [[plugin, options]] }
4826
);
27+
assert(result, "Expected transformation to produce a result");
28+
const { code } = result;
29+
assert(code, "Expected transformation to produce code");
30+
assertion(code);
31+
});
32+
}
4933

50-
{
51-
const result = transformFileSync(
52-
path.join(tempDirectoryPath, "./addon-1.js"),
53-
{ plugins: [[plugin, { stripPathSuffix: false }]] }
54-
);
55-
assert(result);
56-
const { code } = result;
34+
function assertIncludes(needle: string, { reverse = false } = {}) {
35+
return (code: string) => {
36+
if (reverse) {
5737
assert(
58-
code && code.includes(`requireNodeAddon("${ADDON_1_REQUIRE_ARG}")`),
59-
`Unexpected code: ${code}`
38+
!code.includes(needle),
39+
`Expected code to not include: ${needle}, got ${code}`
6040
);
61-
}
62-
63-
{
64-
const result = transformFileSync(
65-
path.join(tempDirectoryPath, "./addon-2.js"),
66-
{ plugins: [[plugin, { naming: "hash" }]] }
67-
);
68-
assert(result);
69-
const { code } = result;
41+
} else {
7042
assert(
71-
code && code.includes(`requireNodeAddon("${ADDON_2_REQUIRE_ARG}")`),
72-
`Unexpected code: ${code}`
43+
code.includes(needle),
44+
`Expected code to include: ${needle}, got ${code}`
7345
);
7446
}
47+
};
48+
}
7549

76-
{
77-
const result = transformFileSync(
78-
path.join(tempDirectoryPath, "./sub-directory/addon-1.js"),
79-
{ plugins: [[plugin, { naming: "hash" }]] }
80-
);
81-
assert(result);
82-
const { code } = result;
83-
assert(
84-
code && code.includes(`requireNodeAddon("${ADDON_1_REQUIRE_ARG}")`),
85-
`Unexpected code: ${code}`
86-
);
87-
}
50+
describe("plugin", () => {
51+
describe("transforming require(...) calls", () => {
52+
itTransforms("a simple call", {
53+
files: {
54+
"package.json": `{ "name": "my-package" }`,
55+
"my-addon.apple.node/my-addon.node":
56+
"// This is supposed to be a binary file",
57+
"index.js": `
58+
const addon = require('./my-addon.node');
59+
console.log(addon);
60+
`,
61+
},
62+
inputFilePath: "index.js",
63+
assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`),
64+
});
8865

89-
{
90-
const result = transformFileSync(
91-
path.join(tempDirectoryPath, "./addon-1-bindings.js"),
92-
{ plugins: [[plugin, { naming: "hash" }]] }
93-
);
94-
assert(result);
95-
const { code } = result;
96-
assert(
97-
code && code.includes(`requireNodeAddon("${ADDON_1_REQUIRE_ARG}")`),
98-
`Unexpected code: ${code}`
99-
);
100-
}
66+
itTransforms("from sub-directory", {
67+
files: {
68+
"package.json": `{ "name": "my-package" }`,
69+
"my-addon.apple.node/my-addon.node":
70+
"// This is supposed to be a binary file",
71+
"sub-dir/index.js": `
72+
const addon = require('../my-addon.node');
73+
console.log(addon);
74+
`,
75+
},
76+
inputFilePath: "sub-dir/index.js",
77+
assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`),
78+
});
10179

102-
{
103-
const result = transformFileSync(
104-
path.join(tempDirectoryPath, "./require-js-file.js"),
105-
{ plugins: [[plugin, { naming: "hash" }]] }
106-
);
107-
assert(result);
108-
const { code } = result;
109-
assert(
110-
code && !code.includes(`requireNodeAddon`),
111-
`Unexpected code: ${code}`
112-
);
113-
}
80+
describe("in 'sub-dir'", () => {
81+
itTransforms("a nested addon (keeping suffix)", {
82+
files: {
83+
"package.json": `{ "name": "my-package" }`,
84+
"sub-dir/my-addon.apple.node/my-addon.node":
85+
"// This is supposed to be a binary file",
86+
"index.js": `
87+
const addon = require('./sub-dir/my-addon.node');
88+
console.log(addon);
89+
`,
90+
},
91+
inputFilePath: "index.js",
92+
options: { pathSuffix: "keep" },
93+
assertion: assertIncludes(
94+
`requireNodeAddon("my-package--sub-dir-my-addon")`
95+
),
96+
});
97+
98+
itTransforms("a nested addon (stripping suffix)", {
99+
files: {
100+
"package.json": `{ "name": "my-package" }`,
101+
"sub-dir/my-addon.apple.node/my-addon.node":
102+
"// This is supposed to be a binary file",
103+
"index.js": `
104+
const addon = require('./sub-dir/my-addon.node');
105+
console.log(addon);
106+
`,
107+
},
108+
inputFilePath: "index.js",
109+
options: { pathSuffix: "strip" },
110+
assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`),
111+
});
112+
113+
itTransforms("a nested addon (omitting suffix)", {
114+
files: {
115+
"package.json": `{ "name": "my-package" }`,
116+
"sub-dir/my-addon.apple.node/my-addon.node":
117+
"// This is supposed to be a binary file",
118+
"index.js": `
119+
const addon = require('./sub-dir/my-addon.node');
120+
console.log(addon);
121+
`,
122+
},
123+
inputFilePath: "index.js",
124+
options: { pathSuffix: "omit" },
125+
assertion: assertIncludes(`requireNodeAddon("my-package")`),
126+
});
127+
});
128+
129+
itTransforms("and does not touch required JS files", {
130+
files: {
131+
"package.json": `{ "name": "my-package" }`,
132+
// TODO: Add a ./my-addon.node to make this test complete
133+
"my-addon.js": "// Some JS file",
134+
"index.js": `
135+
const addon = require('./my-addon');
136+
console.log(addon);
137+
`,
138+
},
139+
inputFilePath: "index.js",
140+
assertion: assertIncludes("requireNodeAddon", { reverse: true }),
141+
});
142+
});
143+
144+
describe("transforming require('binding')(...) calls", () => {
145+
itTransforms("a simple call", {
146+
files: {
147+
"package.json": `{ "name": "my-package" }`,
148+
"my-addon.apple.node/my-addon.node":
149+
"// This is supposed to be a binary file",
150+
"index.js": `
151+
const addon = require('bindings')('my-addon');
152+
console.log(addon);
153+
`,
154+
},
155+
inputFilePath: "index.js",
156+
assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`),
157+
});
158+
159+
describe("in 'build/Release'", () => {
160+
itTransforms("a nested addon (keeping suffix)", {
161+
files: {
162+
"package.json": `{ "name": "my-package" }`,
163+
"build/Release/my-addon.apple.node/my-addon.node":
164+
"// This is supposed to be a binary file",
165+
"index.js": `
166+
const addon = require('bindings')('my-addon');
167+
console.log(addon);
168+
`,
169+
},
170+
inputFilePath: "index.js",
171+
options: { pathSuffix: "keep" },
172+
assertion: assertIncludes(
173+
`requireNodeAddon("my-package--build-Release-my-addon")`
174+
),
175+
});
176+
177+
itTransforms("a nested addon (stripping suffix)", {
178+
files: {
179+
"package.json": `{ "name": "my-package" }`,
180+
"build/Release/my-addon.apple.node/my-addon.node":
181+
"// This is supposed to be a binary file",
182+
"index.js": `
183+
const addon = require('bindings')('my-addon');
184+
console.log(addon);
185+
`,
186+
},
187+
inputFilePath: "index.js",
188+
options: { pathSuffix: "strip" },
189+
assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`),
190+
});
191+
192+
itTransforms("a nested addon (omitting suffix)", {
193+
files: {
194+
"package.json": `{ "name": "my-package" }`,
195+
"build/Release/my-addon.apple.node/my-addon.node":
196+
"// This is supposed to be a binary file",
197+
"index.js": `
198+
const addon = require('bindings')('my-addon');
199+
console.log(addon);
200+
`,
201+
},
202+
inputFilePath: "index.js",
203+
options: { pathSuffix: "omit" },
204+
assertion: assertIncludes(`requireNodeAddon("my-package")`),
205+
});
206+
});
114207
});
115208
});

0 commit comments

Comments
 (0)