Skip to content

Commit 72b26aa

Browse files
committed
Handling non-framework dylibs too
1 parent 577bb2c commit 72b26aa

File tree

3 files changed

+162
-109
lines changed

3 files changed

+162
-109
lines changed

packages/cmake-rn/src/platforms/apple.ts

Lines changed: 150 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,6 @@ export function createPlistContent(values: Record<string, string>) {
125125
].join("\n");
126126
}
127127

128-
export function getAppleBuildArgs() {
129-
// We expect the final application to sign these binaries
130-
return ["CODE_SIGNING_ALLOWED=NO"];
131-
}
132-
133128
const xcframeworkExtensionOption = new Option(
134129
"--xcframework-extension",
135130
"Don't rename the xcframework to .apple.node",
@@ -143,6 +138,30 @@ function getBuildPath(baseBuildPath: string, triplet: Triplet) {
143138
return path.join(baseBuildPath, triplet.replace(/;/g, "_"));
144139
}
145140

141+
async function readCmakeSharedLibraryTarget(
142+
buildPath: string,
143+
configuration: string,
144+
target: string[],
145+
) {
146+
const targets = await cmakeFileApi.readCurrentTargetsDeep(
147+
buildPath,
148+
configuration,
149+
"2.0",
150+
);
151+
const sharedLibraries = targets.filter(
152+
({ type, name }) =>
153+
type === "SHARED_LIBRARY" &&
154+
(target.length === 0 || target.includes(name)),
155+
);
156+
assert.equal(
157+
sharedLibraries.length,
158+
1,
159+
"Expected exactly one shared library",
160+
);
161+
const [sharedLibrary] = sharedLibraries;
162+
return sharedLibrary;
163+
}
164+
146165
export const platform: Platform<Triplet[], AppleOpts> = {
147166
id: "apple",
148167
name: "Apple",
@@ -218,68 +237,94 @@ export const platform: Platform<Triplet[], AppleOpts> = {
218237
}
219238

220239
const buildPath = getBuildPath(build, triplet);
221-
const { project } = listXcodeProject(buildPath);
222240

223-
const schemes = project.schemes.filter(
224-
(scheme) => scheme !== "ALL_BUILD" && scheme !== "ZERO_CHECK",
241+
const sharedLibrary = await readCmakeSharedLibraryTarget(
242+
buildPath,
243+
configuration,
244+
target,
225245
);
226246

227-
assert(
228-
schemes.length === 1,
229-
`Expected exactly one buildable scheme, got ${schemes.join(", ")}`,
230-
);
247+
const isFramework = sharedLibrary.nameOnDisk?.includes(".framework/");
231248

232-
const [scheme] = schemes;
249+
if (isFramework) {
250+
const { project } = listXcodeProject(buildPath);
233251

234-
if (target.length === 1) {
235-
assert.equal(
236-
scheme,
237-
target[0],
238-
"Expected the only scheme to match the requested target",
252+
const schemes = project.schemes.filter(
253+
(scheme) => scheme !== "ALL_BUILD" && scheme !== "ZERO_CHECK",
239254
);
240-
}
241-
242-
// TODO: Don't forget "CODE_SIGNING_ALLOWED=NO"
243-
await spawn(
244-
"xcodebuild",
245-
[
246-
"archive",
247-
"-scheme",
248-
scheme,
249-
"-configuration",
250-
configuration,
251255

252-
// Ideally, we would just pass -destination here,
253-
// but I'm not able to configure / generate a single Xcode project supporting all
254-
"-destination",
255-
DESTINATION_BY_TRIPLET[triplet],
256+
assert(
257+
schemes.length === 1,
258+
`Expected exactly one buildable scheme, got ${schemes.join(", ")}`,
259+
);
256260

257-
// // TODO: Should this be outputPath?
258-
// "-archivePath",
259-
// "archives/MyFramework.xcarchive",
260-
],
261-
buildPath,
262-
);
263-
await spawn(
264-
"xcodebuild",
265-
[
266-
"install",
267-
"-scheme",
268-
scheme,
269-
"-configuration",
270-
configuration,
261+
const [scheme] = schemes;
271262

272-
// Ideally, we would just pass -destination here,
273-
// but I'm not able to configure / generate a single Xcode project supporting all
274-
"-destination",
275-
DESTINATION_BY_TRIPLET[triplet],
263+
if (target.length === 1) {
264+
assert.equal(
265+
scheme,
266+
target[0],
267+
"Expected the only scheme to match the requested target",
268+
);
269+
}
276270

277-
// // TODO: Should this be outputPath?
278-
// "-archivePath",
279-
// "archives/MyFramework.xcarchive",
280-
],
281-
buildPath,
282-
);
271+
await spawn(
272+
"xcodebuild",
273+
[
274+
"archive",
275+
"-scheme",
276+
scheme,
277+
"-configuration",
278+
configuration,
279+
280+
// Ideally, we would just pass -destination here,
281+
// but I'm not able to configure / generate a single Xcode project supporting all
282+
"-destination",
283+
DESTINATION_BY_TRIPLET[triplet],
284+
],
285+
buildPath,
286+
);
287+
await spawn(
288+
"xcodebuild",
289+
[
290+
"install",
291+
"-scheme",
292+
scheme,
293+
"-configuration",
294+
configuration,
295+
296+
// Ideally, we would just pass -destination here,
297+
// but I'm not able to configure / generate a single Xcode project supporting all
298+
"-destination",
299+
DESTINATION_BY_TRIPLET[triplet],
300+
],
301+
buildPath,
302+
);
303+
} else {
304+
await spawn("cmake", [
305+
"--build",
306+
buildPath,
307+
"--config",
308+
configuration,
309+
...(target.length > 0 ? ["--target", ...target] : []),
310+
"--",
311+
312+
// Skip code-signing (needed when building free dynamic libraries)
313+
// TODO: Make this configurable
314+
"CODE_SIGNING_ALLOWED=NO",
315+
]);
316+
// Create a framework
317+
const { artifacts } = sharedLibrary;
318+
assert(
319+
artifacts && artifacts.length === 1,
320+
"Expected exactly one artifact",
321+
);
322+
const [artifact] = artifacts;
323+
await createAppleFramework(
324+
path.join(buildPath, artifact.path),
325+
triplet.endsWith("-darwin"),
326+
);
327+
}
283328
},
284329
isSupportedByHost: function (): boolean | Promise<boolean> {
285330
return process.platform === "darwin";
@@ -289,74 +334,72 @@ export const platform: Platform<Triplet[], AppleOpts> = {
289334
triplets,
290335
{ configuration, autoLink, xcframeworkExtension, target, build },
291336
) {
292-
const prebuilds: Record<string, string[]> = {};
337+
const libraryNames = new Set<string>();
338+
const frameworkPaths: string[] = [];
293339
for (const { triplet } of triplets) {
294340
const buildPath = getBuildPath(build, triplet);
295341
assert(fs.existsSync(buildPath), `Expected a directory at ${buildPath}`);
296-
const targets = await cmakeFileApi.readCurrentTargetsDeep(
342+
const sharedLibrary = await readCmakeSharedLibraryTarget(
297343
buildPath,
298344
configuration,
299-
"2.0",
300-
);
301-
const sharedLibraries = targets.filter(
302-
({ type, name }) =>
303-
type === "SHARED_LIBRARY" &&
304-
(target.length === 0 || target.includes(name)),
305-
);
306-
assert.equal(
307-
sharedLibraries.length,
308-
1,
309-
"Expected exactly one shared library",
345+
target,
310346
);
311-
const [sharedLibrary] = sharedLibraries;
312347
const { artifacts } = sharedLibrary;
313348
assert(
314349
artifacts && artifacts.length === 1,
315350
"Expected exactly one artifact",
316351
);
317352
const [artifact] = artifacts;
318-
// Add prebuild entry, creating a new entry if needed
319-
if (!(sharedLibrary.name in prebuilds)) {
320-
prebuilds[sharedLibrary.name] = [];
353+
libraryNames.add(sharedLibrary.name);
354+
// Locate the path of the framework, if a free dynamic library was built
355+
if (artifact.path.includes(".framework/")) {
356+
frameworkPaths.push(path.dirname(path.join(buildPath, artifact.path)));
357+
} else {
358+
const libraryName = path.basename(
359+
artifact.path,
360+
path.extname(artifact.path),
361+
);
362+
const frameworkPath = path.join(
363+
buildPath,
364+
path.dirname(artifact.path),
365+
`${libraryName}.framework`,
366+
);
367+
assert(
368+
fs.existsSync(frameworkPath),
369+
`Expected to find a framework at: ${frameworkPath}`,
370+
);
371+
frameworkPaths.push(frameworkPath);
321372
}
322-
prebuilds[sharedLibrary.name].push(path.join(buildPath, artifact.path));
323373
}
324374

325375
const extension = xcframeworkExtension ? ".xcframework" : ".apple.node";
326376

327-
for (const [libraryName, libraryPaths] of Object.entries(prebuilds)) {
328-
const frameworkPaths = await Promise.all(
329-
libraryPaths.map(async (libraryPath) => {
330-
const parentDir = path.dirname(libraryPath);
331-
if (path.extname(parentDir) === ".framework") {
332-
return parentDir;
333-
} else {
334-
return createAppleFramework(libraryPath);
335-
}
336-
}),
337-
);
377+
assert(
378+
libraryNames.size === 1,
379+
"Expected all libraries to have the same name",
380+
);
381+
const [libraryName] = libraryNames;
338382

339-
// Create the xcframework
340-
const xcframeworkOutputPath = path.resolve(
341-
outputPath,
342-
`${libraryName}${extension}`,
343-
);
383+
// Create the xcframework
384+
const xcframeworkOutputPath = path.resolve(
385+
outputPath,
386+
`${libraryName}${extension}`,
387+
);
344388

345-
await oraPromise(
346-
createXCframework({
347-
outputPath: xcframeworkOutputPath,
348-
frameworkPaths,
349-
autoLink,
350-
}),
351-
{
352-
text: `Assembling XCFramework (${libraryName})`,
353-
successText: `XCFramework (${libraryName}) assembled into ${chalk.dim(
354-
path.relative(process.cwd(), xcframeworkOutputPath),
355-
)}`,
356-
failText: ({ message }) =>
357-
`Failed to assemble XCFramework (${libraryName}): ${message}`,
358-
},
359-
);
360-
}
389+
await oraPromise(
390+
createXCframework({
391+
outputPath: xcframeworkOutputPath,
392+
frameworkPaths,
393+
autoLink,
394+
}),
395+
{
396+
text: `Assembling XCFramework (${libraryName})`,
397+
successText: `XCFramework (${libraryName}) assembled into ${chalk.dim(
398+
path.relative(process.cwd(), xcframeworkOutputPath),
399+
)}`,
400+
failText: ({ message }) =>
401+
`Failed to assemble XCFramework (${libraryName}): ${message}`,
402+
},
403+
);
361404
},
362405
};

packages/ferric/src/build.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,10 @@ export const buildCommand = new Command("build")
237237
if (appleLibraries.length > 0) {
238238
const libraryPaths = await combineLibraries(appleLibraries);
239239
const frameworkPaths = await Promise.all(
240-
libraryPaths.map(createAppleFramework),
240+
libraryPaths.map((libraryPath) =>
241+
// TODO: Pass true as `versioned` argument for -darwin targets
242+
createAppleFramework(libraryPath),
243+
),
241244
);
242245
const xcframeworkFilename = determineXCFrameworkFilename(
243246
frameworkPaths,

packages/host/src/node/prebuilds/apple.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,14 @@ type XCframeworkOptions = {
4444
autoLink: boolean;
4545
};
4646

47-
export async function createAppleFramework(libraryPath: string) {
47+
export async function createAppleFramework(
48+
libraryPath: string,
49+
versioned = false,
50+
) {
51+
if (versioned) {
52+
// TODO: Add support for generating a Versions/Current/Resources/Info.plist convention framework
53+
throw new Error("Creating versioned frameworks is not supported yet");
54+
}
4855
assert(fs.existsSync(libraryPath), `Library not found: ${libraryPath}`);
4956
// Write a info.plist file to the framework
5057
const libraryName = path.basename(libraryPath, path.extname(libraryPath));

0 commit comments

Comments
 (0)