2024-08-15 09:22:33 +08:00
import { addEnv , addPath } from "os-env"
2022-11-23 12:51:18 +08:00
2024-04-03 15:15:43 +08:00
import { GITHUB_ACTIONS } from "ci-info"
import { info , warning } from "ci-log"
2024-08-07 14:44:32 +08:00
import type { ExecaReturnValue } 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 16:50:32 +08:00
import { installAptPack , updateAptAlternatives } from "setup-apt"
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"
import { extract7Zip } from "../utils/setup/extract.js"
import { type InstallationInfo , type PackageInfo , setupBin } from "../utils/setup/setupBin.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.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
interface MingwInfo {
2022-05-21 07:28:35 +08:00
releaseName : string
fileSuffix : string
2022-05-21 06:58:11 +08:00
}
2022-05-21 07:28:35 +08:00
// https://github.com/brechtsanders/winlibs_mingw/releases
2022-05-21 06:58:11 +08:00
const GccToMingwInfo = {
2023-09-04 08:42:40 +08:00
"13" : { releaseName : "13.2.0-16.0.6-11.0.0-ucrt-r1" , fileSuffix : "13.2.0-mingw-w64ucrt-11.0.0-r1" } ,
"13.2-ucrt" : { releaseName : "13.2.0-16.0.6-11.0.0-ucrt-r1" , fileSuffix : "13.2.0-mingw-w64ucrt-11.0.0-r1" } ,
"13.2-ucrt-mcf" : { releaseName : "13.2.0mcf-16.0.6-11.0.1-ucrt-r2" , fileSuffix : "13.2.0-mingw-w64ucrt-11.0.1-r2" } ,
"13.2-msvcrt" : { releaseName : "13.2.0-16.0.6-11.0.1-msvcrt-r1" , fileSuffix : "13.2.0-mingw-w64msvcrt-11.0.1-r1" } ,
2023-05-24 12:10:03 +08:00
"13.1-ucrt" : { releaseName : "13.1.0posix-16.0.3-11.0.0-ucrt-r1" , fileSuffix : "13.1.0-mingw-w64ucrt-11.0.0-r1" } ,
"13.1-msvcrt" : { releaseName : "13.1.0posix-16.0.3-11.0.0-msvcrt-r1" , fileSuffix : "13.1.0-mingw-w64msvcrt-11.0.0-r1" } ,
"12" : { releaseName : "12.3.0-16.0.4-11.0.0-ucrt-r1" , fileSuffix : "12.3.0-mingw-w64ucrt-11.0.0-r1" } ,
"12.3.0-ucrt" : { releaseName : "12.3.0-16.0.4-11.0.0-ucrt-r1" , fileSuffix : "12.3.0-mingw-w64ucrt-11.0.0-r1" } ,
"12.3.0-msvcrt" : { releaseName : "12.3.0-16.0.4-11.0.0-msvcrt-r1" , fileSuffix : "12.3.0-mingw-w64msvcrt-11.0.0-r1" } ,
2022-11-21 08:25:37 +08:00
"12.2.0-ucrt" : { releaseName : "12.2.0-14.0.6-10.0.0-ucrt-r2" , fileSuffix : "12.2.0-mingw-w64ucrt-10.0.0-r2" } ,
"12.2.0-msvcrt" : { releaseName : "12.2.0-14.0.6-10.0.0-msvcrt-r2" , fileSuffix : "12.2.0-mingw-w64msvcrt-10.0.0-r2" } ,
2022-06-10 03:02:41 +08:00
"12.1.0-ucrt" : { releaseName : "12.1.0-14.0.4-10.0.0-ucrt-r2" , fileSuffix : "12.1.0-mingw-w64ucrt-10.0.0-r2" } ,
2022-08-09 02:50:49 +08:00
"12.1.0-msvcrt" : {
releaseName : "12.1.0-14.0.6-10.0.0-msvcrt-r3" ,
fileSuffix : "12.1.0-llvm-14.0.6-mingw-w64msvcrt-10.0.0-r3" ,
} ,
2022-05-21 07:28:35 +08:00
"11" : { releaseName : "11.3.0-14.0.3-10.0.0-ucrt-r3" , fileSuffix : "11.3.0-mingw-w64ucrt-10.0.0-r3" } ,
"11.3.0-ucrt" : { releaseName : "11.3.0-14.0.3-10.0.0-ucrt-r3" , fileSuffix : "11.3.0-mingw-w64ucrt-10.0.0-r3" } ,
"11.3.0-msvcrt" : { releaseName : "11.3.0-14.0.3-10.0.0-msvcrt-r3" , fileSuffix : "11.3.0-mingw-w64msvcrt-10.0.0-r3" } ,
"11.2.0-ucrt" : { releaseName : "11.2.0-9.0.0-ucrt-r5" , fileSuffix : "11.2.0-mingw-w64ucrt-9.0.0-r5" } ,
"11.2.0-msvcrt" : { releaseName : "11.2.0-9.0.0-msvcrt-r5" , fileSuffix : "11.2.0-mingw-w64msvcrt-9.0.0-r5" } ,
2023-09-04 08:42:40 +08:00
"10" : { releaseName : "10.5.0-11.0.1-msvcrt-r1" , fileSuffix : "10.5.0-mingw-w64msvcrt-11.0.1-r1" } ,
"10.5.0-msvcrt" : { releaseName : "10.5.0-11.0.1-msvcrt-r1" , fileSuffix : "10.5.0-mingw-w64msvcrt-11.0.1-r1" } ,
2022-05-21 07:28:35 +08:00
"10.3.0" : { releaseName : "10.3.0-12.0.0-9.0.0-r2" , fileSuffix : "10.3.0-llvm-12.0.0-mingw-w64-9.0.0-r2" } ,
"10.2.0" : { releaseName : "10.2.0-7.0.0-r4" , fileSuffix : "10.2.0-llvm-10.0.1-mingw-w64-7.0.0-r4" } ,
"9" : { releaseName : "9.4.0-9.0.0-r1" , fileSuffix : "9.4.0-mingw-w64-9.0.0-r1" } ,
"9.4.0" : { releaseName : "9.4.0-9.0.0-r1" , fileSuffix : "9.4.0-mingw-w64-9.0.0-r1" } ,
2022-05-21 06:58:11 +08:00
} as Record < string , MingwInfo | undefined >
function getGccPackageInfo ( version : string , platform : NodeJS.Platform , arch : string ) : PackageInfo {
switch ( platform ) {
case "win32" : {
const mingwInfo = GccToMingwInfo [ version ]
if ( mingwInfo === undefined ) {
throw new Error ( ` mingw version ${ version } is not supported ` )
}
const mingwArch = arch === "ia32" ? "i686" : "x86_64"
2022-05-21 07:28:35 +08:00
const exceptionModel : "seh" | "dwarf" = "seh" // SEH is native windows exception model https://github.com/brechtsanders/winlibs_mingw/issues/4#issuecomment-599296483
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-04-03 15:15:43 +08:00
url :
` https://github.com/brechtsanders/winlibs_mingw/releases/download/ ${ mingwInfo . releaseName } /winlibs- ${ mingwArch } -posix- ${ exceptionModel } -gcc- ${ mingwInfo . fileSuffix } .7z ` ,
2022-05-21 06:58:11 +08:00
}
}
default :
throw new Error ( ` Unsupported platform ' ${ platform } ' ` )
}
}
2021-09-16 22:03:54 +08:00
// eslint-disable-next-line @typescript-eslint/no-unused-vars
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" : {
2022-11-21 13:26:31 +08:00
installationInfo = await setupBrewPack ( "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-08-16 16:50:32 +08:00
installationInfo = await installAptPack ( [
2022-11-23 13:33:06 +08:00
{ name : "gcc" , version , repositories : [ "ppa:ubuntu-toolchain-r/test" ] } ,
{ name : "g++" , version , repositories : [ "ppa:ubuntu-toolchain-r/test" ] } ,
] )
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 ( ) ) {
2023-05-25 05:57:08 +08:00
await setupPacmanPack ( "gcc-multilib" , version )
2022-07-11 08:39:21 +08:00
} else if ( isUbuntu ( ) ) {
2024-08-16 16:50:32 +08:00
await installAptPack ( [ { name : "gcc-multilib" , version , repositories : [ "ppa:ubuntu-toolchain-r/test" ] } ] )
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 ( [
2023-07-20 05:31:19 +08:00
{ name : "mingw-w64" , version , repositories : [ "ppa:ubuntu-toolchain-r/test" ] } ,
] )
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-01-22 14:04:51 +08:00
async function activateGcc ( version : 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 {
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 16:50:32 +08:00
updateAptAlternatives ( "cc" , ` ${ binDir } /gcc- ${ majorVersion } ` , rcOptions , priority ) ,
updateAptAlternatives ( "cxx" , ` ${ binDir } /g++- ${ majorVersion } ` , rcOptions , priority ) ,
updateAptAlternatives ( "gcc" , ` ${ binDir } /gcc- ${ majorVersion } ` , rcOptions , priority ) ,
updateAptAlternatives ( "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 16:50:32 +08:00
updateAptAlternatives ( "cc" , ` ${ binDir } /gcc- ${ version } ` , rcOptions , priority ) ,
updateAptAlternatives ( "cxx" , ` ${ binDir } /g++- ${ version } ` , rcOptions , priority ) ,
updateAptAlternatives ( "gcc" , ` ${ binDir } /gcc- ${ version } ` , rcOptions , priority ) ,
updateAptAlternatives ( "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
}
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
}