-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: allow only using macOS SDKs in CI
- Loading branch information
1 parent
0b3bd7e
commit 2f871ce
Showing
5 changed files
with
212 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
const cp = require('child_process'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const semver = require('semver'); | ||
const { ensureDir } = require('./paths'); | ||
const evmConfig = require('../evm-config'); | ||
|
||
const { color, fatal } = require('./logging'); | ||
const { deleteDir } = require('./paths'); | ||
|
||
const SDKDir = path.resolve(__dirname, '..', '..', 'third_party', 'SDKs'); | ||
const SDKZip = path.resolve(SDKDir, 'MacOSX.sdk.zip'); | ||
|
||
const XcodeBaseURL = 'https://dev-cdn.electronjs.org/xcode/'; | ||
|
||
const SDKs = { | ||
'14.0': { | ||
fileName: 'MacOSX-14.0.sdk.zip', | ||
sha256: '63c0e69c60c3e0f25b42726fc3a0f0f2902b5cac304d78456c33e13f9dd6d081', | ||
}, | ||
'13.3': { | ||
fileName: 'MacOSX-13.3.sdk.zip', | ||
sha256: '78b99db2e6f0fba2ffeef0d2dfb25e6b700483e3f18cdaf9a18a9a3f9ed10cfa', | ||
}, | ||
'13.0': { | ||
fileName: 'MacOSX-13.0.sdk.zip', | ||
sha256: '689ae09a4287d2711bd137e48a675635e0d66fdcfb3cf8a324c4b3f03c2cf883', | ||
}, | ||
'12.3': { | ||
fileName: 'MacOSX-12.3.sdk.zip', | ||
sha256: '4fb95f95d439f1d1eaf5c89e3e2b842ac746b96273908f8bf8d732a39597e78f', | ||
}, | ||
}; | ||
|
||
const fallbackSDK = () => { | ||
return Object.keys(SDKs) | ||
.map(v => semver.valid(semver.coerce(v))) | ||
.sort(semver.rcompare)[0]; | ||
}; | ||
|
||
function getSDKVersion() { | ||
const { SDKROOT } = evmConfig.current().env; | ||
console.log(SDKROOT); | ||
|
||
if (!fs.existsSync(SDKROOT)) { | ||
return 'unknown'; | ||
} | ||
|
||
const settingsPath = path.resolve(SDKROOT, 'SDKSettings.json'); | ||
const data = fs.readFileSync(settingsPath, 'utf8'); | ||
const json = JSON.parse(data); | ||
|
||
return json.MinimalDisplayName; | ||
} | ||
|
||
function extractSDKVersion(config) { | ||
const match = /macOS \d+(?:\.\d+)? SDK\n\# \((\d+\.\d+)/.exec(config); | ||
return match ? match[1] : null; | ||
} | ||
|
||
function expectedSDKVersion() { | ||
const { root } = evmConfig.current(); | ||
|
||
// The current Xcode version and associated SDK can be found in build/mac_toolchain.py. | ||
const macToolchainPy = path.resolve(root, 'src', 'build', 'mac_toolchain.py'); | ||
|
||
if (!fs.existsSync(macToolchainPy)) { | ||
console.warn( | ||
color.warn, | ||
`Failed to find ${color.path(macToolchainPy)} - falling back to default of`, | ||
fallbackSDK(), | ||
); | ||
return fallbackSDK(); | ||
} | ||
|
||
const config = fs.readFileSync(macToolchainPy, 'utf8'); | ||
const version = extractSDKVersion(config); | ||
|
||
if (isNaN(Number(version)) || !SDKs[version]) { | ||
console.warn( | ||
color.warn, | ||
`Automatically detected an unknown macOS SDK ${color.path( | ||
version, | ||
)} - falling back to default of`, | ||
fallbackSDK(), | ||
); | ||
return fallbackSDK(); | ||
} | ||
|
||
return version; | ||
} | ||
|
||
function ensureSDK() { | ||
const expected = expectedSDKVersion(); | ||
const eventualVersionedPath = path.resolve(SDKDir, `MacOSX-${expected}.sdk`); | ||
|
||
const shouldEnsureSDK = !fs.existsSync(eventualVersionedPath) || getSDKVersion() !== expected; | ||
|
||
if (shouldEnsureSDK) { | ||
ensureDir(SDKDir); | ||
const expectedSDKHash = SDKs[expected].sha256; | ||
|
||
if (!fs.existsSync(eventualVersionedPath)) { | ||
let shouldDownload = true; | ||
if (fs.existsSync(SDKZip)) { | ||
const existingHash = hashFile(SDKZip); | ||
if (existingHash === expectedSDKHash) { | ||
shouldDownload = false; | ||
} else { | ||
console.log( | ||
`${color.warn} Got existing hash ${color.cmd( | ||
existingHash, | ||
)} which did not match ${color.cmd(expectedSDKHash)} so redownloading SDK`, | ||
); | ||
deleteDir(SDKZip); | ||
} | ||
} | ||
|
||
if (shouldDownload) { | ||
const sdkURL = `${XcodeBaseURL}${SDKs[expected].fileName}`; | ||
console.log(`Downloading ${color.cmd(sdkURL)} into ${color.path(SDKZip)}`); | ||
const { status } = cp.spawnSync( | ||
process.execPath, | ||
[path.resolve(__dirname, '..', 'download.js'), sdkURL, SDKZip], | ||
{ | ||
stdio: 'inherit', | ||
}, | ||
); | ||
|
||
if (status !== 0) { | ||
deleteDir(SDKZip); | ||
fatal(`Failure while downloading SDK zip`); | ||
} | ||
|
||
const newHash = hashFile(SDKZip); | ||
if (newHash !== expectedSDKHash) { | ||
deleteDir(SDKZip); | ||
fatal( | ||
`Downloaded SDK zip had hash "${newHash}" which does not match expected hash "${expectedSDKHash}"`, | ||
); | ||
} | ||
} | ||
|
||
console.log(`Extracting ${color.cmd(SDKZip)} into ${color.path(eventualVersionedPath)}`); | ||
const unzipPath = path.resolve(SDKDir, 'tmp_unzip'); | ||
deleteDir(unzipPath); | ||
const { status } = cp.spawnSync('unzip', ['-q', '-o', SDKZip, '-d', unzipPath], { | ||
stdio: 'inherit', | ||
}); | ||
if (status !== 0) { | ||
fatal('Failure while extracting SDK zip'); | ||
} | ||
|
||
fs.renameSync(path.resolve(unzipPath, 'MacOSX.sdk'), eventualVersionedPath); | ||
deleteDir(SDKZip); | ||
deleteDir(unzipPath); | ||
} | ||
|
||
evmConfig.setEnvVar(evmConfig.currentName(), 'SDKROOT', eventualVersionedPath); | ||
} | ||
|
||
deleteDir(SDKZip); | ||
|
||
console.log(`${color.info} Now using SDK version ${color.path(getSDKVersion())}`); | ||
|
||
return true; | ||
} | ||
|
||
// Hash MacOSX.sdk directory zip with sha256. | ||
function hashFile(file) { | ||
console.log(`Calculating hash for ${color.path(file)}`); | ||
return cp | ||
.spawnSync('shasum', ['-a', '256', file]) | ||
.stdout.toString() | ||
.split(' ')[0] | ||
.trim(); | ||
} | ||
|
||
module.exports = { | ||
ensureSDK, | ||
}; |