diff --git a/common.js b/common.js index d505d0a..feb7e15 100644 --- a/common.js +++ b/common.js @@ -155,7 +155,15 @@ export function win2nix(path) { return path.replace(/\\/g, '/').replace(/ /g, '\\ ') } +// JRuby is installed after setupPath is called, so folder doesn't exist +function rubyIsUCRT(path) { + return !!(fs.existsSync(path) && + fs.readdirSync(path, { withFileTypes: true }).find(dirent => + dirent.isFile() && dirent.name.match(/^x64-ucrt-ruby\d{3}\.dll$/))) +} + export function setupPath(newPathEntries) { + let win_build_sys = null const envPath = windows ? 'Path' : 'PATH' const originalPath = process.env[envPath].split(path.delimiter) let cleanPath = originalPath.filter(entry => !/\bruby\b/i.test(entry)) @@ -176,8 +184,11 @@ export function setupPath(newPathEntries) { // Then add new path entries using core.addPath() let newPath if (windows) { + // main Ruby dll determines whether mingw or ucrt build + win_build_sys = rubyIsUCRT(newPathEntries[0]) ? 'ucrt64' : 'mingw64' + // add MSYS2 in path for all Rubies on Windows, as it provides a better bash shell and a native toolchain - const msys2 = ['C:\\msys64\\mingw64\\bin', 'C:\\msys64\\usr\\bin'] + const msys2 = [`C:\\msys64\\${win_build_sys}\\bin`, 'C:\\msys64\\usr\\bin'] newPath = [...newPathEntries, ...msys2] } else { newPath = newPathEntries @@ -189,4 +200,5 @@ export function setupPath(newPathEntries) { core.endGroup() core.addPath(newPath.join(path.delimiter)) + return win_build_sys } diff --git a/windows.js b/windows.js index b987dc4..3b7d6b6 100644 --- a/windows.js +++ b/windows.js @@ -50,15 +50,53 @@ export async function install(platform, engine, version) { let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version) - common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths]) - if (!inToolCache) { await downloadAndExtract(engine, version, url, base, rubyPrefix); } + const winMSYS2Type = common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths]) + + const virtualEnv = common.getVirtualEnvironmentName() + + if (( winMSYS2Type === 'ucrt64') || !['windows-2019', 'windows-2016'].includes(virtualEnv)) { + await installGCCTools(winMSYS2Type) + + if (!['windows-2019', 'windows-2016'].includes(virtualEnv)) { + await installMSY2Tools() + } + } + return rubyPrefix } +// Actions windows-2022 image does not contain any mingw or ucrt build tools. Install tools for it, +// and also install ucrt tools on earlier versions, which have msys2 and mingw tools preinstalled. +async function installGCCTools(type) { + const downloadPath = await common.measure(`Download ${type} build tools`, async () => { + let url = `https://github.com/MSP-Greg/setup-msys2-gcc/releases/download/msys2-gcc-pkgs/${type}.7z` + console.log(url) + return await tc.downloadTool(url) + }) + + await common.measure(`Extracting ${type} build tools`, async () => + // -aoa overwrite existing, -bd disable progress indicator + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', '-oC:\\msys64'], { silent: true })) +} + +// Actions windows-2022 image does not contain any MSYS2 build tools. Install tools for it. +// A subset of the MSYS2 base-devel group +async function installMSY2Tools() { + const downloadPath = await common.measure(`Download msys2 build tools`, async () => { + let url = `https://github.com/MSP-Greg/setup-msys2-gcc/releases/download/msys2-gcc-pkgs/msys2.7z` + console.log(url) + return await tc.downloadTool(url) + }) + + await common.measure(`Extracting msys2 build tools`, async () => + // -aoa overwrite existing, -bd disable progress indicator + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', '-oC:\\msys64'], { silent: true })) +} + async function downloadAndExtract(engine, version, url, base, rubyPrefix) { const parentDir = path.dirname(rubyPrefix) @@ -68,7 +106,7 @@ async function downloadAndExtract(engine, version, url, base, rubyPrefix) { }) await common.measure('Extracting Ruby', async () => - exec.exec('7z', ['x', downloadPath, `-xr!${base}\\share\\doc`, `-o${parentDir}`], { silent: true })) + exec.exec('7z', ['x', downloadPath, '-bd', `-xr!${base}\\share\\doc`, `-o${parentDir}`], { silent: true })) if (base !== path.basename(rubyPrefix)) { await io.mv(path.join(parentDir, base), rubyPrefix)