@@ -129,11 +129,6 @@ export function createPlistContent(values: Record<string, string>) {
129129 ] . join ( "\n" ) ;
130130}
131131
132- export function getAppleBuildArgs ( ) {
133- // We expect the final application to sign these binaries
134- return [ "CODE_SIGNING_ALLOWED=NO" ] ;
135- }
136-
137132const xcframeworkExtensionOption = new Option (
138133 "--xcframework-extension" ,
139134 "Don't rename the xcframework to .apple.node" ,
@@ -147,6 +142,30 @@ function getBuildPath(baseBuildPath: string, triplet: Triplet) {
147142 return path . join ( baseBuildPath , triplet . replace ( / ; / g, "_" ) ) ;
148143}
149144
145+ async function readCmakeSharedLibraryTarget (
146+ buildPath : string ,
147+ configuration : string ,
148+ target : string [ ] ,
149+ ) {
150+ const targets = await cmakeFileApi . readCurrentTargetsDeep (
151+ buildPath ,
152+ configuration ,
153+ "2.0" ,
154+ ) ;
155+ const sharedLibraries = targets . filter (
156+ ( { type, name } ) =>
157+ type === "SHARED_LIBRARY" &&
158+ ( target . length === 0 || target . includes ( name ) ) ,
159+ ) ;
160+ assert . equal (
161+ sharedLibraries . length ,
162+ 1 ,
163+ "Expected exactly one shared library" ,
164+ ) ;
165+ const [ sharedLibrary ] = sharedLibraries ;
166+ return sharedLibrary ;
167+ }
168+
150169export const platform : Platform < Triplet [ ] , AppleOpts > = {
151170 id : "apple" ,
152171 name : "Apple" ,
@@ -222,68 +241,94 @@ export const platform: Platform<Triplet[], AppleOpts> = {
222241 }
223242
224243 const buildPath = getBuildPath ( build , triplet ) ;
225- const { project } = listXcodeProject ( buildPath ) ;
226244
227- const schemes = project . schemes . filter (
228- ( scheme ) => scheme !== "ALL_BUILD" && scheme !== "ZERO_CHECK" ,
245+ const sharedLibrary = await readCmakeSharedLibraryTarget (
246+ buildPath ,
247+ configuration ,
248+ target ,
229249 ) ;
230250
231- assert (
232- schemes . length === 1 ,
233- `Expected exactly one buildable scheme, got ${ schemes . join ( ", " ) } ` ,
234- ) ;
251+ const isFramework = sharedLibrary . nameOnDisk ?. includes ( ".framework/" ) ;
235252
236- const [ scheme ] = schemes ;
253+ if ( isFramework ) {
254+ const { project } = listXcodeProject ( buildPath ) ;
237255
238- if ( target . length === 1 ) {
239- assert . equal (
240- scheme ,
241- target [ 0 ] ,
242- "Expected the only scheme to match the requested target" ,
256+ const schemes = project . schemes . filter (
257+ ( scheme ) => scheme !== "ALL_BUILD" && scheme !== "ZERO_CHECK" ,
243258 ) ;
244- }
245-
246- // TODO: Don't forget "CODE_SIGNING_ALLOWED=NO"
247- await spawn (
248- "xcodebuild" ,
249- [
250- "archive" ,
251- "-scheme" ,
252- scheme ,
253- "-configuration" ,
254- configuration ,
255259
256- // Ideally, we would just pass -destination here,
257- // but I'm not able to configure / generate a single Xcode project supporting all
258- "-destination" ,
259- DESTINATION_BY_TRIPLET [ triplet ] ,
260+ assert (
261+ schemes . length === 1 ,
262+ `Expected exactly one buildable scheme, got ${ schemes . join ( ", " ) } ` ,
263+ ) ;
260264
261- // // TODO: Should this be outputPath?
262- // "-archivePath",
263- // "archives/MyFramework.xcarchive",
264- ] ,
265- buildPath ,
266- ) ;
267- await spawn (
268- "xcodebuild" ,
269- [
270- "install" ,
271- "-scheme" ,
272- scheme ,
273- "-configuration" ,
274- configuration ,
265+ const [ scheme ] = schemes ;
275266
276- // Ideally, we would just pass -destination here,
277- // but I'm not able to configure / generate a single Xcode project supporting all
278- "-destination" ,
279- DESTINATION_BY_TRIPLET [ triplet ] ,
267+ if ( target . length === 1 ) {
268+ assert . equal (
269+ scheme ,
270+ target [ 0 ] ,
271+ "Expected the only scheme to match the requested target" ,
272+ ) ;
273+ }
280274
281- // // TODO: Should this be outputPath?
282- // "-archivePath",
283- // "archives/MyFramework.xcarchive",
284- ] ,
285- buildPath ,
286- ) ;
275+ await spawn (
276+ "xcodebuild" ,
277+ [
278+ "archive" ,
279+ "-scheme" ,
280+ scheme ,
281+ "-configuration" ,
282+ configuration ,
283+
284+ // Ideally, we would just pass -destination here,
285+ // but I'm not able to configure / generate a single Xcode project supporting all
286+ "-destination" ,
287+ DESTINATION_BY_TRIPLET [ triplet ] ,
288+ ] ,
289+ buildPath ,
290+ ) ;
291+ await spawn (
292+ "xcodebuild" ,
293+ [
294+ "install" ,
295+ "-scheme" ,
296+ scheme ,
297+ "-configuration" ,
298+ configuration ,
299+
300+ // Ideally, we would just pass -destination here,
301+ // but I'm not able to configure / generate a single Xcode project supporting all
302+ "-destination" ,
303+ DESTINATION_BY_TRIPLET [ triplet ] ,
304+ ] ,
305+ buildPath ,
306+ ) ;
307+ } else {
308+ await spawn ( "cmake" , [
309+ "--build" ,
310+ buildPath ,
311+ "--config" ,
312+ configuration ,
313+ ...( target . length > 0 ? [ "--target" , ...target ] : [ ] ) ,
314+ "--" ,
315+
316+ // Skip code-signing (needed when building free dynamic libraries)
317+ // TODO: Make this configurable
318+ "CODE_SIGNING_ALLOWED=NO" ,
319+ ] ) ;
320+ // Create a framework
321+ const { artifacts } = sharedLibrary ;
322+ assert (
323+ artifacts && artifacts . length === 1 ,
324+ "Expected exactly one artifact" ,
325+ ) ;
326+ const [ artifact ] = artifacts ;
327+ await createAppleFramework (
328+ path . join ( buildPath , artifact . path ) ,
329+ triplet . endsWith ( "-darwin" ) ,
330+ ) ;
331+ }
287332 } ,
288333 isSupportedByHost : function ( ) : boolean | Promise < boolean > {
289334 return process . platform === "darwin" ;
@@ -293,72 +338,70 @@ export const platform: Platform<Triplet[], AppleOpts> = {
293338 triplets ,
294339 { configuration, autoLink, xcframeworkExtension, target, build } ,
295340 ) {
296- const prebuilds : Record < string , string [ ] > = { } ;
341+ const libraryNames = new Set < string > ( ) ;
342+ const frameworkPaths : string [ ] = [ ] ;
297343 for ( const { triplet } of triplets ) {
298344 const buildPath = getBuildPath ( build , triplet ) ;
299345 assert ( fs . existsSync ( buildPath ) , `Expected a directory at ${ buildPath } ` ) ;
300- const targets = await cmakeFileApi . readCurrentTargetsDeep (
346+ const sharedLibrary = await readCmakeSharedLibraryTarget (
301347 buildPath ,
302348 configuration ,
303- "2.0" ,
304- ) ;
305- const sharedLibraries = targets . filter (
306- ( { type, name } ) =>
307- type === "SHARED_LIBRARY" &&
308- ( target . length === 0 || target . includes ( name ) ) ,
309- ) ;
310- assert . equal (
311- sharedLibraries . length ,
312- 1 ,
313- "Expected exactly one shared library" ,
349+ target ,
314350 ) ;
315- const [ sharedLibrary ] = sharedLibraries ;
316351 const { artifacts } = sharedLibrary ;
317352 assert (
318353 artifacts && artifacts . length === 1 ,
319354 "Expected exactly one artifact" ,
320355 ) ;
321356 const [ artifact ] = artifacts ;
322- // Add prebuild entry, creating a new entry if needed
323- if ( ! ( sharedLibrary . name in prebuilds ) ) {
324- prebuilds [ sharedLibrary . name ] = [ ] ;
357+ libraryNames . add ( sharedLibrary . name ) ;
358+ // Locate the path of the framework, if a free dynamic library was built
359+ if ( artifact . path . includes ( ".framework/" ) ) {
360+ frameworkPaths . push ( path . dirname ( path . join ( buildPath , artifact . path ) ) ) ;
361+ } else {
362+ const libraryName = path . basename (
363+ artifact . path ,
364+ path . extname ( artifact . path ) ,
365+ ) ;
366+ const frameworkPath = path . join (
367+ buildPath ,
368+ path . dirname ( artifact . path ) ,
369+ `${ libraryName } .framework` ,
370+ ) ;
371+ assert (
372+ fs . existsSync ( frameworkPath ) ,
373+ `Expected to find a framework at: ${ frameworkPath } ` ,
374+ ) ;
375+ frameworkPaths . push ( frameworkPath ) ;
325376 }
326- prebuilds [ sharedLibrary . name ] . push ( path . join ( buildPath , artifact . path ) ) ;
327377 }
328378
329379 const extension = xcframeworkExtension ? ".xcframework" : ".apple.node" ;
330380
331- for ( const [ libraryName , libraryPaths ] of Object . entries ( prebuilds ) ) {
332- const frameworkPaths = await Promise . all (
333- libraryPaths . map ( async ( libraryPath ) => {
334- const parentDir = path . dirname ( libraryPath ) ;
335- if ( path . extname ( parentDir ) === ".framework" ) {
336- return parentDir ;
337- } else {
338- return createAppleFramework ( libraryPath ) ;
339- }
340- } ) ,
341- ) ;
381+ assert (
382+ libraryNames . size === 1 ,
383+ "Expected all libraries to have the same name" ,
384+ ) ;
385+ const [ libraryName ] = libraryNames ;
342386
343- // Create the xcframework
344- const xcframeworkOutputPath = path . resolve (
345- outputPath ,
346- `${ libraryName } ${ extension } ` ,
347- ) ;
387+ // Create the xcframework
388+ const xcframeworkOutputPath = path . resolve (
389+ outputPath ,
390+ `${ libraryName } ${ extension } ` ,
391+ ) ;
348392
349- await oraPromise (
350- createXCframework ( {
351- outputPath : xcframeworkOutputPath ,
352- frameworkPaths,
353- autoLink,
354- } ) ,
355- {
356- text : `Assembling XCFramework (${ libraryName } )` ,
357- successText : `XCFramework (${ libraryName } ) assembled into ${ prettyPath ( xcframeworkOutputPath ) } ` ,
358- failText : ( { message } ) =>
359- `Failed to assemble XCFramework (${ libraryName } ): ${ message } ` ,
360- } ,
361- ) ;
362- }
393+ await oraPromise (
394+ createXCframework ( {
395+ outputPath : xcframeworkOutputPath ,
396+ frameworkPaths,
397+ autoLink,
398+ } ) ,
399+ {
400+ text : `Assembling XCFramework (${ libraryName } )` ,
401+ successText : `XCFramework (${ libraryName } ) assembled into ${ prettyPath ( xcframeworkOutputPath ) } ` ,
402+ failText : ( { message } ) =>
403+ `Failed to assemble XCFramework (${ libraryName } ): ${ message } ` ,
404+ } ,
405+ ) ;
363406 } ,
364407} ;
0 commit comments