diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b97df88b..ad4ddce59 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -134,7 +134,7 @@ jobs: echo 'ridk is unavailable' } } elseif ($plat.Contains('mswin')) { - &"$env:VCPKG_INSTALLATION_ROOT\vcpkg" list + Get-ChildItem "$env:VCPKG_INSTALLATION_ROOT\installed\vcpkg\info" } - name: RbConfig::CONFIG run: ruby -rrbconfig -rpp -e 'pp RbConfig::CONFIG' diff --git a/common.js b/common.js index 43acc26c7..d45784634 100644 --- a/common.js +++ b/common.js @@ -12,7 +12,7 @@ const linuxOSInfo = require('linux-os-info') export const windows = (os.platform() === 'win32') // Extract to SSD on Windows, see https://github.com/ruby/setup-ruby/pull/14 -export const drive = (windows ? (process.env['GITHUB_WORKSPACE'] || 'C')[0] : undefined) +export const drive = (windows ? (process.env['RUNNER_TEMP'] || 'C')[0] : undefined) export const inputs = { selfHosted: undefined @@ -334,7 +334,7 @@ function engineToToolCacheName(engine) { }[engine] } -export function getToolCacheRubyPrefix(platform, engine, version) { +export function getToolCacheRubyPrefix(_platform, engine, version) { const toolCache = getToolCachePath() return path.join(toolCache, engineToToolCacheName(engine), version, os.arch()) } @@ -356,15 +356,7 @@ 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|vcruntime\d{3})-ruby\d{3}\.dll$/))) -} - export function setupPath(newPathEntries) { - let msys2Type = null const envPath = windows ? 'Path' : 'PATH' const originalPath = process.env[envPath].split(path.delimiter) let cleanPath = originalPath.filter(entry => !/\bruby\b/i.test(entry)) @@ -382,29 +374,13 @@ export function setupPath(newPathEntries) { core.exportVariable(envPath, cleanPath.join(path.delimiter)) } - // Then add new path entries using core.addPath() - let newPath - const windowsToolchain = core.getInput('windows-toolchain') - if (windows && windowsToolchain !== 'none') { - // main Ruby dll determines whether mingw or ucrt build - msys2Type = os.arch() === 'arm64' - ? 'clangarm64' - : 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\\${msys2Type}\\bin`, 'C:\\msys64\\usr\\bin'] - newPath = [...newPathEntries, ...msys2] - } else { - newPath = newPathEntries - } console.log(`Entries added to ${envPath} to use selected Ruby:`) - for (const entry of newPath) { + for (const entry of newPathEntries) { console.log(` ${entry}`) } core.endGroup() - core.addPath(newPath.join(path.delimiter)) - return msys2Type + core.addPath(newPathEntries.join(path.delimiter)) } export async function setupJavaHome(rubyPrefix) { diff --git a/dist/index.js b/dist/index.js index d42d55d26..803a6e557 100644 --- a/dist/index.js +++ b/dist/index.js @@ -332,7 +332,7 @@ const linuxOSInfo = __nccwpck_require__(8487) const windows = (os.platform() === 'win32') // Extract to SSD on Windows, see https://github.com/ruby/setup-ruby/pull/14 -const drive = (windows ? (process.env['GITHUB_WORKSPACE'] || 'C')[0] : undefined) +const drive = (windows ? (process.env['RUNNER_TEMP'] || 'C')[0] : undefined) const inputs = { selfHosted: undefined @@ -654,7 +654,7 @@ function engineToToolCacheName(engine) { }[engine] } -function getToolCacheRubyPrefix(platform, engine, version) { +function getToolCacheRubyPrefix(_platform, engine, version) { const toolCache = getToolCachePath() return path.join(toolCache, engineToToolCacheName(engine), version, os.arch()) } @@ -676,15 +676,7 @@ 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|vcruntime\d{3})-ruby\d{3}\.dll$/))) -} - function setupPath(newPathEntries) { - let msys2Type = null const envPath = windows ? 'Path' : 'PATH' const originalPath = process.env[envPath].split(path.delimiter) let cleanPath = originalPath.filter(entry => !/\bruby\b/i.test(entry)) @@ -702,29 +694,13 @@ function setupPath(newPathEntries) { core.exportVariable(envPath, cleanPath.join(path.delimiter)) } - // Then add new path entries using core.addPath() - let newPath - const windowsToolchain = core.getInput('windows-toolchain') - if (windows && windowsToolchain !== 'none') { - // main Ruby dll determines whether mingw or ucrt build - msys2Type = os.arch() === 'arm64' - ? 'clangarm64' - : 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\\${msys2Type}\\bin`, 'C:\\msys64\\usr\\bin'] - newPath = [...newPathEntries, ...msys2] - } else { - newPath = newPathEntries - } console.log(`Entries added to ${envPath} to use selected Ruby:`) - for (const entry of newPath) { + for (const entry of newPathEntries) { console.log(` ${entry}`) } core.endGroup() - core.addPath(newPath.join(path.delimiter)) - return msys2Type + core.addPath(newPathEntries.join(path.delimiter)) } async function setupJavaHome(rubyPrefix) { @@ -74085,8 +74061,15 @@ async function install(platform, engine, version) { rubyPrefix = path.join(os.homedir(), '.rubies', `${engine}-${version}`) } + const paths = [path.join(rubyPrefix, 'bin')] + + // JRuby can use compiled extension code via ffi, so make sure gcc exists. + if (platform.startsWith('windows') && engine === 'jruby') { + paths.push(...await (__nccwpck_require__(3216).installJRubyTools)()) + } + // Set the PATH now, so the MSYS2 'tar' is in Path on Windows - common.setupPath([path.join(rubyPrefix, 'bin')]) + common.setupPath(paths) if (!inToolCache) { await io.mkdirP(rubyPrefix) @@ -74258,48 +74241,23 @@ __nccwpck_require__.r(__webpack_exports__); /* harmony export */ __nccwpck_require__.d(__webpack_exports__, { /* harmony export */ "getAvailableVersions": () => (/* binding */ getAvailableVersions), /* harmony export */ "install": () => (/* binding */ install), -/* harmony export */ "installJRubyTools": () => (/* binding */ installJRubyTools), -/* harmony export */ "addVCVARSEnv": () => (/* binding */ addVCVARSEnv) +/* harmony export */ "installJRubyTools": () => (/* binding */ installJRubyTools) /* harmony export */ }); // 7z arguments // -aoa overwrite existing, -bd disable progress indicator -// OpenSSL version detection is needed in installGCCTools and installJRubyTools - const fs = __nccwpck_require__(7147) const os = __nccwpck_require__(2037) const path = __nccwpck_require__(1017) const cp = __nccwpck_require__(2081) const core = __nccwpck_require__(2186) const exec = __nccwpck_require__(1514) -const io = __nccwpck_require__(7436) const tc = __nccwpck_require__(7784) const common = __nccwpck_require__(4717) const rubyInstallerVersions = __nccwpck_require__(6459) +const toolchainVersions = __nccwpck_require__(3344) -const drive = common.drive - -const msys2GCCReleaseURI = 'https://github.com/ruby/setup-msys2-gcc/releases/download' - -const msys2BasePath = process.env['GHCUP_MSYS2'] || 'C:\\msys64' -const vcPkgBasePath = process.env['VCPKG_INSTALLATION_ROOT'] - -// needed for Ruby 2.0-2.3, cert file used by Git for Windows -const certFile = [ - 'C:\\Program Files\\Git\\mingw64\\etc\\ssl\\cert.pem', - 'C:\\Program Files\\Git\\mingw64\\ssl\\cert.pem', - 'C:\\Program Files\\Git\\clangarm64\\etc\\ssl\\cert.pem', - 'C:\\Program Files\\Git\\clangarm64\\ssl\\cert.pem' -].find(file => fs.existsSync(file)) -if (certFile === undefined) { - throw new Error("Cannot find Git's cert file") -} - -// location & path for old RubyInstaller DevKit (MSYS1), used with Ruby 2.0-2.3 -const msys1 = `${drive}:\\DevKit64` -const msysPathEntries = [`${msys1}\\mingw\\x86_64-w64-mingw32\\bin`, `${msys1}\\mingw\\bin`, `${msys1}\\bin`] - -function getAvailableVersions(platform, engine) { +function getAvailableVersions(_platform, engine) { if (engine === 'ruby') { return Object.keys(rubyInstallerVersions).filter(version => os.arch() in rubyInstallerVersions[version]) } else { @@ -74310,14 +74268,10 @@ function getAvailableVersions(platform, engine) { async function install(platform, engine, version) { const url = rubyInstallerVersions[version][os.arch()] - // The windows-2016 and windows-2019 images have MSYS2 build tools (C:/msys64/usr) - // and MinGW build tools installed. The windows-2022 image has neither. - const hasMSYS2PreInstalled = ['windows-2019', 'windows-2016'].includes(platform) - if (!url.endsWith('.7z')) { throw new Error(`URL should end in .7z: ${url}`) } - const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length) + const base = path.posix.basename(url, '.7z') let rubyPrefix, inToolCache if (common.shouldUseToolCache(engine, version)) { @@ -74328,230 +74282,202 @@ async function install(platform, engine, version) { rubyPrefix = common.getToolCacheRubyPrefix(platform, engine, version) } } else { - rubyPrefix = `${drive}:\\${base}` + rubyPrefix = `${common.drive}:\\${base}` } if (!inToolCache) { await downloadAndExtract(engine, version, url, base, rubyPrefix); } + const paths = [`${rubyPrefix}\\bin`] const windowsToolchain = core.getInput('windows-toolchain') if (windowsToolchain === 'none') { - common.setupPath([`${rubyPrefix}\\bin`]) + common.setupPath(paths) return rubyPrefix } - let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version) - const msys2Type = common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths]) - - // install msys2 tools for all Ruby versions, only install mingw or ucrt for Rubies >= 2.4 + const toolchainUrl = toolchainVersions[version][os.arch()] - if (!hasMSYS2PreInstalled) { - await installMSYS2Tools() - } - - // windows 2016 and 2019 need ucrt64 installed, 2022 and future images need - // ucrt64 or mingw64 installed, depending on Ruby version - if ((msys2Type === 'ucrt64') || (common.floatVersion(version) >= 2.4)) { - await installGCCTools(msys2Type, version) - } + // Examples: + // - DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe + // - msys2-clangarm64.7z + // - vcpkg-x64-windows.7z + const toolchainName = path.posix.basename(toolchainUrl).split('-')[0].toLowerCase() - if (version === 'mswin') { - await installVCPkg() - } + if (toolchainName === 'msys2') { + paths.push(...await installMSYS2(toolchainUrl, rubyPrefix)) + } else { + if (toolchainName === 'vcpkg') { + paths.push(...await installVCPKG(toolchainUrl)) + } else if (toolchainName === 'devkit') { + paths.push(...await installMSYS1(toolchainUrl)) + } else { + throw new Error(`Unknown toolchain type: ${toolchainUrl}`) + } - const ridk = `${rubyPrefix}\\bin\\ridk.cmd` - if (fs.existsSync(ridk)) { - await common.measure('Adding ridk env variables', async () => addRidkEnv(ridk)) + // Install msys2 for other rubies to provide better command line tools + paths.push(...await installMSYS2(toolchainVersions['head'][os.arch()])) } + common.setupPath(paths) 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, version) { - // 2022-Dec ruby/msys2-gcc-pkgs now uses a suffix to delineate different archive versions. - // At present, the only use is to indicate the included OpenSSL version. - // With no suffix, archives include OpenSSL 1.1.1, with a '-3.0' suffix, they include - // OpenSSL 3.0.x. Note that the mswin archive uses OpenSSL 3. - // As of Jan-2023, OpenSSL 3 is used in Ruby 3.2 & all head versions. MSYS2 updated - // to OpenSSL 3 on 14-Jan-2023. - let suffix = '' - if (common.isHeadVersion(version) || common.floatVersion(version) >= 3.2) { - suffix = '-3.0' - } - const downloadPath = await common.measure(`Downloading ${type}${suffix} build tools`, async () => { - let url = `${msys2GCCReleaseURI}/msys2-gcc-pkgs/${type}${suffix}.7z` +async function downloadAndExtract(engine, version, url, base, rubyPrefix) { + const downloadPath = await common.measure('Downloading Ruby', async () => { console.log(url) return await tc.downloadTool(url) }) - await common.measure(`Extracting ${type}${suffix} build tools`, async () => - exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${msys2BasePath}`], { 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 installMSYS2Tools() { - const downloadPath = await common.measure(`Downloading msys2 build tools`, async () => { - const suffix = os.arch() === 'arm64' ? '-arm64' : '' + const extractPath = process.env.RUNNER_TEMP + await common.measure('Extracting Ruby', async () => + // -xr extract but exclude share\doc files + exec.exec('7z', ['x', downloadPath, '-bd', `-xr!${base}\\share\\doc`, `-o${extractPath}`], { silent: true })) - let url = `${msys2GCCReleaseURI}/msys2-gcc-pkgs/msys2${suffix}.7z` - console.log(url) - return await tc.downloadTool(url) - }) + const parentDir = path.dirname(rubyPrefix) + if (!fs.existsSync(parentDir)) { + fs.mkdirSync(parentDir, { recursive: true }) + } - // need to remove all directories, since they may indicate old packages are installed, - // otherwise, error of "error: duplicated database entry" - fs.rmSync(`${msys2BasePath}\\var\\lib\\pacman\\local`, { recursive: true, force: true }) + const extractedPath = path.join(extractPath, base) + if (extractedPath[0] === rubyPrefix[0]) { + fs.renameSync(extractedPath, rubyPrefix) + } else { + fs.symlinkSync(extractedPath, rubyPrefix, 'junction') + } - await common.measure(`Extracting msys2 build tools`, async () => - exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${msys2BasePath}`], { silent: true })) + if (common.shouldUseToolCache(engine, version)) { + common.createToolCacheCompleteFile(rubyPrefix) + } } -// Windows JRuby can install gems that require compile tools, only needed for -// windows-2022 and later images async function installJRubyTools() { - await installMSYS2Tools() - await installGCCTools(os.arch() === 'arm64' ? 'clangarm64' : 'mingw64', '3.4') -} - -// Install vcpkg files needed to build mswin Ruby -async function installVCPkg() { - const downloadPath = await common.measure(`Downloading mswin vcpkg packages`, async () => { - let url = `${msys2GCCReleaseURI}/msys2-gcc-pkgs/mswin.7z` - console.log(url) - return await tc.downloadTool(url) - }) - - await common.measure(`Extracting mswin vcpkg packages`, async () => - exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${vcPkgBasePath}`], { silent: true })) + return await installMSYS2(toolchainVersions['head'][os.arch()]) } -async function downloadAndExtract(engine, version, url, base, rubyPrefix) { - const parentDir = path.dirname(rubyPrefix) - - const downloadPath = await common.measure('Downloading Ruby', async () => { +async function installMSYS2(url, rubyPrefix = process.env.RUNNER_TEMP) { + const downloadPath = await common.measure('Downloading msys2 build tools', async () => { console.log(url) return await tc.downloadTool(url) }) - await common.measure('Extracting Ruby', async () => - // -xr extract but exclude share\doc files - exec.exec('7z', ['x', downloadPath, '-bd', `-xr!${base}\\share\\doc`, `-o${parentDir}`], { silent: true })) + const extractPath = path.join(process.env.RUNNER_TEMP, 'msys64') + await common.measure('Extracting msys2 build tools', async () => + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${extractPath}`], { silent: true })) - if (base !== path.basename(rubyPrefix)) { - await io.mv(path.join(parentDir, base), rubyPrefix) + // https://github.com/oneclick/rubyinstaller2/blob/HEAD/lib/ruby_installer/build/msys2_installation.rb + // + // ri2 searches for msys64 in the following order: + // - ENV["MSYS2_PATH"] + // - File.join(RbConfig::TOPDIR, "msys64") + // - File.join(File.dirname(RbConfig::TOPDIR), "msys64") + // - "C:\msys64" + // - ... + // + // The first option ENV["MSYS2_PATH"] is only supported in ruby >=3.0.7. + // Therefore we use the second option to avoid conflict with existing "C:\msys64" + const msys2Path = path.join(rubyPrefix, 'msys64') + if (extractPath !== msys2Path) { + fs.symlinkSync(extractPath, msys2Path, 'junction') } - if (common.shouldUseToolCache(engine, version)) { - common.createToolCacheCompleteFile(rubyPrefix) + const ridk = `${rubyPrefix}\\bin\\ridk.cmd` + if (fs.existsSync(ridk)) { + await common.measure('Setting up ridk environment', async () => exportCommandEnv(`set MAKE=make && "${ridk}" enable`)) } -} -async function setupMingw(version) { - core.exportVariable('MAKE', 'make.exe') - - // rename these to avoid confusion when Ruby is using OpenSSL 1.0.2. - // most current extconf files look for 1.1.x dll files first, which is the version of the renamed files - if (common.floatVersion(version) <= 2.4) { - renameSystem32Dlls() - } + // Examples: + // - msys2-clangarm64.7z + // - msys2-ucrt64-gcc@14.7z + // - msys2-mingw64-gcc@14-openssl@1.1.7z + const msys2Type = path.posix.basename(url).split(/[-.]/)[1] + return [`${msys2Path}\\${msys2Type}\\bin`, `${msys2Path}\\usr\\bin`] +} - if (common.floatVersion(version) <= 2.3) { - core.exportVariable('SSL_CERT_FILE', certFile) - await common.measure('Installing MSYS1', async () => installMSYS1(version)) - return msysPathEntries - } else { - return [] +async function installMSYS1(url) { + const certFile = [ + 'C:\\Program Files\\Git\\mingw64\\etc\\ssl\\cert.pem', + 'C:\\Program Files\\Git\\mingw64\\ssl\\cert.pem', + ].find(file => fs.existsSync(file)) + if (certFile === undefined) { + throw new Error("Cannot find Git's cert file") } -} -// Ruby 2.0-2.3 -async function installMSYS1(version) { - const url = 'https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe' - const downloadPath = await tc.downloadTool(url) - await exec.exec('7z', ['x', downloadPath, `-o${msys1}`], { silent: true }) + const downloadPath = await common.measure('Downloading msys1 build tools', async () => { + console.log(url) + return await tc.downloadTool(url) + }) - // below are set in the old devkit.rb file ? - core.exportVariable('RI_DEVKIT', msys1) - core.exportVariable('CC' , 'gcc') - core.exportVariable('CXX', 'g++') - core.exportVariable('CPP', 'cpp') - core.info(`Installed RubyInstaller DevKit for Ruby ${version}`) -} + const msys1Path = `${common.drive}:\\DevKit64` + await common.measure('Extracting msys1 build tools', async () => + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${msys1Path}`], { silent: true })) + + await common.measure('Setting up DevKit environment', async () => { + // ssl dlls cause issues with msys1 Rubies + const sys32 = 'C:\\Windows\\System32\\' + const badFiles = [`${sys32}libcrypto-1_1-x64.dll`, `${sys32}libssl-1_1-x64.dll`] + const existing = badFiles.filter((dll) => fs.existsSync(dll)) + if (existing.length > 0) { + core.warning(`Renaming ${existing.join(' and ')} to avoid dll resolution conflicts on Ruby < 2.4`) + existing.forEach(dll => fs.renameSync(dll, `${dll}_`)) + } + + exportEnv({ + CC: 'gcc', + CPP: 'cpp', + CXX: 'g++', + MAKE: 'make', + RI_DEVKIT: msys1Path, + SSL_CERT_FILE: certFile + }) + }) -async function setupMSWin() { - core.exportVariable('MAKE', 'nmake.exe') - return await common.measure('Setting up MSVC environment', async () => addVCVARSEnv()) + return [`${msys1Path}\\mingw\\x86_64-w64-mingw32\\bin`, `${msys1Path}\\mingw\\bin`, `${msys1Path}\\bin`] } /* Sets MSVC environment for use in Actions * allows steps to run without running vcvars*.bat, also for PowerShell - * adds a convenience VCVARS environment variable * this assumes a single Visual Studio version being available in the Windows images */ -function addVCVARSEnv() { - let cmd = 'vswhere -latest -property installationPath' - let vcVars = `${cp.execSync(cmd).toString().trim()}\\VC\\Auxiliary\\Build\\vcvars64.bat` - - if (!fs.existsSync(vcVars)) { - throw new Error(`Missing vcVars file: ${vcVars}`) - } - core.exportVariable('VCVARS', vcVars) +async function installVCPKG(url) { + const downloadPath = await common.measure('Downloading mswin vcpkg packages', async () => { + console.log(url) + return await tc.downloadTool(url) + }) - cmd = `cmd.exe /c ""${vcVars}" && set"` + const extractPath = process.env.VCPKG_INSTALLATION_ROOT + await common.measure('Extracting mswin vcpkg packages', async () => + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${extractPath}`], { silent: true })) - let newEnv = new Map() - let newSet = cp.execSync(cmd).toString().trim().split(/\r?\n/) - newSet = newSet.filter(line => /\S=\S/.test(line)) - newSet.forEach(s => { - let [k,v] = common.partition(s, '=') - newEnv.set(k,v) - }) + return await common.measure('Setting up MSVC environment', async () => { + const cmd = 'vswhere -latest -property installationPath' + const vcVarsBat = os.arch() === 'arm64' ? 'vcvarsarm64.bat' : 'vcvars64.bat' + const vcVars = `${cp.execSync(cmd).toString().trim()}\\VC\\Auxiliary\\Build\\${vcVarsBat}` - let newPathEntries = undefined - for (let [k, v] of newEnv) { - if (process.env[k] !== v) { - if (/^Path$/i.test(k)) { - const newPathStr = v.replace(`${path.delimiter}${process.env['Path']}`, '') - newPathEntries = newPathStr.split(path.delimiter) - } else { - core.exportVariable(k, v) - } + if (!fs.existsSync(vcVars)) { + throw new Error(`Missing vcVars file: ${vcVars}`) } - } - return newPathEntries -} -// ssl files cause issues with non RI2 Rubies (<2.4) and ruby/ruby's CI from build folder due to dll resolution -function renameSystem32Dlls() { - const sys32 = 'C:\\Windows\\System32\\' - const badFiles = [`${sys32}libcrypto-1_1-x64.dll`, `${sys32}libssl-1_1-x64.dll`] - const existing = badFiles.filter((dll) => fs.existsSync(dll)) - if (existing.length > 0) { - console.log(`Renaming ${existing.join(' and ')} to avoid dll resolution conflicts on Ruby <= 2.4`) - existing.forEach(dll => fs.renameSync(dll, `${dll}_`)) - } + return exportCommandEnv(`set MAKE=nmake && "${vcVars}"`) + }) } -// Sets MSYS2 ENV variables set from running `ridk enable` -function addRidkEnv(ridk) { - let newEnv = new Map() - let cmd = `cmd.exe /c "${ridk} enable && set"` - let newSet = cp.execSync(cmd).toString().trim().split(/\r?\n/) - newSet = newSet.filter(line => /^\S+=\S+/.test(line)) - newSet.forEach(s => { - let [k, v] = common.partition(s, '=') - newEnv.set(k, v) - }) +// Run a cmd command, export its environment, and return new paths +function exportCommandEnv(command) { + const cmd = `cmd.exe /s /c "${command} >NUL && "${process.execPath}" -e console.log(JSON.stringify(process.env))"` + const env = JSON.parse(cp.execSync(cmd).toString()) - for (let [k, v] of newEnv) { + const paths = env.Path.replace(`${path.delimiter}${process.env.Path}`, '').split(path.delimiter) + delete env.Path + + exportEnv(env) + return paths +} + +function exportEnv(env) { + for (const [k, v] of Object.entries(env)) { if (process.env[k] !== v) { - if (!/^Path$/i.test(k)) { - console.log(`${k}=${v}`) - core.exportVariable(k, v) - } + console.log(`${k}=${v}`) + core.exportVariable(k, v) } } } @@ -74767,6 +74693,14 @@ module.exports = JSON.parse('{"ruby":["1.9.3-p551","2.0.0-p648","2.1.9","2.2.10" /***/ }), +/***/ 3344: +/***/ ((module) => { + +"use strict"; +module.exports = JSON.parse('{"2.0.0":{"x64":"https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"},"2.1.9":{"x64":"https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"},"2.2.6":{"x64":"https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"},"2.3.0":{"x64":"https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"},"2.3.1":{"x64":"https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"},"2.3.3":{"x64":"https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"},"2.4.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.9":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.4.10":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.8":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.5.9":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.8":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.9":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.6.10":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"2.7.8":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.0.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.1.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z"},"3.2.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.2.8":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.0":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.1":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.2":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.3":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.4":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.5":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.6":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.7":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.3.8":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.4.1":{"arm64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64-mingw-w64@r688.7z","x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.4.2":{"arm64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64-mingw-w64@r688.7z","x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"3.4.3":{"arm64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64-mingw-w64@r688.7z","x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z"},"head":{"arm64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64.7z","x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64.7z"},"mingw":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64.7z"},"mswin":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/vcpkg-x64-windows.7z"},"ucrt":{"x64":"https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64.7z"}}'); + +/***/ }), + /***/ 6459: /***/ ((module) => { @@ -74922,13 +74856,6 @@ async function setupRuby(options = {}) { createGemRC(engine, version) envPreInstall() - // JRuby can use compiled extension code, so make sure gcc exists. - // As of Jan-2022, JRuby compiles against msvcrt. - if (platform.startsWith('windows') && engine === 'jruby' && - !fs.existsSync('C:\\msys64\\mingw64\\bin\\gcc.exe')) { - await (__nccwpck_require__(3216).installJRubyTools)() - } - const rubyPrefix = await installer.install(platform, engine, version) await common.measure('Print Ruby version', async () => diff --git a/generate-windows-versions.rb b/generate-windows-versions.rb index 80ad57065..6fb1fd26d 100644 --- a/generate-windows-versions.rb +++ b/generate-windows-versions.rb @@ -1,11 +1,11 @@ -require 'net/http' +require 'open-uri' require 'yaml' require 'json' min_requirements = ['~> 2.0.0', '~> 2.1.9', '>= 2.2.6'].map { |req| Gem::Requirement.new(req) } url = 'https://raw.githubusercontent.com/oneclick/rubyinstaller.org-website/master/_data/downloads.yaml' -entries = YAML.load(Net::HTTP.get(URI(url)), symbolize_names: true) +entries = YAML.load(URI.open(url, &:read), symbolize_names: true) versions = entries.select { |entry| entry[:filetype] == 'rubyinstaller7z' and @@ -31,18 +31,63 @@ min_requirements.any? { |req| req.satisfied_by?(Gem::Version.new(version)) } }.to_h +latest_version = Gem::Version.new(versions.keys.last) +head_version = Gem::Version.new("#{latest_version.bump}.0dev") + versions['head'] = { - 'arm64': 'https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-arm.7z', - 'x64': 'https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-x64.7z' + 'arm64' => 'https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-arm.7z', + 'x64' => 'https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-x64.7z' } versions['mingw'] = { - 'x64': 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-mingw.7z' + 'x64' => 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-mingw.7z' } versions['mswin'] = { - 'x64': 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-mswin.7z' + 'x64' => 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-mswin.7z' } versions['ucrt'] = { - 'x64': 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-ucrt.7z' + 'x64' => 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-ucrt.7z' } File.binwrite 'windows-versions.json', "#{JSON.pretty_generate(versions)}\n" + +base_url = 'https://github.com/ruby/setup-msys2-gcc/releases/latest/download/windows-toolchain.json' +windows_toolchain = JSON.parse(URI.open(base_url, &:read), symbolize_names: true) + +versions.each do |raw_version, archs| + version = Gem::Version.correct?(raw_version) ? Gem::Version.new(raw_version) : head_version + + archs.each_key do |raw_arch| + arch = raw_arch == 'arm64' ? 'aarch64' : raw_arch + + platform = + case raw_version + when 'head', 'ucrt' + "#{arch}-mingw-ucrt" + when 'mingw' + "#{arch}-mingw32" + when 'mswin' + "#{arch}-mswin64" + else + if version >= Gem::Version.new('3.1.0.dev') + "#{arch}-mingw-ucrt" + else + "#{arch}-mingw32" + end + end + + toolchain = + windows_toolchain.select do |pkg| + pkg[:platform] == platform && pkg[:required_ruby_version].any? do |requirement| + Gem::Requirement.new(requirement).satisfied_by?(version) + end + end + + unless toolchain.one? + raise "#{toolchain.empty? ? 'no' : 'multiple'} toolchains found for #{raw_version} #{raw_arch}: #{toolchain}" + end + + archs[raw_arch] = URI.join(base_url, toolchain.first[:href]) + end +end + +File.binwrite 'windows-toolchain-versions.json', "#{JSON.pretty_generate(versions)}\n" diff --git a/index.js b/index.js index 1bba0a4be..62e46feb9 100644 --- a/index.js +++ b/index.js @@ -70,13 +70,6 @@ export async function setupRuby(options = {}) { createGemRC(engine, version) envPreInstall() - // JRuby can use compiled extension code, so make sure gcc exists. - // As of Jan-2022, JRuby compiles against msvcrt. - if (platform.startsWith('windows') && engine === 'jruby' && - !fs.existsSync('C:\\msys64\\mingw64\\bin\\gcc.exe')) { - await require('./windows').installJRubyTools() - } - const rubyPrefix = await installer.install(platform, engine, version) await common.measure('Print Ruby version', async () => diff --git a/ruby-builder.js b/ruby-builder.js index 8244fec49..93a690960 100644 --- a/ruby-builder.js +++ b/ruby-builder.js @@ -46,8 +46,15 @@ export async function install(platform, engine, version) { rubyPrefix = path.join(os.homedir(), '.rubies', `${engine}-${version}`) } + const paths = [path.join(rubyPrefix, 'bin')] + + // JRuby can use compiled extension code via ffi, so make sure gcc exists. + if (platform.startsWith('windows') && engine === 'jruby') { + paths.push(...await require('./windows').installJRubyTools()) + } + // Set the PATH now, so the MSYS2 'tar' is in Path on Windows - common.setupPath([path.join(rubyPrefix, 'bin')]) + common.setupPath(paths) if (!inToolCache) { await io.mkdirP(rubyPrefix) diff --git a/windows-toolchain-versions.json b/windows-toolchain-versions.json new file mode 100644 index 000000000..6910dcd3c --- /dev/null +++ b/windows-toolchain-versions.json @@ -0,0 +1,258 @@ +{ + "2.0.0": { + "x64": "https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" + }, + "2.1.9": { + "x64": "https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" + }, + "2.2.6": { + "x64": "https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" + }, + "2.3.0": { + "x64": "https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" + }, + "2.3.1": { + "x64": "https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" + }, + "2.3.3": { + "x64": "https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" + }, + "2.4.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.9": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.4.10": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.8": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.5.9": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.8": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.9": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.6.10": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "2.7.8": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.0.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.1.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14-openssl@1.1.7z" + }, + "3.2.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.2.8": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.0": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.1": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.2": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.3": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.4": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.5": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.6": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.7": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.3.8": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.4.1": { + "arm64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64-mingw-w64@r688.7z", + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.4.2": { + "arm64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64-mingw-w64@r688.7z", + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "3.4.3": { + "arm64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64-mingw-w64@r688.7z", + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64-mingw-w64@r688-gcc@14.7z" + }, + "head": { + "arm64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-clangarm64.7z", + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64.7z" + }, + "mingw": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-mingw64.7z" + }, + "mswin": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/vcpkg-x64-windows.7z" + }, + "ucrt": { + "x64": "https://github.com/ruby/setup-msys2-gcc/releases/latest/download/msys2-ucrt64.7z" + } +} diff --git a/windows.js b/windows.js index c3b6c2304..f998f6797 100644 --- a/windows.js +++ b/windows.js @@ -1,42 +1,18 @@ // 7z arguments // -aoa overwrite existing, -bd disable progress indicator -// OpenSSL version detection is needed in installGCCTools and installJRubyTools - const fs = require('fs') const os = require('os') const path = require('path') const cp = require('child_process') const core = require('@actions/core') const exec = require('@actions/exec') -const io = require('@actions/io') const tc = require('@actions/tool-cache') const common = require('./common') const rubyInstallerVersions = require('./windows-versions.json') +const toolchainVersions = require('./windows-toolchain-versions.json') -const drive = common.drive - -const msys2GCCReleaseURI = 'https://github.com/ruby/setup-msys2-gcc/releases/download' - -const msys2BasePath = process.env['GHCUP_MSYS2'] || 'C:\\msys64' -const vcPkgBasePath = process.env['VCPKG_INSTALLATION_ROOT'] - -// needed for Ruby 2.0-2.3, cert file used by Git for Windows -const certFile = [ - 'C:\\Program Files\\Git\\mingw64\\etc\\ssl\\cert.pem', - 'C:\\Program Files\\Git\\mingw64\\ssl\\cert.pem', - 'C:\\Program Files\\Git\\clangarm64\\etc\\ssl\\cert.pem', - 'C:\\Program Files\\Git\\clangarm64\\ssl\\cert.pem' -].find(file => fs.existsSync(file)) -if (certFile === undefined) { - throw new Error("Cannot find Git's cert file") -} - -// location & path for old RubyInstaller DevKit (MSYS1), used with Ruby 2.0-2.3 -const msys1 = `${drive}:\\DevKit64` -const msysPathEntries = [`${msys1}\\mingw\\x86_64-w64-mingw32\\bin`, `${msys1}\\mingw\\bin`, `${msys1}\\bin`] - -export function getAvailableVersions(platform, engine) { +export function getAvailableVersions(_platform, engine) { if (engine === 'ruby') { return Object.keys(rubyInstallerVersions).filter(version => os.arch() in rubyInstallerVersions[version]) } else { @@ -47,14 +23,10 @@ export function getAvailableVersions(platform, engine) { export async function install(platform, engine, version) { const url = rubyInstallerVersions[version][os.arch()] - // The windows-2016 and windows-2019 images have MSYS2 build tools (C:/msys64/usr) - // and MinGW build tools installed. The windows-2022 image has neither. - const hasMSYS2PreInstalled = ['windows-2019', 'windows-2016'].includes(platform) - if (!url.endsWith('.7z')) { throw new Error(`URL should end in .7z: ${url}`) } - const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length) + const base = path.posix.basename(url, '.7z') let rubyPrefix, inToolCache if (common.shouldUseToolCache(engine, version)) { @@ -65,230 +37,202 @@ export async function install(platform, engine, version) { rubyPrefix = common.getToolCacheRubyPrefix(platform, engine, version) } } else { - rubyPrefix = `${drive}:\\${base}` + rubyPrefix = `${common.drive}:\\${base}` } if (!inToolCache) { await downloadAndExtract(engine, version, url, base, rubyPrefix); } + const paths = [`${rubyPrefix}\\bin`] const windowsToolchain = core.getInput('windows-toolchain') if (windowsToolchain === 'none') { - common.setupPath([`${rubyPrefix}\\bin`]) + common.setupPath(paths) return rubyPrefix } - let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version) - const msys2Type = common.setupPath([`${rubyPrefix}\\bin`, ...toolchainPaths]) - - // install msys2 tools for all Ruby versions, only install mingw or ucrt for Rubies >= 2.4 - - if (!hasMSYS2PreInstalled) { - await installMSYS2Tools() - } + const toolchainUrl = toolchainVersions[version][os.arch()] - // windows 2016 and 2019 need ucrt64 installed, 2022 and future images need - // ucrt64 or mingw64 installed, depending on Ruby version - if ((msys2Type === 'ucrt64') || (common.floatVersion(version) >= 2.4)) { - await installGCCTools(msys2Type, version) - } + // Examples: + // - DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe + // - msys2-clangarm64.7z + // - vcpkg-x64-windows.7z + const toolchainName = path.posix.basename(toolchainUrl).split('-')[0].toLowerCase() - if (version === 'mswin') { - await installVCPkg() - } + if (toolchainName === 'msys2') { + paths.push(...await installMSYS2(toolchainUrl, rubyPrefix)) + } else { + if (toolchainName === 'vcpkg') { + paths.push(...await installVCPKG(toolchainUrl)) + } else if (toolchainName === 'devkit') { + paths.push(...await installMSYS1(toolchainUrl)) + } else { + throw new Error(`Unknown toolchain type: ${toolchainUrl}`) + } - const ridk = `${rubyPrefix}\\bin\\ridk.cmd` - if (fs.existsSync(ridk)) { - await common.measure('Adding ridk env variables', async () => addRidkEnv(ridk)) + // Install msys2 for other rubies to provide better command line tools + paths.push(...await installMSYS2(toolchainVersions['head'][os.arch()])) } + common.setupPath(paths) 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, version) { - // 2022-Dec ruby/msys2-gcc-pkgs now uses a suffix to delineate different archive versions. - // At present, the only use is to indicate the included OpenSSL version. - // With no suffix, archives include OpenSSL 1.1.1, with a '-3.0' suffix, they include - // OpenSSL 3.0.x. Note that the mswin archive uses OpenSSL 3. - // As of Jan-2023, OpenSSL 3 is used in Ruby 3.2 & all head versions. MSYS2 updated - // to OpenSSL 3 on 14-Jan-2023. - let suffix = '' - if (common.isHeadVersion(version) || common.floatVersion(version) >= 3.2) { - suffix = '-3.0' - } - const downloadPath = await common.measure(`Downloading ${type}${suffix} build tools`, async () => { - let url = `${msys2GCCReleaseURI}/msys2-gcc-pkgs/${type}${suffix}.7z` +async function downloadAndExtract(engine, version, url, base, rubyPrefix) { + const downloadPath = await common.measure('Downloading Ruby', async () => { console.log(url) return await tc.downloadTool(url) }) - await common.measure(`Extracting ${type}${suffix} build tools`, async () => - exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${msys2BasePath}`], { 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 installMSYS2Tools() { - const downloadPath = await common.measure(`Downloading msys2 build tools`, async () => { - const suffix = os.arch() === 'arm64' ? '-arm64' : '' + const extractPath = process.env.RUNNER_TEMP + await common.measure('Extracting Ruby', async () => + // -xr extract but exclude share\doc files + exec.exec('7z', ['x', downloadPath, '-bd', `-xr!${base}\\share\\doc`, `-o${extractPath}`], { silent: true })) - let url = `${msys2GCCReleaseURI}/msys2-gcc-pkgs/msys2${suffix}.7z` - console.log(url) - return await tc.downloadTool(url) - }) + const parentDir = path.dirname(rubyPrefix) + if (!fs.existsSync(parentDir)) { + fs.mkdirSync(parentDir, { recursive: true }) + } - // need to remove all directories, since they may indicate old packages are installed, - // otherwise, error of "error: duplicated database entry" - fs.rmSync(`${msys2BasePath}\\var\\lib\\pacman\\local`, { recursive: true, force: true }) + const extractedPath = path.join(extractPath, base) + if (extractedPath[0] === rubyPrefix[0]) { + fs.renameSync(extractedPath, rubyPrefix) + } else { + fs.symlinkSync(extractedPath, rubyPrefix, 'junction') + } - await common.measure(`Extracting msys2 build tools`, async () => - exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${msys2BasePath}`], { silent: true })) + if (common.shouldUseToolCache(engine, version)) { + common.createToolCacheCompleteFile(rubyPrefix) + } } -// Windows JRuby can install gems that require compile tools, only needed for -// windows-2022 and later images export async function installJRubyTools() { - await installMSYS2Tools() - await installGCCTools(os.arch() === 'arm64' ? 'clangarm64' : 'mingw64', '3.4') + return await installMSYS2(toolchainVersions['head'][os.arch()]) } -// Install vcpkg files needed to build mswin Ruby -async function installVCPkg() { - const downloadPath = await common.measure(`Downloading mswin vcpkg packages`, async () => { - let url = `${msys2GCCReleaseURI}/msys2-gcc-pkgs/mswin.7z` +async function installMSYS2(url, rubyPrefix = process.env.RUNNER_TEMP) { + const downloadPath = await common.measure('Downloading msys2 build tools', async () => { console.log(url) return await tc.downloadTool(url) }) - await common.measure(`Extracting mswin vcpkg packages`, async () => - exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${vcPkgBasePath}`], { silent: true })) -} - -async function downloadAndExtract(engine, version, url, base, rubyPrefix) { - const parentDir = path.dirname(rubyPrefix) - - const downloadPath = await common.measure('Downloading Ruby', async () => { - console.log(url) - return await tc.downloadTool(url) - }) - - await common.measure('Extracting Ruby', async () => - // -xr extract but exclude share\doc files - 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) + const extractPath = path.join(process.env.RUNNER_TEMP, 'msys64') + await common.measure('Extracting msys2 build tools', async () => + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${extractPath}`], { silent: true })) + + // https://github.com/oneclick/rubyinstaller2/blob/HEAD/lib/ruby_installer/build/msys2_installation.rb + // + // ri2 searches for msys64 in the following order: + // - ENV["MSYS2_PATH"] + // - File.join(RbConfig::TOPDIR, "msys64") + // - File.join(File.dirname(RbConfig::TOPDIR), "msys64") + // - "C:\msys64" + // - ... + // + // The first option ENV["MSYS2_PATH"] is only supported in ruby >=3.0.7. + // Therefore we use the second option to avoid conflict with existing "C:\msys64" + const msys2Path = path.join(rubyPrefix, 'msys64') + if (extractPath !== msys2Path) { + fs.symlinkSync(extractPath, msys2Path, 'junction') } - if (common.shouldUseToolCache(engine, version)) { - common.createToolCacheCompleteFile(rubyPrefix) + const ridk = `${rubyPrefix}\\bin\\ridk.cmd` + if (fs.existsSync(ridk)) { + await common.measure('Setting up ridk environment', async () => exportCommandEnv(`set MAKE=make && "${ridk}" enable`)) } -} -async function setupMingw(version) { - core.exportVariable('MAKE', 'make.exe') + // Examples: + // - msys2-clangarm64.7z + // - msys2-ucrt64-gcc@14.7z + // - msys2-mingw64-gcc@14-openssl@1.1.7z + const msys2Type = path.posix.basename(url).split(/[-.]/)[1] + return [`${msys2Path}\\${msys2Type}\\bin`, `${msys2Path}\\usr\\bin`] +} - // rename these to avoid confusion when Ruby is using OpenSSL 1.0.2. - // most current extconf files look for 1.1.x dll files first, which is the version of the renamed files - if (common.floatVersion(version) <= 2.4) { - renameSystem32Dlls() +async function installMSYS1(url) { + const certFile = [ + 'C:\\Program Files\\Git\\mingw64\\etc\\ssl\\cert.pem', + 'C:\\Program Files\\Git\\mingw64\\ssl\\cert.pem', + ].find(file => fs.existsSync(file)) + if (certFile === undefined) { + throw new Error("Cannot find Git's cert file") } - if (common.floatVersion(version) <= 2.3) { - core.exportVariable('SSL_CERT_FILE', certFile) - await common.measure('Installing MSYS1', async () => installMSYS1(version)) - return msysPathEntries - } else { - return [] - } -} + const downloadPath = await common.measure('Downloading msys1 build tools', async () => { + console.log(url) + return await tc.downloadTool(url) + }) -// Ruby 2.0-2.3 -async function installMSYS1(version) { - const url = 'https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe' - const downloadPath = await tc.downloadTool(url) - await exec.exec('7z', ['x', downloadPath, `-o${msys1}`], { silent: true }) - - // below are set in the old devkit.rb file ? - core.exportVariable('RI_DEVKIT', msys1) - core.exportVariable('CC' , 'gcc') - core.exportVariable('CXX', 'g++') - core.exportVariable('CPP', 'cpp') - core.info(`Installed RubyInstaller DevKit for Ruby ${version}`) -} + const msys1Path = `${common.drive}:\\DevKit64` + await common.measure('Extracting msys1 build tools', async () => + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${msys1Path}`], { silent: true })) + + await common.measure('Setting up DevKit environment', async () => { + // ssl dlls cause issues with msys1 Rubies + const sys32 = 'C:\\Windows\\System32\\' + const badFiles = [`${sys32}libcrypto-1_1-x64.dll`, `${sys32}libssl-1_1-x64.dll`] + const existing = badFiles.filter((dll) => fs.existsSync(dll)) + if (existing.length > 0) { + core.warning(`Renaming ${existing.join(' and ')} to avoid dll resolution conflicts on Ruby < 2.4`) + existing.forEach(dll => fs.renameSync(dll, `${dll}_`)) + } -async function setupMSWin() { - core.exportVariable('MAKE', 'nmake.exe') - return await common.measure('Setting up MSVC environment', async () => addVCVARSEnv()) + exportEnv({ + CC: 'gcc', + CPP: 'cpp', + CXX: 'g++', + MAKE: 'make', + RI_DEVKIT: msys1Path, + SSL_CERT_FILE: certFile + }) + }) + + return [`${msys1Path}\\mingw\\x86_64-w64-mingw32\\bin`, `${msys1Path}\\mingw\\bin`, `${msys1Path}\\bin`] } /* Sets MSVC environment for use in Actions * allows steps to run without running vcvars*.bat, also for PowerShell - * adds a convenience VCVARS environment variable * this assumes a single Visual Studio version being available in the Windows images */ -export function addVCVARSEnv() { - let cmd = 'vswhere -latest -property installationPath' - let vcVars = `${cp.execSync(cmd).toString().trim()}\\VC\\Auxiliary\\Build\\vcvars64.bat` - - if (!fs.existsSync(vcVars)) { - throw new Error(`Missing vcVars file: ${vcVars}`) - } - core.exportVariable('VCVARS', vcVars) +async function installVCPKG(url) { + const downloadPath = await common.measure('Downloading mswin vcpkg packages', async () => { + console.log(url) + return await tc.downloadTool(url) + }) - cmd = `cmd.exe /c ""${vcVars}" && set"` + const extractPath = process.env.VCPKG_INSTALLATION_ROOT + await common.measure('Extracting mswin vcpkg packages', async () => + exec.exec('7z', ['x', downloadPath, '-aoa', '-bd', `-o${extractPath}`], { silent: true })) - let newEnv = new Map() - let newSet = cp.execSync(cmd).toString().trim().split(/\r?\n/) - newSet = newSet.filter(line => /\S=\S/.test(line)) - newSet.forEach(s => { - let [k,v] = common.partition(s, '=') - newEnv.set(k,v) - }) + return await common.measure('Setting up MSVC environment', async () => { + const cmd = 'vswhere -latest -property installationPath' + const vcVarsBat = os.arch() === 'arm64' ? 'vcvarsarm64.bat' : 'vcvars64.bat' + const vcVars = `${cp.execSync(cmd).toString().trim()}\\VC\\Auxiliary\\Build\\${vcVarsBat}` - let newPathEntries = undefined - for (let [k, v] of newEnv) { - if (process.env[k] !== v) { - if (/^Path$/i.test(k)) { - const newPathStr = v.replace(`${path.delimiter}${process.env['Path']}`, '') - newPathEntries = newPathStr.split(path.delimiter) - } else { - core.exportVariable(k, v) - } + if (!fs.existsSync(vcVars)) { + throw new Error(`Missing vcVars file: ${vcVars}`) } - } - return newPathEntries -} -// ssl files cause issues with non RI2 Rubies (<2.4) and ruby/ruby's CI from build folder due to dll resolution -function renameSystem32Dlls() { - const sys32 = 'C:\\Windows\\System32\\' - const badFiles = [`${sys32}libcrypto-1_1-x64.dll`, `${sys32}libssl-1_1-x64.dll`] - const existing = badFiles.filter((dll) => fs.existsSync(dll)) - if (existing.length > 0) { - console.log(`Renaming ${existing.join(' and ')} to avoid dll resolution conflicts on Ruby <= 2.4`) - existing.forEach(dll => fs.renameSync(dll, `${dll}_`)) - } + return exportCommandEnv(`set MAKE=nmake && "${vcVars}"`) + }) } -// Sets MSYS2 ENV variables set from running `ridk enable` -function addRidkEnv(ridk) { - let newEnv = new Map() - let cmd = `cmd.exe /c "${ridk} enable && set"` - let newSet = cp.execSync(cmd).toString().trim().split(/\r?\n/) - newSet = newSet.filter(line => /^\S+=\S+/.test(line)) - newSet.forEach(s => { - let [k, v] = common.partition(s, '=') - newEnv.set(k, v) - }) +// Run a cmd command, export its environment, and return new paths +function exportCommandEnv(command) { + const cmd = `cmd.exe /s /c "${command} >NUL && "${process.execPath}" -e console.log(JSON.stringify(process.env))"` + const env = JSON.parse(cp.execSync(cmd).toString()) + + const paths = env.Path.replace(`${path.delimiter}${process.env.Path}`, '').split(path.delimiter) + delete env.Path + + exportEnv(env) + return paths +} - for (let [k, v] of newEnv) { +function exportEnv(env) { + for (const [k, v] of Object.entries(env)) { if (process.env[k] !== v) { - if (!/^Path$/i.test(k)) { - console.log(`${k}=${v}`) - core.exportVariable(k, v) - } + console.log(`${k}=${v}`) + core.exportVariable(k, v) } } }