@@ -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-
133128const 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+
146165export 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} ;
0 commit comments