2024-08-16 17:52:11 +08:00
|
|
|
import { addEnv, addPath } from "envosman"
|
2022-11-23 12:51:18 +08:00
|
|
|
|
2024-04-03 15:15:43 +08:00
|
|
|
import { GITHUB_ACTIONS } from "ci-info"
|
2024-09-04 03:20:35 +08:00
|
|
|
import { error, info, warning } from "ci-log"
|
2024-09-03 19:23:02 +08:00
|
|
|
import { type ExecaReturnValue, execa } from "execa"
|
2024-04-03 15:15:43 +08:00
|
|
|
import { pathExists } from "path-exists"
|
|
|
|
import { addExeExt, join } from "patha"
|
2021-09-17 07:02:18 +08:00
|
|
|
import semverCoerce from "semver/functions/coerce"
|
2024-04-03 15:15:43 +08:00
|
|
|
import semverMajor from "semver/functions/major"
|
2024-08-16 17:13:47 +08:00
|
|
|
import { addUpdateAlternativesToRc, installAptPack } from "setup-apt"
|
2024-08-24 06:20:37 +08:00
|
|
|
import { installBrewPack } from "setup-brew"
|
2024-08-16 06:22:07 +08:00
|
|
|
import { rcOptions } from "../cli-options.js"
|
|
|
|
import { setupMacOSSDK } from "../macos-sdk/macos-sdk.js"
|
|
|
|
import { hasDnf } from "../utils/env/hasDnf.js"
|
|
|
|
import { isArch } from "../utils/env/isArch.js"
|
|
|
|
import { isUbuntu } from "../utils/env/isUbuntu.js"
|
2024-09-03 18:42:37 +08:00
|
|
|
import { loadGitHubAssetList, matchAsset } from "../utils/github/load-assets.js"
|
2024-08-16 06:22:07 +08:00
|
|
|
import { extract7Zip } from "../utils/setup/extract.js"
|
|
|
|
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
|
|
|
|
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
|
|
|
|
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
|
|
|
|
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
|
2022-05-21 06:58:11 +08:00
|
|
|
|
2024-09-03 18:42:37 +08:00
|
|
|
async function getGccPackageInfo(version: string, platform: NodeJS.Platform, arch: string): Promise<PackageInfo> {
|
2022-05-21 06:58:11 +08:00
|
|
|
switch (platform) {
|
|
|
|
case "win32": {
|
2024-09-03 18:42:37 +08:00
|
|
|
const mingwAssets = await loadGitHubAssetList(
|
|
|
|
join(__dirname, "github_brechtsanders_winlibs_mingw.json"),
|
|
|
|
)
|
|
|
|
const asset = matchAsset(
|
|
|
|
mingwAssets,
|
|
|
|
{
|
|
|
|
version,
|
2024-09-03 19:08:01 +08:00
|
|
|
arch: arch === "x64"
|
|
|
|
? "x86_64"
|
|
|
|
: arch === "ia32"
|
|
|
|
? "i386"
|
|
|
|
: arch,
|
2024-09-03 18:42:37 +08:00
|
|
|
filterName: (name) => name.endsWith(".7z"),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2022-05-21 06:58:11 +08:00
|
|
|
return {
|
2022-05-21 08:07:25 +08:00
|
|
|
binRelativeDir: "bin/",
|
2022-08-21 06:38:51 +08:00
|
|
|
binFileName: addExeExt("g++"),
|
2022-05-21 06:58:11 +08:00
|
|
|
extractedFolderName: "mingw64",
|
|
|
|
extractFunction: extract7Zip,
|
2024-09-03 18:42:37 +08:00
|
|
|
url: `https://github.com/brechtsanders/winlibs_mingw/releases/download/${asset.tag}/${asset.name}`,
|
2022-05-21 06:58:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw new Error(`Unsupported platform '${platform}'`)
|
|
|
|
}
|
|
|
|
}
|
2021-09-16 22:03:54 +08:00
|
|
|
|
2024-01-22 14:04:51 +08:00
|
|
|
export async function setupGcc(version: string, setupDir: string, arch: string, priority: number = 40) {
|
2022-05-21 06:58:11 +08:00
|
|
|
let installationInfo: InstallationInfo | undefined
|
2021-09-16 22:03:54 +08:00
|
|
|
switch (process.platform) {
|
|
|
|
case "win32": {
|
|
|
|
if (arch === "arm" || arch === "arm64") {
|
2021-09-16 22:19:56 +08:00
|
|
|
await setupChocoPack("gcc-arm-embedded", version)
|
2021-09-16 22:03:54 +08:00
|
|
|
}
|
2022-05-21 06:58:11 +08:00
|
|
|
try {
|
|
|
|
installationInfo = await setupBin("g++", version, getGccPackageInfo, setupDir, arch)
|
|
|
|
} catch (err) {
|
2022-05-21 07:28:35 +08:00
|
|
|
info(`Failed to download g++ binary. ${err}. Falling back to chocolatey.`)
|
2022-05-21 06:58:11 +08:00
|
|
|
installationInfo = await setupChocoMingw(version, arch)
|
|
|
|
}
|
2021-09-17 05:47:49 +08:00
|
|
|
break
|
2021-09-16 22:03:54 +08:00
|
|
|
}
|
|
|
|
case "darwin": {
|
2024-08-24 06:20:37 +08:00
|
|
|
installationInfo = await installBrewPack("gcc", version)
|
2021-09-17 05:47:49 +08:00
|
|
|
break
|
2021-09-16 22:03:54 +08:00
|
|
|
}
|
|
|
|
case "linux": {
|
|
|
|
if (arch === "x64") {
|
2022-06-30 10:06:33 +08:00
|
|
|
if (isArch()) {
|
2023-05-25 05:12:42 +08:00
|
|
|
installationInfo = await setupPacmanPack("gcc", version)
|
2022-07-11 07:34:56 +08:00
|
|
|
} else if (hasDnf()) {
|
2023-07-16 18:12:24 +08:00
|
|
|
installationInfo = await setupDnfPack([
|
|
|
|
{ name: "gcc", version },
|
|
|
|
{ name: "gcc-c++", version },
|
|
|
|
{ name: "libstdc++-devel" },
|
|
|
|
])
|
2022-07-11 08:39:21 +08:00
|
|
|
} else if (isUbuntu()) {
|
2024-09-03 18:42:37 +08:00
|
|
|
if (version === "") {
|
2024-09-03 17:41:54 +08:00
|
|
|
// the default version
|
|
|
|
installationInfo = await installAptPack([{ name: "gcc" }, { name: "g++" }])
|
|
|
|
} else {
|
|
|
|
// add the PPA for access to more versions
|
|
|
|
installationInfo = await installAptPack([
|
|
|
|
{
|
|
|
|
name: "gcc",
|
|
|
|
version,
|
|
|
|
repository: "ppa:ubuntu-toolchain-r/test",
|
|
|
|
key: { key: "1E9377A2BA9EF27F", fileName: "ubuntu-toolchain-r-test.gpg" },
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "g++",
|
|
|
|
version,
|
|
|
|
repository: "ppa:ubuntu-toolchain-r/test",
|
|
|
|
key: { key: "1E9377A2BA9EF27F", fileName: "ubuntu-toolchain-r-test.gpg" },
|
|
|
|
},
|
|
|
|
])
|
|
|
|
}
|
2022-06-30 00:06:35 +08:00
|
|
|
}
|
2021-09-17 06:00:14 +08:00
|
|
|
} else {
|
2021-09-17 06:17:32 +08:00
|
|
|
info(`Install g++-multilib because gcc for ${arch} was requested`)
|
2022-06-30 10:06:33 +08:00
|
|
|
if (isArch()) {
|
2024-09-04 03:20:35 +08:00
|
|
|
installationInfo = await setupPacmanPack("gcc-multilib", version)
|
2022-07-11 08:39:21 +08:00
|
|
|
} else if (isUbuntu()) {
|
2024-09-03 18:42:37 +08:00
|
|
|
if (version === "") {
|
2024-09-03 17:41:54 +08:00
|
|
|
// the default version
|
2024-09-04 03:20:35 +08:00
|
|
|
installationInfo = await installAptPack([{ name: "gcc-multilib" }])
|
2024-09-03 17:41:54 +08:00
|
|
|
} else {
|
|
|
|
// add the PPA for access to more versions
|
2024-09-04 03:20:35 +08:00
|
|
|
installationInfo = await installAptPack([{
|
2024-09-03 17:41:54 +08:00
|
|
|
name: "gcc-multilib",
|
|
|
|
version,
|
|
|
|
repository: "ppa:ubuntu-toolchain-r/test",
|
|
|
|
key: { key: "1E9377A2BA9EF27F", fileName: "ubuntu-toolchain-r-test.gpg" },
|
|
|
|
}])
|
|
|
|
}
|
2022-06-30 00:06:35 +08:00
|
|
|
}
|
2021-09-16 22:03:54 +08:00
|
|
|
}
|
2021-09-17 05:47:49 +08:00
|
|
|
break
|
2021-09-16 22:03:54 +08:00
|
|
|
}
|
2021-12-07 16:53:22 +08:00
|
|
|
// TODO support bare-metal (need to support passing it as the input)
|
2021-09-16 22:03:54 +08:00
|
|
|
// TODO support abi
|
|
|
|
// case "none": {
|
|
|
|
// if (arch === "arm" || arch === "arm64") {
|
2024-08-16 16:50:32 +08:00
|
|
|
// return installAptPack("gcc-arm-none-eabi", version, [
|
2021-12-07 20:16:31 +08:00
|
|
|
// "ppa:ubuntu-toolchain-r/test",
|
2021-12-07 16:53:22 +08:00
|
|
|
// ])
|
2021-09-16 22:03:54 +08:00
|
|
|
// } else {
|
|
|
|
// throw new Error(`Unsupported platform for ${arch}`)
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
default: {
|
|
|
|
throw new Error(`Unsupported platform for ${arch}`)
|
|
|
|
}
|
|
|
|
}
|
2022-05-21 06:58:11 +08:00
|
|
|
if (installationInfo !== undefined) {
|
2024-01-22 14:04:51 +08:00
|
|
|
await activateGcc(version, installationInfo.binDir, priority)
|
2022-05-21 06:58:11 +08:00
|
|
|
return installationInfo
|
2021-09-17 05:47:49 +08:00
|
|
|
}
|
|
|
|
return undefined
|
2021-09-16 22:03:54 +08:00
|
|
|
}
|
2021-09-20 20:25:41 +08:00
|
|
|
|
2022-12-30 05:00:49 +08:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
export async function setupMingw(version: string, setupDir: string, arch: string) {
|
|
|
|
let installationInfo: InstallationInfo | undefined
|
|
|
|
switch (process.platform) {
|
2023-07-20 05:31:19 +08:00
|
|
|
case "win32":
|
|
|
|
case "darwin": {
|
|
|
|
return setupGcc(version, setupDir, arch)
|
2022-12-30 05:00:49 +08:00
|
|
|
}
|
|
|
|
case "linux": {
|
2023-07-20 05:31:19 +08:00
|
|
|
if (isArch()) {
|
2023-07-20 06:26:55 +08:00
|
|
|
installationInfo = await setupPacmanPack("mingw-w64-gcc", version)
|
2023-07-20 05:31:19 +08:00
|
|
|
} else if (hasDnf()) {
|
2023-07-20 17:44:13 +08:00
|
|
|
installationInfo = await setupDnfPack([{ name: "mingw64-gcc", version }])
|
2023-07-20 05:31:19 +08:00
|
|
|
} else if (isUbuntu()) {
|
2024-08-16 16:50:32 +08:00
|
|
|
installationInfo = await installAptPack([
|
2024-08-29 04:54:48 +08:00
|
|
|
{
|
|
|
|
name: "mingw-w64",
|
|
|
|
version,
|
2024-08-29 05:23:40 +08:00
|
|
|
repository: "ppa:ubuntu-toolchain-r/test",
|
|
|
|
key: { key: "1E9377A2BA9EF27F", fileName: "ubuntu-toolchain-r-test.gpg" },
|
2024-08-29 04:54:48 +08:00
|
|
|
},
|
2023-07-20 05:31:19 +08:00
|
|
|
])
|
2022-12-30 05:00:49 +08:00
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
throw new Error(`Unsupported platform for ${arch}`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (installationInfo !== undefined) {
|
|
|
|
// TODO: setup alternatives and update CC/CXX env. ?
|
2024-04-03 15:15:43 +08:00
|
|
|
// Setting up g++-mingw-w64-i686-win32 (10.3.0-14ubuntu1+24.3) ...
|
2022-12-30 05:00:49 +08:00
|
|
|
// update-alternatives: using /usr/bin/i686-w64-mingw32-g++-win32 to provide /usr/bin/i686-w64-mingw32-g++ (i686-w64-mingw32-g++) in auto mode
|
2024-04-03 15:15:43 +08:00
|
|
|
// Setting up g++-mingw-w64-x86-64-win32 (10.3.0-14ubuntu1+24.3) ...
|
2022-12-30 05:00:49 +08:00
|
|
|
// update-alternatives: using /usr/bin/x86_64-w64-mingw32-g++-win32 to provide /usr/bin/x86_64-w64-mingw32-g++ (x86_64-w64-mingw32-g++) in auto mode
|
2024-04-03 15:15:43 +08:00
|
|
|
// await activateGcc(version, installationInfo.binDir)
|
2022-12-30 05:00:49 +08:00
|
|
|
return installationInfo
|
|
|
|
}
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
2022-05-21 06:58:11 +08:00
|
|
|
async function setupChocoMingw(version: string, arch: string): Promise<InstallationInfo | undefined> {
|
2022-05-21 06:19:19 +08:00
|
|
|
await setupChocoPack("mingw", version)
|
|
|
|
let binDir: string | undefined
|
2022-11-23 12:51:18 +08:00
|
|
|
if (arch === "x64" && (await pathExists("C:/tools/mingw64/bin"))) {
|
2022-05-21 06:19:19 +08:00
|
|
|
binDir = "C:/tools/mingw64/bin"
|
2024-08-15 09:43:53 +08:00
|
|
|
await addPath(binDir, rcOptions)
|
2022-11-23 12:51:18 +08:00
|
|
|
} else if (arch === "ia32" && (await pathExists("C:/tools/mingw32/bin"))) {
|
2022-05-21 06:19:19 +08:00
|
|
|
binDir = "C:/tools/mingw32/bin"
|
2024-08-15 09:43:53 +08:00
|
|
|
await addPath(binDir, rcOptions)
|
2022-11-23 12:51:18 +08:00
|
|
|
} else if (await pathExists(`${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin/g++.exe`)) {
|
2022-05-21 06:19:19 +08:00
|
|
|
binDir = `${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin`
|
|
|
|
}
|
2022-05-21 06:58:11 +08:00
|
|
|
if (binDir !== undefined) {
|
|
|
|
return { binDir }
|
|
|
|
}
|
|
|
|
return undefined
|
2022-05-21 06:19:19 +08:00
|
|
|
}
|
|
|
|
|
2024-09-03 19:23:02 +08:00
|
|
|
async function activateGcc(givenVersion: string, binDir: string, priority: number = 40) {
|
2023-05-25 05:57:08 +08:00
|
|
|
const promises: Promise<void | ExecaReturnValue<string>>[] = []
|
2022-05-13 09:39:47 +08:00
|
|
|
// Setup gcc as the compiler
|
|
|
|
|
2021-09-20 20:25:41 +08:00
|
|
|
// TODO
|
|
|
|
// const ld = process.env.LD_LIBRARY_PATH ?? ""
|
|
|
|
// const dyld = process.env.DYLD_LIBRARY_PATH ?? ""
|
2022-05-13 09:39:47 +08:00
|
|
|
// promises.push(
|
2024-08-15 09:43:53 +08:00
|
|
|
// addEnv("LD_LIBRARY_PATH", `${installDir}/lib${path.delimiter}${ld}`, rcOptions),
|
|
|
|
// addEnv("DYLD_LIBRARY_PATH", `${installDir}/lib${path.delimiter}${dyld}`, rcOptions),
|
|
|
|
// addEnv("CPATH", `${installDir}/lib/gcc/${majorVersion}/include`, rcOptions),
|
|
|
|
// addEnv("LDFLAGS", `-L${installDir}/lib`, rcOptions),
|
|
|
|
// addEnv("CPPFLAGS", `-I${installDir}/include`, rcOptions),
|
2022-05-13 09:39:47 +08:00
|
|
|
// )
|
|
|
|
|
2021-09-20 20:25:41 +08:00
|
|
|
if (process.platform === "win32") {
|
2024-08-15 09:43:53 +08:00
|
|
|
promises.push(
|
|
|
|
addEnv("CC", addExeExt(`${binDir}/gcc`), rcOptions),
|
|
|
|
addEnv("CXX", addExeExt(`${binDir}/g++`), rcOptions),
|
|
|
|
)
|
2021-09-20 20:25:41 +08:00
|
|
|
} else {
|
2024-09-03 19:23:02 +08:00
|
|
|
// if version is empty, get the version from the gcc command
|
|
|
|
let version = givenVersion
|
|
|
|
if (givenVersion === "") {
|
|
|
|
version = await getGccCmdVersion(binDir, version)
|
|
|
|
info(`Using gcc version ${version}`)
|
|
|
|
}
|
|
|
|
|
2021-12-07 20:16:31 +08:00
|
|
|
const majorVersion = semverMajor(semverCoerce(version) ?? version)
|
|
|
|
if (majorVersion >= 5) {
|
2024-08-15 09:43:53 +08:00
|
|
|
promises.push(
|
|
|
|
addEnv("CC", `${binDir}/gcc-${majorVersion}`, rcOptions),
|
|
|
|
addEnv("CXX", `${binDir}/g++-${majorVersion}`, rcOptions),
|
|
|
|
)
|
2022-04-19 14:34:18 +08:00
|
|
|
|
2022-06-30 11:52:25 +08:00
|
|
|
if (isUbuntu()) {
|
2022-11-23 14:11:47 +08:00
|
|
|
promises.push(
|
2024-08-16 17:13:47 +08:00
|
|
|
addUpdateAlternativesToRc("cc", `${binDir}/gcc-${majorVersion}`, rcOptions, priority),
|
|
|
|
addUpdateAlternativesToRc("cxx", `${binDir}/g++-${majorVersion}`, rcOptions, priority),
|
|
|
|
addUpdateAlternativesToRc("gcc", `${binDir}/gcc-${majorVersion}`, rcOptions, priority),
|
|
|
|
addUpdateAlternativesToRc("g++", `${binDir}/g++-${majorVersion}`, rcOptions, priority),
|
2022-11-23 14:11:47 +08:00
|
|
|
)
|
2022-04-19 14:34:18 +08:00
|
|
|
}
|
2021-12-07 20:16:31 +08:00
|
|
|
} else {
|
2024-08-15 09:43:53 +08:00
|
|
|
promises.push(
|
|
|
|
addEnv("CC", `${binDir}/gcc-${version}`, rcOptions),
|
|
|
|
addEnv("CXX", `${binDir}/g++-${version}`, rcOptions),
|
|
|
|
)
|
2022-04-19 14:34:18 +08:00
|
|
|
|
2022-06-30 11:52:25 +08:00
|
|
|
if (isUbuntu()) {
|
2022-11-23 14:11:47 +08:00
|
|
|
promises.push(
|
2024-08-16 17:13:47 +08:00
|
|
|
addUpdateAlternativesToRc("cc", `${binDir}/gcc-${version}`, rcOptions, priority),
|
|
|
|
addUpdateAlternativesToRc("cxx", `${binDir}/g++-${version}`, rcOptions, priority),
|
|
|
|
addUpdateAlternativesToRc("gcc", `${binDir}/gcc-${version}`, rcOptions, priority),
|
|
|
|
addUpdateAlternativesToRc("g++", `${binDir}/g++-${version}`, rcOptions, priority),
|
2022-11-23 14:11:47 +08:00
|
|
|
)
|
2022-04-19 14:34:18 +08:00
|
|
|
}
|
2021-12-07 20:16:31 +08:00
|
|
|
}
|
2021-09-20 20:25:41 +08:00
|
|
|
}
|
2021-11-22 01:06:16 +08:00
|
|
|
|
2022-05-13 09:39:47 +08:00
|
|
|
promises.push(setupMacOSSDK())
|
2022-02-12 08:58:50 +08:00
|
|
|
|
2023-04-22 17:31:04 +08:00
|
|
|
if (GITHUB_ACTIONS) {
|
2022-11-23 12:51:18 +08:00
|
|
|
await addGccLoggingMatcher()
|
2022-02-12 08:58:50 +08:00
|
|
|
}
|
2022-05-13 09:39:47 +08:00
|
|
|
|
|
|
|
await Promise.all(promises)
|
2022-02-12 08:58:50 +08:00
|
|
|
}
|
|
|
|
|
2024-09-03 19:23:02 +08:00
|
|
|
async function getGccCmdVersion(binDir: string, givenVersion: string) {
|
2024-09-04 03:20:35 +08:00
|
|
|
// TODO get the version from the package manager
|
|
|
|
try {
|
|
|
|
const gccExe = await pathExists(`${binDir}/gcc`) ? `${binDir}/gcc` : "gcc"
|
|
|
|
|
|
|
|
const { stdout: versionStdout } = await execa(gccExe, ["--version"], { stdio: "pipe" })
|
2024-09-03 19:23:02 +08:00
|
|
|
|
2024-09-04 03:20:35 +08:00
|
|
|
const versionMatch = (versionStdout as string).match(/gcc \(.*\) ([\d.]+)/)
|
2024-09-03 19:23:02 +08:00
|
|
|
|
2024-09-04 03:20:35 +08:00
|
|
|
return versionMatch !== null ? versionMatch[1] : givenVersion
|
|
|
|
} catch (err) {
|
|
|
|
error(`Failed to get gcc version: ${err}`)
|
|
|
|
return givenVersion
|
|
|
|
}
|
2024-09-03 19:23:02 +08:00
|
|
|
}
|
|
|
|
|
2022-11-23 12:51:18 +08:00
|
|
|
async function addGccLoggingMatcher() {
|
2022-08-21 06:38:51 +08:00
|
|
|
const matcherPath = join(__dirname, "gcc_matcher.json")
|
2022-11-23 12:51:18 +08:00
|
|
|
if (!(await pathExists(matcherPath))) {
|
2023-01-18 13:40:21 +08:00
|
|
|
return warning("the gcc_matcher.json file does not exist in the same folder as setup-cpp.js")
|
2022-02-12 08:58:50 +08:00
|
|
|
}
|
|
|
|
info(`::add-matcher::${matcherPath}`)
|
2021-09-20 20:25:41 +08:00
|
|
|
}
|