Merge pull request #152 from aminya/perf [skip ci]

This commit is contained in:
Amin Yahyaabadi 2022-11-22 22:39:34 -08:00 committed by GitHub
commit 24f1544102
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 206 additions and 156 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -59,12 +59,14 @@
"ci-log": "workspace:1.0.0",
"escape-path-with-spaces": "github:aminya/escape-path-with-spaces#d9f81ee649203ddc55783a2f96ada59df06118e3",
"escape-quotes": "^1.0.2",
"escape-string-regexp": "^5.0.0",
"exec-powershell": "workspace:1.0.0",
"execa": "^5.1.1",
"is-url-online": "^1.5.0",
"mri": "^1.2.0",
"msvc-dev-cmd": "github:aminya/msvc-dev-cmd#9f672c1",
"numerous": "1.0.3",
"path-exists": "^4.0.0",
"patha": "^0.4.1",
"quote-unquote": "^1.0.0",
"semver": "7.3.8",

View File

@ -31,6 +31,7 @@ importers:
cspell: ^6.14.3
escape-path-with-spaces: github:aminya/escape-path-with-spaces#d9f81ee649203ddc55783a2f96ada59df06118e3
escape-quotes: ^1.0.2
escape-string-regexp: ^5.0.0
eslint: ^8.28.0
eslint-config-atomic: ^1.18.1
exec-powershell: workspace:1.0.0
@ -44,6 +45,7 @@ importers:
npm-run-all2: ^6.0.4
numerous: 1.0.3
parcel: 2.8.0
path-exists: ^4.0.0
patha: ^0.4.1
prettier: 2.7.1
prettier-config-atomic: ^3.1.0
@ -72,12 +74,14 @@ importers:
ci-log: link:packages/ci-log
escape-path-with-spaces: github.com/aminya/escape-path-with-spaces/d9f81ee649203ddc55783a2f96ada59df06118e3
escape-quotes: 1.0.2
escape-string-regexp: 5.0.0
exec-powershell: link:packages/exec-powershell
execa: 5.1.1
is-url-online: 1.5.0
mri: 1.2.0
msvc-dev-cmd: github.com/aminya/msvc-dev-cmd/9f672c1
numerous: 1.0.3
path-exists: 4.0.0
patha: 0.4.1
quote-unquote: 1.0.0
semver: 7.3.8
@ -7822,7 +7826,6 @@ packages:
/path-exists/4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
dev: true
/path-is-absolute/1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}

View File

@ -36,7 +36,7 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
"-c",
`echo "deb [arch=amd64 signed-by=${keyFileName}] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list`,
])
return setupAptPack("bazel", version, [], true)
return setupAptPack([{ name: "bazel", version }], true)
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -22,7 +22,7 @@ export function setupCcache(version: string, _setupDir: string, _arch: string) {
} else if (hasDnf()) {
return setupDnfPack("ccache", version)
} else if (isUbuntu()) {
return setupAptPack("ccache", version)
return setupAptPack([{ name: "ccache", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -1,6 +1,7 @@
/* eslint-disable require-atomic-updates */
import execa from "execa"
import { existsSync } from "fs"
import pathExists from "path-exists"
import { dirname } from "patha"
import which from "which"
import { addPath } from "../utils/env/addEnv"
@ -63,7 +64,7 @@ export async function setupChocolatey(
binDir = `${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin`
}
if (existsSync(binDir)) {
if (await pathExists(binDir)) {
return { binDir }
}
return undefined

View File

@ -25,7 +25,7 @@ export async function setupCppcheck(version: string | undefined, _setupDir: stri
} else if (hasDnf()) {
return setupDnfPack("ccache", version)
} else if (isUbuntu()) {
return setupAptPack("cppcheck", version)
return setupAptPack([{ name: "cppcheck", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -9,11 +9,12 @@ import { extractTar, extractZip } from "../utils/setup/extract"
import { notice } from "ci-log"
import { setupGraphviz } from "../graphviz/graphviz"
import { getVersion } from "../versions/versions"
import { existsSync } from "fs"
import { isArch } from "../utils/env/isArch"
import { hasDnf } from "../utils/env/hasDnf"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
import pathExists from "path-exists"
/** Get the platform data for cmake */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -66,7 +67,7 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
} else if (hasDnf()) {
return setupDnfPack("doxygen", version)
} else if (isUbuntu()) {
installationInfo = await setupAptPack("doxygen", version)
installationInfo = await setupAptPack([{ name: "doxygen", version }])
} else {
throw new Error(`Unsupported linux distributions`)
}
@ -74,10 +75,10 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
try {
// doxygen on stable Ubuntu repositories is very old. So, we use get the binary from the website itself
installationInfo = await setupBin("doxygen", version, getDoxygenPackageInfo, setupDir, arch)
await setupAptPack("libclang-cpp9")
await setupAptPack([{ name: "libclang-cpp9" }])
} catch (err) {
notice(`Failed to download doxygen binary. ${err}. Falling back to apt-get.`)
installationInfo = await setupAptPack("doxygen", undefined)
installationInfo = await setupAptPack([{ name: "doxygen" }])
}
} else {
throw new Error(`Unsupported linux distributions`)
@ -99,7 +100,7 @@ async function activateWinDoxygen() {
"C:/Program Files/doxygen/bin",
"C:/Program Files (x86)/doxygen",
]) {
if (existsSync(join(binDir, "doxygen.exe"))) {
if (await pathExists(join(binDir, "doxygen.exe"))) {
// eslint-disable-next-line no-await-in-loop
await addPath(binDir)
return binDir

View File

@ -1,5 +1,5 @@
import { addPath, addEnv } from "../utils/env/addEnv"
import { existsSync } from "fs"
import { setupAptPack, updateAptAlternatives } from "../utils/setup/setupAptPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
@ -16,6 +16,7 @@ import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { hasDnf } from "../utils/env/hasDnf"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import pathExists from "path-exists"
interface MingwInfo {
releaseName: string
@ -95,15 +96,17 @@ export async function setupGcc(version: string, setupDir: string, arch: string)
setupDnfPack("gcc-c++", version)
setupDnfPack("libstdc++-devel", undefined)
} else if (isUbuntu()) {
await setupAptPack("gcc", version, ["ppa:ubuntu-toolchain-r/test"])
installationInfo = await setupAptPack("g++", version, [])
installationInfo = await setupAptPack([
{ name: "gcc", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
{ name: "g++", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
])
}
} else {
info(`Install g++-multilib because gcc for ${arch} was requested`)
if (isArch()) {
setupPacmanPack("gcc-multilib", version)
} else if (isUbuntu()) {
await setupAptPack("gcc-multilib", version, ["ppa:ubuntu-toolchain-r/test"])
await setupAptPack([{ name: "gcc-multilib", version, repositories: ["ppa:ubuntu-toolchain-r/test"] }])
}
}
break
@ -133,13 +136,13 @@ export async function setupGcc(version: string, setupDir: string, arch: string)
async function setupChocoMingw(version: string, arch: string): Promise<InstallationInfo | undefined> {
await setupChocoPack("mingw", version)
let binDir: string | undefined
if (arch === "x64" && existsSync("C:/tools/mingw64/bin")) {
if (arch === "x64" && (await pathExists("C:/tools/mingw64/bin"))) {
binDir = "C:/tools/mingw64/bin"
await addPath(binDir)
} else if (arch === "ia32" && existsSync("C:/tools/mingw32/bin")) {
} else if (arch === "ia32" && (await pathExists("C:/tools/mingw32/bin"))) {
binDir = "C:/tools/mingw32/bin"
await addPath(binDir)
} else if (existsSync(`${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin/g++.exe`)) {
} else if (await pathExists(`${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin/g++.exe`)) {
binDir = `${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin`
}
if (binDir !== undefined) {
@ -149,7 +152,7 @@ async function setupChocoMingw(version: string, arch: string): Promise<Installat
}
async function activateGcc(version: string, binDir: string) {
const promises: Promise<void>[] = []
const promises: Promise<any>[] = []
// Setup gcc as the compiler
// TODO
@ -171,19 +174,23 @@ async function activateGcc(version: string, binDir: string) {
promises.push(addEnv("CC", `${binDir}/gcc-${majorVersion}`), addEnv("CXX", `${binDir}/g++-${majorVersion}`))
if (isUbuntu()) {
updateAptAlternatives("cc", `${binDir}/gcc-${majorVersion}`)
updateAptAlternatives("cxx", `${binDir}/g++-${majorVersion}`)
updateAptAlternatives("gcc", `${binDir}/gcc-${majorVersion}`)
updateAptAlternatives("g++", `${binDir}/g++-${majorVersion}`)
promises.push(
updateAptAlternatives("cc", `${binDir}/gcc-${majorVersion}`),
updateAptAlternatives("cxx", `${binDir}/g++-${majorVersion}`),
updateAptAlternatives("gcc", `${binDir}/gcc-${majorVersion}`),
updateAptAlternatives("g++", `${binDir}/g++-${majorVersion}`)
)
}
} else {
promises.push(addEnv("CC", `${binDir}/gcc-${version}`), addEnv("CXX", `${binDir}/g++-${version}`))
if (isUbuntu()) {
updateAptAlternatives("cc", `${binDir}/gcc-${version}`)
updateAptAlternatives("cxx", `${binDir}/g++-${version}`)
updateAptAlternatives("gcc", `${binDir}/gcc-${version}`)
updateAptAlternatives("g++", `${binDir}/g++-${version}`)
promises.push(
updateAptAlternatives("cc", `${binDir}/gcc-${version}`),
updateAptAlternatives("cxx", `${binDir}/g++-${version}`),
updateAptAlternatives("gcc", `${binDir}/gcc-${version}`),
updateAptAlternatives("g++", `${binDir}/g++-${version}`)
)
}
}
}
@ -191,15 +198,15 @@ async function activateGcc(version: string, binDir: string) {
promises.push(setupMacOSSDK())
if (ciDetect() === "github-actions") {
addGccLoggingMatcher()
await addGccLoggingMatcher()
}
await Promise.all(promises)
}
function addGccLoggingMatcher() {
async function addGccLoggingMatcher() {
const matcherPath = join(__dirname, "gcc_matcher.json")
if (!existsSync(matcherPath)) {
if (!(await pathExists(matcherPath))) {
return warning("the gcc_matcher.json file does not exist in the same folder as setup_cpp.js")
}
info(`::add-matcher::${matcherPath}`)

View File

@ -25,7 +25,7 @@ export async function setupGraphviz(version: string, _setupDir: string, _arch: s
} else if (hasDnf()) {
return setupDnfPack("graphviz", version)
} else if (isUbuntu()) {
return setupAptPack("graphviz", version)
return setupAptPack([{ name: "graphviz", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -50,8 +50,7 @@ async function buildKcov(file: string, dest: string) {
setupDnfPack("libdwarf-devel")
setupDnfPack("libcurl-devel")
} else if (isUbuntu()) {
await setupAptPack("libdw-dev")
await setupAptPack("libcurl4-openssl-dev")
await setupAptPack([{ name: "libdw-dev" }, { name: "libcurl4-openssl-dev" }])
}
}
const buildDir = join(out, "build")
@ -102,7 +101,7 @@ export async function setupKcov(versionGiven: string, setupDir: string, arch: st
} else if (hasDnf()) {
setupDnfPack("binutils")
} else if (isUbuntu()) {
await setupAptPack("libbinutils")
await setupAptPack([{ name: "libbinutils" }])
}
return installationInfo
} else {

View File

@ -7,13 +7,14 @@ import { setupMacOSSDK } from "../macos-sdk/macos-sdk"
import { addEnv } from "../utils/env/addEnv"
import { setupAptPack, updateAptAlternatives } from "../utils/setup/setupAptPack"
import { info, warning } from "ci-log"
import { existsSync } from "fs"
import ciDetect from "@npmcli/ci-detect"
import { setupGcc } from "../gcc/gcc"
import { getVersion } from "../versions/versions"
import { isUbuntu } from "../utils/env/isUbuntu"
import { getLLVMPackageInfo } from "./llvm_url"
import { ubuntuVersion } from "../utils/env/ubuntu_version"
import pathExists from "path-exists"
export async function setupLLVM(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
const installationInfo = await setupLLVMWithoutActivation(version, setupDir, arch)
@ -51,9 +52,9 @@ async function setupLLVMDeps(arch: string, version: string) {
if (isUbuntu()) {
const majorVersion = parseInt(version.split(".")[0], 10)
if (majorVersion <= 10) {
await setupAptPack("libtinfo5")
await setupAptPack([{ name: "libtinfo5" }])
} else {
await setupAptPack("libtinfo-dev")
await setupAptPack([{ name: "libtinfo-dev" }])
}
}
// TODO: install libtinfo on other distros
@ -69,7 +70,7 @@ export async function activateLLVM(directory: string, versionGiven: string) {
const ld = process.env.LD_LIBRARY_PATH ?? ""
const dyld = process.env.DYLD_LIBRARY_PATH ?? ""
const promises = [
const promises: Promise<any>[] = [
// the output of this action
addEnv("LLVM_PATH", directory),
@ -94,41 +95,43 @@ export async function activateLLVM(directory: string, versionGiven: string) {
// windows builds fail with llvm's CPATH
if (process.platform !== "win32") {
const llvmMajor = semverMajor(version)
if (existsSync(`${directory}/lib/clang/${version}/include`)) {
if (await pathExists(`${directory}/lib/clang/${version}/include`)) {
promises.push(addEnv("CPATH", `${directory}/lib/clang/${version}/include`))
} else if (existsSync(`${directory}/lib/clang/${llvmMajor}/include`)) {
} else if (await pathExists(`${directory}/lib/clang/${llvmMajor}/include`)) {
promises.push(addEnv("CPATH", `${directory}/lib/clang/${llvmMajor}/include`))
}
}
if (isUbuntu()) {
updateAptAlternatives("cc", `${directory}/bin/clang`)
updateAptAlternatives("cxx", `${directory}/bin/clang++`)
updateAptAlternatives("clang", `${directory}/bin/clang`)
updateAptAlternatives("clang++", `${directory}/bin/clang++`)
updateAptAlternatives("lld", `${directory}/bin/lld`)
updateAptAlternatives("ld.lld", `${directory}/bin/ld.lld`)
updateAptAlternatives("llvm-ar", `${directory}/bin/llvm-ar`)
promises.push(
updateAptAlternatives("cc", `${directory}/bin/clang`),
updateAptAlternatives("cxx", `${directory}/bin/clang++`),
updateAptAlternatives("clang", `${directory}/bin/clang`),
updateAptAlternatives("clang++", `${directory}/bin/clang++`),
updateAptAlternatives("lld", `${directory}/bin/lld`),
updateAptAlternatives("ld.lld", `${directory}/bin/ld.lld`),
updateAptAlternatives("llvm-ar", `${directory}/bin/llvm-ar`)
)
}
if (ciDetect() === "github-actions") {
addLLVMLoggingMatcher()
await addLLVMLoggingMatcher()
}
await Promise.all(promises)
}
/** Setup llvm tools (clang tidy, clang format, etc) without activating llvm and using it as the compiler */
export function setupClangTools(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
export async function setupClangTools(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
if (ciDetect() === "github-actions") {
addLLVMLoggingMatcher()
await addLLVMLoggingMatcher()
}
return setupLLVMWithoutActivation(version, setupDir, arch)
}
function addLLVMLoggingMatcher() {
async function addLLVMLoggingMatcher() {
const matcherPath = join(__dirname, "llvm_matcher.json")
if (!existsSync(matcherPath)) {
if (!(await pathExists(matcherPath))) {
return warning("the llvm_matcher.json file does not exist in the same folder as setup_cpp.js")
}
info(`::add-matcher::${matcherPath}`)

View File

@ -270,7 +270,7 @@ export async function main(args: string[]): Promise<number> {
info(`took ${timeFormatter.format(time1, time2) || "0 seconds"}`)
}
finalizeCpprc()
await finalizeCpprc()
if (successMessages.length === 0 && errorMessages.length === 0) {
warning("setup_cpp was called without any arguments. Nothing to do.")

View File

@ -25,7 +25,7 @@ export async function setupMake(version: string, _setupDir: string, _arch: strin
} else if (hasDnf()) {
return setupDnfPack("make", version)
} else if (isUbuntu()) {
return setupAptPack("make", version)
return setupAptPack([{ name: "make", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -5,8 +5,9 @@ import { setupVCVarsall } from "../vcvarsall/vcvarsall"
import { vsversion_to_versionnumber, findVcvarsall } from "msvc-dev-cmd/lib.js"
import ciDetect from "@npmcli/ci-detect"
import { join } from "patha"
import { existsSync } from "fs"
import { error, info, warning } from "ci-log"
import pathExists from "path-exists"
type MSVCVersion = "2022" | "17.0" | "2019" | "16.0" | "2017" | "15.0" | "2015" | "14.0" | "2013" | "12.0" | string
@ -66,13 +67,13 @@ export async function setupMSVC(
await setupVCVarsall(version, VCTargetsPath, arch, toolset, sdk, uwp, spectre)
if (ciDetect() === "github-actions") {
addMSVCLoggingMatcher()
await addMSVCLoggingMatcher()
}
}
function addMSVCLoggingMatcher() {
async function addMSVCLoggingMatcher() {
const matcherPath = join(__dirname, "msvc_matcher.json")
if (!existsSync(matcherPath)) {
if (!(await pathExists(matcherPath))) {
return warning("the msvc_matcher.json file does not exist in the same folder as setup_cpp.js")
}
info(`::add-matcher::${matcherPath}`)

View File

@ -33,12 +33,12 @@ export async function setupNala(version: string, _setupDir: string, _arch: strin
try {
if (version !== "legacy") {
await setupAptPack("nala", undefined, [], true)
await setupAptPack([{ name: "nala" }], true)
} else {
await setupAptPack("nala-legacy", undefined, [], true)
await setupAptPack([{ name: "nala-legacy" }], true)
}
} catch (err) {
await setupAptPack("nala-legacy", undefined, [], true)
await setupAptPack([{ name: "nala-legacy" }], true)
}
binDir = "/usr/bin" // eslint-disable-line require-atomic-updates

View File

@ -33,7 +33,7 @@ export async function setupPowershell(version: string | undefined, _setupDir: st
])
return setupDnfPack("powershell", version)
} else if (isUbuntu()) {
await setupAptPack("curl")
await setupAptPack([{ name: "curl" }])
const ubuntuVerSplitted = (await ubuntuVersion())!
const ubuntuVersionString = `${ubuntuVerSplitted[0]}.0${ubuntuVerSplitted[1]}`
@ -53,7 +53,7 @@ export async function setupPowershell(version: string | undefined, _setupDir: st
// `echo "deb [arch=amd64 signed-by=${keyFileName}] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list`,
// ])
return setupAptPack("powershell", version, [], true)
return setupAptPack([{ name: "powershell", version }], true)
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -1,12 +1,13 @@
import { useCpythonVersion } from "setup-python/src/find-python"
import { findPyPyVersion } from "setup-python/src/find-pypy"
import { existsSync } from "fs"
import { info, warning } from "ci-log"
import { debug } from "@actions/core"
import { join } from "patha"
import ciDetect from "@npmcli/ci-detect"
import { isCacheFeatureAvailable, IS_MAC } from "setup-python/src/utils"
import { getCacheDistributor } from "setup-python/src/cache-distributions/cache-factory"
import pathExists from "path-exists"
function isPyPyVersion(versionSpec: string) {
return versionSpec.startsWith("pypy")
@ -51,15 +52,15 @@ export async function setupActionsPython(version: string, _setupDir: string, arc
}
if (ciDetect() === "github-actions") {
addPythonLoggingMatcher()
await addPythonLoggingMatcher()
}
return undefined
}
function addPythonLoggingMatcher() {
async function addPythonLoggingMatcher() {
const matcherPath = join(__dirname, "python_matcher.json")
if (!existsSync(matcherPath)) {
if (!(await pathExists(matcherPath))) {
return warning("the python_matcher.json file does not exist in the same folder as setup_cpp.js")
}
info(`::add-matcher::${matcherPath}`)

View File

@ -69,8 +69,7 @@ export async function setupPythonViaSystem(
installInfo = setupDnfPack("python3", version)
setupDnfPack("python3-pip")
} else if (isUbuntu()) {
installInfo = await setupAptPack("python3", version)
await setupAptPack("python3-pip")
installInfo = await setupAptPack([{ name: "python3", version }, { name: "python3-pip" }])
} else {
throw new Error(`Unsupported linux distributions`)
}
@ -118,7 +117,7 @@ export async function setupPythonAndPip(): Promise<string> {
} else if (hasDnf()) {
setupDnfPack("python3-pip")
} else if (isUbuntu()) {
await setupAptPack("python3-pip")
await setupAptPack([{ name: "python3-pip" }])
}
}

View File

@ -23,7 +23,7 @@ export function setupSevenZip(version: string, _setupDir: string, _arch: string)
setupDnfPack("p7zip", version)
return setupDnfPack("p7zip-plugins", version)
} else if (isUbuntu()) {
return setupAptPack("p7zip-full", version)
return setupAptPack([{ name: "p7zip-full", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -1,13 +1,14 @@
import { exportVariable, addPath as ghAddPath, info, setFailed } from "@actions/core"
import ciDetect from "@npmcli/ci-detect"
import { untildifyUser } from "untildify-user"
import { appendFileSync, existsSync, readFileSync, writeFileSync } from "fs"
import { appendFileSync, readFileSync, writeFileSync } from "fs"
import { error, warning } from "ci-log"
import { execPowershell } from "exec-powershell"
import { delimiter } from "path"
import escapeSpace from "escape-path-with-spaces"
import { giveUserAccess } from "user-access"
import escapeQuote from "escape-quotes"
import pathExists from "path-exists"
/**
* Add an environment variable.
@ -75,7 +76,7 @@ async function addEnvSystem(name: string, valGiven: string | undefined) {
}
case "linux":
case "darwin": {
setupCppInProfile()
await setupCppInProfile()
appendFileSync(cpprc_path, `\nexport ${name}="${val}"\n`)
info(`${name}="${val}" was added to "${cpprc_path}`)
return
@ -99,7 +100,7 @@ async function addPathSystem(path: string) {
}
case "linux":
case "darwin": {
setupCppInProfile()
await setupCppInProfile()
appendFileSync(cpprc_path, `\nexport PATH="${path}:$PATH"\n`)
info(`"${path}" was added to "${cpprc_path}"`)
return
@ -113,7 +114,7 @@ async function addPathSystem(path: string) {
let setupCppInProfile_called = false
/// handles adding conditions to source .cpprc file from .bashrc and .profile
export function setupCppInProfile() {
export async function setupCppInProfile() {
if (setupCppInProfile_called) {
return
}
@ -121,7 +122,7 @@ export function setupCppInProfile() {
// a variable that prevents source_cpprc from being called from .bashrc and .profile
const source_cpprc_str = "# Automatically Generated by setup-cpp\nexport SOURCE_CPPRC=0"
if (existsSync(cpprc_path)) {
if (await pathExists(cpprc_path)) {
const cpprc_content = readFileSync(cpprc_path, "utf8")
if (cpprc_content.includes(source_cpprc_str)) {
// already executed setupCppInProfile
@ -153,8 +154,8 @@ export function setupCppInProfile() {
setupCppInProfile_called = true
}
export function finalizeCpprc() {
if (existsSync(cpprc_path)) {
export async function finalizeCpprc() {
if (await pathExists(cpprc_path)) {
const entries = readFileSync(cpprc_path, "utf-8").split("\n")
const unique_entries = [...new Set(entries.reverse())].reverse() // remove duplicates, keeping the latest entry

View File

@ -8,7 +8,7 @@ export async function ubuntuVersion(): Promise<number[] | null> {
try {
if (isUbuntu()) {
if (which.sync("lsb_release", { nothrow: true }) === null) {
await setupAptPack("lsb-release")
await setupAptPack([{ name: "lsb-release" }])
}
const versionSplitted = await getUbuntuVersion()

View File

@ -1,25 +1,32 @@
/* eslint-disable require-atomic-updates */
import { InstallationInfo } from "./setupBin"
import { execRootSync } from "admina"
import { execRoot, execRootSync } from "admina"
import { info } from "@actions/core"
import ciDetect from "@npmcli/ci-detect"
import { addEnv, cpprc_path, setupCppInProfile } from "../env/addEnv"
import { appendFileSync, existsSync } from "fs"
import which from "which"
import pathExists from "path-exists"
import { promises as fsPromises } from "fs"
const { appendFile } = fsPromises
import execa from "execa"
import escapeRegex from "escape-string-regexp"
let didUpdate: boolean = false
let didInit: boolean = false
export type AptPackage = {
name: string
version?: string
repositories?: string[]
}
/** A function that installs a package using apt */
export async function setupAptPack(
name: string,
version?: string,
repositories: string[] = [],
update = false
): Promise<InstallationInfo> {
export async function setupAptPack(packages: AptPackage[], update = false): Promise<InstallationInfo> {
const apt: string = getApt()
info(`Installing ${name} ${version ?? ""} via ${apt}`)
for (const { name, version } of packages) {
info(`Installing ${name} ${version ?? ""} via ${apt}`)
}
process.env.DEBIAN_FRONTEND = "noninteractive"
@ -33,27 +40,40 @@ export async function setupAptPack(
didInit = true
}
if (Array.isArray(repositories) && repositories.length !== 0) {
for (const repo of repositories) {
const allRepositories = [...new Set(packages.flatMap((pack) => pack.repositories ?? []))]
if (allRepositories.length !== 0) {
for (const repo of allRepositories) {
// eslint-disable-next-line no-await-in-loop
execRootSync("add-apt-repository", ["--update", "-y", repo])
execRootSync("add-apt-repository", ["-y", repo])
}
updateRepos(apt)
}
if (version !== undefined && version !== "") {
try {
execRootSync(apt, ["install", "--fix-broken", "-y", `${name}=${version}`])
} catch {
execRootSync(apt, ["install", "--fix-broken", "-y", `${name}-${version}`])
}
} else {
execRootSync(apt, ["install", "--fix-broken", "-y", name])
}
const aptArgs = await Promise.all(packages.map((pack) => getAptArg(pack.name, pack.version)))
execRootSync(apt, ["install", "--fix-broken", "-y", ...aptArgs])
return { binDir: "/usr/bin/" }
}
async function getAptArg(name: string, version: string | undefined) {
if (version !== undefined && version !== "") {
const { stdout } = await execa("apt-cache", [
"search",
"--names-only",
`^${escapeRegex(name)}\-${escapeRegex(version)}$`,
])
if (stdout.trim() !== "") {
return `${name}-${version}`
} else {
return `${name}=${version}`
}
} else {
return name
}
}
function getApt() {
let apt: string
if (which.sync("nala", { nothrow: true }) !== null) {
@ -79,56 +99,61 @@ async function initApt(apt: string) {
"ca-certificates",
"gnupg",
])
addAptKeyViaServer(["3B4FE6ACC0B21F32", "40976EAF437D05B5"], "setup-cpp-ubuntu-archive.gpg")
addAptKeyViaServer(["1E9377A2BA9EF27F"], "launchpad-toolchain.gpg")
const promises: Promise<any>[] = [
addAptKeyViaServer(["3B4FE6ACC0B21F32", "40976EAF437D05B5"], "setup-cpp-ubuntu-archive.gpg"),
addAptKeyViaServer(["1E9377A2BA9EF27F"], "launchpad-toolchain.gpg"),
]
if (apt === "nala") {
// enable utf8 otherwise it fails because of the usage of ASCII encoding
await addEnv("LANG", "C.UTF-8")
await addEnv("LC_ALL", "C.UTF-8")
promises.push(addEnv("LANG", "C.UTF-8"), addEnv("LC_ALL", "C.UTF-8"))
}
await Promise.all(promises)
}
function initGpg() {
execRootSync("gpg", ["-k"])
}
export function addAptKeyViaServer(keys: string[], name: string, server = "keyserver.ubuntu.com") {
export async function addAptKeyViaServer(keys: string[], name: string, server = "keyserver.ubuntu.com") {
const fileName = `/etc/apt/trusted.gpg.d/${name}`
if (!existsSync(fileName)) {
if (!(await pathExists(fileName))) {
initGpg()
for (const key of keys) {
execRootSync("gpg", [
"--no-default-keyring",
"--keyring",
`gnupg-ring:${fileName}`,
"--keyserver",
server,
"--recv-keys",
key,
])
execRootSync("chmod", ["644", fileName])
}
await Promise.all(
keys.map(async (key) => {
await execRoot("gpg", [
"--no-default-keyring",
"--keyring",
`gnupg-ring:${fileName}`,
"--keyserver",
server,
"--recv-keys",
key,
])
await execRoot("chmod", ["644", fileName])
})
)
}
return fileName
}
export async function addAptKeyViaDownload(name: string, url: string) {
const fileName = `/etc/apt/trusted.gpg.d/${name}`
if (!existsSync(fileName)) {
if (!(await pathExists(fileName))) {
initGpg()
await setupAptPack("curl", undefined)
await setupAptPack([{ name: "curl" }], undefined)
execRootSync("bash", ["-c", `curl -s ${url} | gpg --no-default-keyring --keyring gnupg-ring:${fileName} --import`])
execRootSync("chmod", ["644", fileName])
}
return fileName
}
export function updateAptAlternatives(name: string, path: string) {
export async function updateAptAlternatives(name: string, path: string) {
if (ciDetect() === "github-actions") {
return execRootSync("update-alternatives", ["--install", `/usr/bin/${name}`, name, path, "40"])
return execRoot("update-alternatives", ["--install", `/usr/bin/${name}`, name, path, "40"])
} else {
setupCppInProfile()
return appendFileSync(
await setupCppInProfile()
return appendFile(
cpprc_path,
`\nif [ $UID -eq 0 ]; then update-alternatives --install /usr/bin/${name} ${name} ${path} 40; fi\n`
)

View File

@ -2,7 +2,7 @@ import { find, downloadTool, cacheDir } from "@actions/tool-cache"
import { info } from "@actions/core"
import { addPath } from "../env/addEnv"
import { join } from "patha"
import { existsSync } from "fs"
import { tmpdir } from "os"
import ciDetect from "@npmcli/ci-detect"
import { setupAptPack } from "./setupAptPack"
@ -11,6 +11,7 @@ import { isArch } from "../env/isArch"
import { hasDnf } from "../env/hasDnf"
import { setupDnfPack } from "./setupDnfPack"
import { isUbuntu } from "../env/isUbuntu"
import pathExists from "path-exists"
/** A type that describes a package */
export type PackageInfo = {
@ -70,7 +71,7 @@ export async function setupBin(
if (dir) {
const installDir = join(dir, extractedFolderName)
const binDir = join(installDir, binRelativeDir)
if (existsSync(binDir) && existsSync(join(binDir, binFileName))) {
if (await pathExists(join(binDir, binFileName))) {
info(`${name} ${version} was found in the cache at ${binDir}.`)
await addPath(binDir)
@ -87,7 +88,7 @@ export async function setupBin(
const binFile = join(binDir, binFileName)
// download ane extract the package into the installation directory.
if (!existsSync(binDir) || !existsSync(binFile)) {
if ((await Promise.all([pathExists(binDir), pathExists(binFile)])).includes(false)) {
info(`Download and extract ${name} ${version}`)
if (!didInit) {
@ -102,9 +103,7 @@ export async function setupBin(
setupDnfPack("tar")
setupDnfPack("xz")
} else if (isUbuntu()) {
await setupAptPack("unzip")
await setupAptPack("tar")
await setupAptPack("xz-utils")
await setupAptPack([{ name: "unzip" }, { name: "tar" }, { name: "xz-utils" }])
}
}
// eslint-disable-next-line require-atomic-updates

View File

@ -3,10 +3,11 @@ import execa from "execa"
import { info } from "@actions/core"
import { addPythonBaseExecPrefix, setupPythonAndPip } from "../../python/python"
import { InstallationInfo } from "./setupBin"
import { existsSync } from "fs"
import { addExeExt, dirname, join } from "patha"
import { addPath } from "../env/addEnv"
import which from "which"
import pathExists from "path-exists"
let python: string | undefined
let binDirs: string[] | undefined
@ -27,15 +28,18 @@ export async function setupPipPack(name: string, version?: string): Promise<Inst
binDirs = await addPythonBaseExecPrefix(python)
}
const binDir = findBinDir(binDirs, name)
const binDir = await findBinDir(binDirs, name)
await addPath(binDir)
return { binDir }
}
function findBinDir(dirs: string[], name: string) {
const foundDir = dirs.find((dir) => existsSync(join(dir, addExeExt(name))))
async function findBinDir(dirs: string[], name: string) {
const exists = await Promise.all(dirs.map((dir) => pathExists(join(dir, addExeExt(name)))))
const dirIndex = exists.findIndex((exist) => exist)
const foundDir = dirs[dirIndex]
if (foundDir !== undefined) {
return foundDir
}

View File

@ -3,7 +3,8 @@ import { tmpdir } from "os"
import * as path from "patha"
import { addExeExt, join } from "patha"
import spawn from "cross-spawn"
import { existsSync } from "fs"
import pathExists from "path-exists"
export async function setupTmpDir(testName: string) {
const tempDirectory = path.join(tmpdir(), "setup cpp temp", testName)
@ -39,7 +40,7 @@ export async function testBin(
console.log(`Testing the existence of ${binDir}`)
expect(binDir).toBeDefined()
expect(binDir).not.toHaveLength(0)
expect(existsSync(binDir)).toBeTruthy()
expect(await pathExists(binDir)).toBeTruthy()
bin = join(binDir, addExeExt(name))
}

View File

@ -1,5 +1,5 @@
import execa from "execa"
import { existsSync } from "fs"
import { dirname, join, addShExt, addShRelativePrefix } from "patha"
import which from "which"
import { addPath } from "../utils/env/addEnv"
@ -12,6 +12,7 @@ import { hasDnf } from "../utils/env/hasDnf"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
import { giveUserAccess } from "user-access"
import pathExists from "path-exists"
let hasVCPKG = false
@ -35,16 +36,18 @@ export async function setupVcpkg(_version: string, setupDir: string, _arch: stri
setupDnfPack("git")
setupDnfPack("pkg-config")
} else if (isUbuntu()) {
await setupAptPack("curl")
await setupAptPack("zip")
await setupAptPack("unzip")
await setupAptPack("tar")
await setupAptPack("git")
await setupAptPack("pkg-config")
await setupAptPack([
{ name: "curl" },
{ name: "zip" },
{ name: "unzip" },
{ name: "tar" },
{ name: "git" },
{ name: "pkg-config" },
])
}
}
if (!existsSync(join(setupDir, addShExt("bootstrap-vcpkg", ".bat")))) {
if (!(await pathExists(join(setupDir, addShExt("bootstrap-vcpkg", ".bat"))))) {
execa.sync("git", ["clone", "https://github.com/microsoft/vcpkg"], { cwd: dirname(setupDir), stdio: "inherit" })
} else {
notice(`Vcpkg folder already exists at ${setupDir}. This might mean that ~/vcpkg is restored from the cache.`)

View File

@ -1,9 +1,9 @@
import { existsSync } from "fs"
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { setupMSVCDevCmd } from "msvc-dev-cmd/lib.js"
import { addEnv } from "../utils/env/addEnv"
import { info } from "ci-log"
import pathExists from "path-exists"
function getArch(arch: string): string {
switch (arch) {
@ -30,7 +30,7 @@ export async function setupVCVarsall(
uwp?: boolean,
spectre?: boolean
) {
if (VCTargetsPath !== undefined && existsSync(VCTargetsPath)) {
if (VCTargetsPath !== undefined && (await pathExists(VCTargetsPath))) {
info(`Adding ${VCTargetsPath} to PATH`)
await addEnv("VCTargetsPath", VCTargetsPath)
}