@@ -14,6 +14,41 @@ const fs = require('fs');
1414const path = require ( 'path' ) ;
1515const { execSync } = require ( 'child_process' ) ;
1616
17+ function isMachOBinary ( filePath ) {
18+ try {
19+ const fd = fs . openSync ( filePath , 'r' ) ;
20+ const buffer = Buffer . alloc ( 4 ) ;
21+ fs . readSync ( fd , buffer , 0 , 4 , 0 ) ;
22+ fs . closeSync ( fd ) ;
23+
24+ // Mach-O & FAT (universal) magic numbers.
25+ const magics = new Set ( [
26+ buffer . toString ( 'hex' ) ,
27+ ] ) ;
28+
29+ // Mach-O 32-bit / 64-bit (big-endian and little-endian)
30+ if ( magics . has ( 'feedface' ) || magics . has ( 'cefaedfe' ) ) return true ;
31+ if ( magics . has ( 'feedfacf' ) || magics . has ( 'cffaedfe' ) ) return true ;
32+
33+ // FAT/universal (32-bit and 64-bit, big-endian and little-endian)
34+ if ( magics . has ( 'cafebabe' ) || magics . has ( 'bebafeca' ) ) return true ;
35+ if ( magics . has ( 'cafebabf' ) || magics . has ( 'bfbafeca' ) ) return true ;
36+
37+ return false ;
38+ } catch ( error ) {
39+ return false ;
40+ }
41+ }
42+
43+ function isFileCommandAvailable ( ) {
44+ try {
45+ execSync ( 'file --version' , { stdio : 'ignore' } ) ;
46+ return true ;
47+ } catch ( error ) {
48+ return false ;
49+ }
50+ }
51+
1752/**
1853 * Get current system architecture
1954 * @returns {string } 'arm64' or 'x86_64'
@@ -23,8 +58,10 @@ function getSystemArchitecture() {
2358 const arch = execSync ( 'uname -m' , { encoding : 'utf8' } ) . trim ( ) ;
2459 return arch ;
2560 } catch ( error ) {
26- console . warn ( 'β οΈ Could not determine system architecture, defaulting to arm64' ) ;
27- return 'arm64' ;
61+ // Fallback for non-POSIX environments (or sandboxed shells).
62+ const arch = process . arch === 'arm64' ? 'arm64' : 'x86_64' ;
63+ console . warn ( `β οΈ Could not determine system architecture via uname, defaulting to ${ arch } ` ) ;
64+ return arch ;
2865 }
2966}
3067
@@ -34,6 +71,9 @@ function getSystemArchitecture() {
3471 * @returns {boolean } True if universal binary
3572 */
3673function isUniversalBinary ( filePath ) {
74+ if ( ! isFileCommandAvailable ( ) ) {
75+ return false ;
76+ }
3777 try {
3878 const output = execSync ( `file "${ filePath } "` , { encoding : 'utf8' } ) ;
3979 return output . includes ( 'universal binary' ) ||
@@ -92,6 +132,10 @@ function copyDylib(libName, bridgeBuildDir, targetDir) {
92132 if ( isUniversalBinary ( universalPath ) ) {
93133 console . log ( ` β
Confirmed as universal binary (arm64 + x86_64)` ) ;
94134 }
135+ if ( ! isMachOBinary ( universalPath ) ) {
136+ console . error ( `β ${ libName } does not appear to be a Mach-O binary: ${ universalPath } ` ) ;
137+ return false ;
138+ }
95139 return copyFile ( universalPath , targetPath ) ;
96140 }
97141
@@ -102,6 +146,10 @@ function copyDylib(libName, bridgeBuildDir, targetDir) {
102146 const archPath = systemArch === 'arm64' ? arm64Path : x86_64Path ;
103147 if ( fs . existsSync ( archPath ) ) {
104148 console . log ( ` β
Found ${ systemArch } binary for ${ libName } ` ) ;
149+ if ( ! isMachOBinary ( archPath ) ) {
150+ console . error ( `β ${ libName } does not appear to be a Mach-O binary: ${ archPath } ` ) ;
151+ return false ;
152+ }
105153 return copyFile ( archPath , targetPath ) ;
106154 }
107155
@@ -112,6 +160,10 @@ function copyDylib(libName, bridgeBuildDir, targetDir) {
112160 if ( fs . existsSync ( otherArchPath ) ) {
113161 console . warn ( `β οΈ Only ${ otherArch } binary found for ${ libName } (current system: ${ systemArch } )` ) ;
114162 console . warn ( ` This may cause compatibility issues!` ) ;
163+ if ( ! isMachOBinary ( otherArchPath ) ) {
164+ console . error ( `β ${ libName } does not appear to be a Mach-O binary: ${ otherArchPath } ` ) ;
165+ return false ;
166+ }
115167 return copyFile ( otherArchPath , targetPath ) ;
116168 }
117169
@@ -230,10 +282,11 @@ function copyMacOSDynamicLibraries(webfDir) {
230282
231283// Main execution
232284function main ( ) {
233- // Check if we're on macOS
285+ // This script only copies Mach-O artifacts, so it can run in Linux containers/CI as long as the
286+ // macOS build outputs are present (e.g., when the repo is mounted from a macOS host).
234287 if ( process . platform !== 'darwin' ) {
235- console . error ( 'β This script can only run on macOS' ) ;
236- process . exit ( 1 ) ;
288+ console . warn ( `β οΈ Not running on macOS (platform: ${ process . platform } ). Continuing with copy only.` ) ;
289+ console . warn ( ` Note: CocoaPods steps (pod install) must be run on macOS.` ) ;
237290 }
238291
239292 // Parse command line arguments
@@ -263,4 +316,4 @@ if (require.main === module) {
263316}
264317
265318// Export for use as a module
266- module . exports = { copyMacOSDynamicLibraries } ;
319+ module . exports = { copyMacOSDynamicLibraries } ;
0 commit comments