Merge pull request #363 from aminya/linux-arm-ci

ci:  tests and executables for Linux arm + fix Doxygen, Sccache on Linux Arm + fix old LLVM on latest Ubuntu arm + fix apt installation fallbacks to latest
This commit is contained in:
Amin Ya 2025-03-16 03:04:58 -07:00 committed by GitHub
commit a63071ebb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 254 additions and 114 deletions

View File

@ -86,6 +86,7 @@ jobs:
os:
- windows-2019
- ubuntu-20.04
- ubuntu-22.04-arm
- macos-13 # x64
- macos-14 # arm64
steps:
@ -143,7 +144,9 @@ jobs:
os:
- windows-2022
- windows-2019
- ubuntu-24.04-arm
- ubuntu-24.04
- ubuntu-22.04-arm
- ubuntu-22.04
- ubuntu-20.04
- macos-15 # arm64

View File

@ -75,18 +75,14 @@ Download the executable for your platform from [here](https://github.com/aminya/
```shell
# windows x64
curl -o ./setup-cpp.exe -LJ "https://github.com/aminya/setup-cpp/releases/download/v1.1.1/setup-cpp-x64-windows.exe"
# linux x64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v1.1.1/setup-cpp-x64-linux"
chmod +x ./setup-cpp
# linux arm64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v1.1.1/setup-cpp-arm64-linux"
# macos arm64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v1.1.1/setup-cpp-arm64-macos"
chmod +x ./setup-cpp
# macos x64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v1.1.1/setup-cpp-x64-macos"
chmod +x ./setup-cpp
```
An example that installs llvm, cmake, ninja, ccache, and vcpkg:
@ -99,6 +95,7 @@ An example that installs llvm, cmake, ninja, ccache, and vcpkg:
```shell
# linux/macos example
chmod +x ./setup-cpp
sudo ./setup-cpp --compiler llvm --cmake true --ninja true --ccache true --vcpkg true
source ~/.cpprc # activate cpp environment variables
```

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

@ -1 +1 @@
{"ninja":"1.12.1","cmake":"3.31.4","task":"3.40.1","powershell":"7.4.5","pip":">=22.2.0","python":">=3.7.9","meson":{"linux":{"ubuntu":{"20":"1.6.1","18":"0.61.4","else":"0.61.4"},"else":"1.6.1"},"else":"1.6.1"},"kcov":{"linux":{"ubuntu":{"22":"42-binary","20":"40-binary","14":"40","else":"42"},"else":"42"},"else":"42"},"doxygen":{"linux":{"archlinux":"1.12.0-2","ubuntu":{"22":"1.12.0","18":"1.10.0","else":"1.10.0"},"else":"1.12.0"},"else":"1.12.0"},"gcc":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"mingw":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"gcovr":{"linux":{"ubuntu":{"20":"","18":"5.0","else":"5.0"},"else":""},"else":""},"nala":{"linux":{"ubuntu":{"22":"","21":"legacy","else":"legacy"},"else":""},"else":""},"llvm":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang++":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-tidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangtidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-format":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangformat":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"}}
{"ninja":"1.12.1","cmake":"3.31.4","task":"3.40.1","powershell":"7.4.5","pip":">=22.2.0","python":">=3.7.9","meson":{"linux":{"ubuntu":{"20":"1.6.1","18":"0.61.4","else":"0.61.4"},"else":"1.6.1"},"else":"1.6.1"},"kcov":{"linux":{"ubuntu":{"22":"42-binary","20":"40-binary","14":"40","else":"42"},"else":"42"},"else":"42"},"doxygen":{"linux":{"archlinux":"1.13.2-1","ubuntu":{"22":"1.13.2","18":"1.10.0","else":"1.10.0"},"else":"1.13.2"},"else":"1.13.2"},"gcc":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"mingw":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"gcovr":{"linux":{"ubuntu":{"20":"","18":"5.0","else":"5.0"},"else":""},"else":""},"nala":{"linux":{"ubuntu":{"22":"","21":"legacy","else":"legacy"},"else":""},"else":""},"llvm":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang++":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-tidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangtidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-format":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangformat":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"}}

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

@ -1 +1 @@
{"ninja":"1.12.1","cmake":"3.31.4","task":"3.40.1","powershell":"7.4.5","pip":">=22.2.0","python":">=3.7.9","meson":{"linux":{"ubuntu":{"20":"1.6.1","18":"0.61.4","else":"0.61.4"},"else":"1.6.1"},"else":"1.6.1"},"kcov":{"linux":{"ubuntu":{"22":"42-binary","20":"40-binary","14":"40","else":"42"},"else":"42"},"else":"42"},"doxygen":{"linux":{"archlinux":"1.12.0-2","ubuntu":{"22":"1.12.0","18":"1.10.0","else":"1.10.0"},"else":"1.12.0"},"else":"1.12.0"},"gcc":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"mingw":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"gcovr":{"linux":{"ubuntu":{"20":"","18":"5.0","else":"5.0"},"else":""},"else":""},"nala":{"linux":{"ubuntu":{"22":"","21":"legacy","else":"legacy"},"else":""},"else":""},"llvm":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang++":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-tidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangtidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-format":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangformat":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"}}
{"ninja":"1.12.1","cmake":"3.31.4","task":"3.40.1","powershell":"7.4.5","pip":">=22.2.0","python":">=3.7.9","meson":{"linux":{"ubuntu":{"20":"1.6.1","18":"0.61.4","else":"0.61.4"},"else":"1.6.1"},"else":"1.6.1"},"kcov":{"linux":{"ubuntu":{"22":"42-binary","20":"40-binary","14":"40","else":"42"},"else":"42"},"else":"42"},"doxygen":{"linux":{"archlinux":"1.13.2-1","ubuntu":{"22":"1.13.2","18":"1.10.0","else":"1.10.0"},"else":"1.13.2"},"else":"1.13.2"},"gcc":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"mingw":{"win32":"14.2.0posix-18.1.8-12.0.0-ucrt-r1","else":""},"gcovr":{"linux":{"ubuntu":{"20":"","18":"5.0","else":"5.0"},"else":""},"else":""},"nala":{"linux":{"ubuntu":{"22":"","21":"legacy","else":"legacy"},"else":""},"else":""},"llvm":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang++":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-tidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangtidy":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clang-format":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"},"clangformat":{"darwin":{"else":{"else":{"x64":"15.0.7","else":"18.1.8"}}},"else":"19.1.6"}}

View File

@ -1,6 +1,6 @@
{
"name": "setup-apt",
"version": "3.0.1",
"version": "3.0.2",
"description": "Setup apt packages and repositories in Debian/Ubuntu-based distributions",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/setup-apt",

View File

@ -1,4 +1,4 @@
import { warning } from "ci-log"
import { info } from "ci-log"
import escapeRegex from "escape-string-regexp"
import { execa } from "execa"
import { getAptEnv } from "./apt-env.js"
@ -37,70 +37,97 @@ export async function qualifiedNeededAptPackage(pack: AptPackage, apt: string =
return (await isAptPackInstalled(qualified)) ? undefined : qualified
}
async function aptPackageType(apt: string, name: string, version: string | undefined): Promise<AptPackageType> {
if (version !== undefined && version !== "") {
const { stdout } = await execa("apt-cache", [
"search",
"--names-only",
`^${escapeRegex(name)}-${escapeRegex(version)}$`,
], { env: getAptEnv(apt), stdio: "pipe" })
if (stdout.trim() !== "") {
async function aptPackageType(
apt: string,
name: string,
version: string | undefined,
fallBackToLatest: boolean,
): Promise<AptPackageType> {
const hasVersion = version !== undefined && version !== ""
const canFallBackToLatest = !hasVersion || fallBackToLatest
if (hasVersion) {
// check if apt-get search can find the version
if (await aptCacheSearchHasPackage(apt, name, version)) {
return AptPackageType.NameDashVersion
}
try {
// check if apt-get show can find the version
// eslint-disable-next-line @typescript-eslint/no-shadow
const { stdout } = await execa("apt-cache", ["show", `${name}=${version}`], { env: getAptEnv(apt) })
if (stdout.trim() === "") {
return AptPackageType.NameEqualsVersion
}
} catch {
// ignore
// check if apt-get show can find the version
if (await aptCacheShowHasPackage(apt, `${name}=${version}`)) {
return AptPackageType.NameEqualsVersion
}
}
try {
const { stdout: showStdout } = await execa("apt-cache", ["show", name], { env: getAptEnv(apt), stdio: "pipe" })
if (showStdout.trim() !== "") {
return AptPackageType.Name
const logFallback = () => {
if (hasVersion && fallBackToLatest) {
info(`Could not find package ${name} ${version}. Falling back to latest version.`)
}
} catch {
// ignore
}
if (canFallBackToLatest && await aptCacheShowHasPackage(apt, name)) {
// if the version is undefined or empty, return the name as a package name
logFallback()
return AptPackageType.Name
}
// If apt-cache fails, update the repos and try again
if (!updatedRepos) {
updateAptReposMemoized(apt)
return aptPackageType(apt, name, version)
return aptPackageType(apt, name, version, fallBackToLatest)
}
if (version === undefined || version === "") {
if (canFallBackToLatest) {
// if the version is undefined or empty, return the name as a package name
logFallback()
return AptPackageType.Name
}
return AptPackageType.None
}
async function aptCacheSearchHasPackage(apt: string, name: string, version: string) {
try {
const { stdout } = await execa("apt-cache", [
"search",
"--names-only",
`^${escapeRegex(name)}-${escapeRegex(version)}$`,
], { env: getAptEnv(apt), stdio: "pipe" })
if (stdout.trim() !== "") {
return true
}
} catch {
// ignore
}
return false
}
async function aptCacheShowHasPackage(apt: string, arg: string) {
try {
const { stdout } = await execa("apt-cache", ["show", arg], {
env: getAptEnv(apt),
stdio: "pipe",
verbose: true,
})
if (stdout.trim() !== "") {
return true
}
} catch {
// ignore
}
return false
}
async function getAptArg(apt: string, pack: AptPackage) {
const { name, version, fallBackToLatest = false } = pack
const package_type = await aptPackageType(apt, name, version)
const package_type = await aptPackageType(apt, name, version, fallBackToLatest)
switch (package_type) {
case AptPackageType.NameDashVersion:
return `${name}-${version}`
case AptPackageType.NameEqualsVersion:
return `${name}=${version}`
case AptPackageType.Name: {
if (version === undefined || version === "") {
return name
}
if (fallBackToLatest) {
warning(`Could not find package '${name}' with version '${version}'. Installing the latest version.`)
return name
}
throw new Error(`Could not find package '${name}' with version '${version}'`)
return name
}
default:
throw new Error(`Could not find package '${name}' ${version ?? "with unspecified version"}`)

View File

@ -7,7 +7,10 @@ import { setupBrew } from "../src/index.js"
jest.setTimeout(300000)
describe("setup-brew", () => {
if (process.platform === "win32") {
if (
process.platform === "win32"
|| process.platform === "linux" && process.arch !== "x64"
) {
it.skip("should setup brew", () => {})
return
}

View File

@ -1,6 +1,6 @@
{
"name": "setup-brew",
"version": "1.1.0",
"version": "1.1.1",
"description": "Setup brew and brew packages",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/setup-brew",

View File

@ -1,5 +1,6 @@
import { tmpdir } from "os"
import { dirname, join } from "path"
import { warning } from "ci-log"
import { type AddPathOptions, addPath } from "envosman"
import { execaSync } from "execa"
import { DownloaderHelper } from "node-downloader-helper"
@ -21,9 +22,20 @@ export type SetupBrewOptions = {
arch?: never
}
/**
* Install brew
*
* @param options - Options for adding the brew path to the rc file
* @returns The path to the bin directory of brew if brew is installed, otherwise undefined if brew is not supported on the current platform
*/
export async function setupBrew(options: SetupBrewOptions = {}): Promise<InstallationInfo | undefined> {
// brew is only available on darwin and linux
if (!["darwin", "linux"].includes(process.platform)) {
if (
// brew is only available on darwin and linux
!["darwin", "linux"].includes(process.platform)
// brew is only supported on Linux x64
|| (process.platform === "linux" && process.arch !== "x64")
) {
warning(`Brew is not supported on ${process.platform} ${process.arch}`)
return undefined
}

27
src/asset-list.ts Normal file
View File

@ -0,0 +1,27 @@
import { basename, dirname } from "path"
import { execa } from "execa"
import glob from "fast-glob"
async function main() {
// create a github token from gh
const token = await execa("gh", ["auth", "token"])
process.env.GITHUB_TOKEN = token.stdout
const files = await glob("src/*/assets-list.ts", {
onlyFiles: true,
absolute: true,
ignore: ["node_modules"],
})
await Promise.all(files.map(async (file) => {
console.log(`Updating ${basename(dirname(file))}`)
const jsFile = file.replace(".ts", ".js")
await import(jsFile)
}))
}
main().catch((err) => {
console.error(err)
process.exit(1)
})

View File

@ -4,6 +4,12 @@ import { setupBazel } from "../bazel.js"
jest.setTimeout(300000)
describe("setup-bazel", () => {
if (process.platform === "linux" && process.arch === "arm64") {
it("should skip bazel tests on Linux arm64", () => {
expect(true).toBe(true)
})
return
}
it("should setup bazel", async () => {
const installInfo = await setupBazel("", "", process.arch)

View File

@ -1,6 +1,7 @@
import { execRootSync } from "admina"
import { execRoot } from "admina"
import { addAptKeyViaURL, installAptPack } from "setup-apt"
import { installBrewPack } from "setup-brew"
import { getDebArch } from "../utils/env/arch.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
@ -24,7 +25,7 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
} else if (hasDnf()) {
// https://bazel.build/install/redhat
await setupDnfPack([{ name: "dnf-plugins-core" }])
execRootSync("dnf", ["copr", "enable", "vbatts/bazel"])
await execRoot("dnf", ["copr", "enable", "vbatts/bazel"])
return setupDnfPack([{ name: "bazel4" }])
} else if (isUbuntu()) {
// https://bazel.build/install/ubuntu
@ -32,9 +33,11 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
fileName: "bazel-archive-keyring.gpg",
keyUrl: "https://bazel.build/bazel-release.pub.gpg",
})
execRootSync("bash", [
await execRoot("bash", [
"-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`,
`echo "deb [arch=${
getDebArch(process.arch)
} signed-by=${keyFileName}] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list`,
])
return installAptPack([{ name: "bazel", version }], true)
}

View File

@ -5,7 +5,7 @@ import { addExeExt } from "patha"
import { installAptPack } from "setup-apt"
import { installBrewPack } from "setup-brew"
import { setupGraphviz } from "../graphviz/graphviz.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
import { getVersion } from "../versions/versions.js"
@ -13,6 +13,7 @@ import { getVersion } from "../versions/versions.js"
import { pathExists } from "path-exists"
import retry from "retry-as-promised"
import { rcOptions } from "../cli-options.js"
import { arm64 } from "../utils/env/arch.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
@ -26,6 +27,9 @@ import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
function getDoxygenPackageInfo(version: string, platform: NodeJS.Platform, _arch: string): PackageInfo {
switch (platform) {
case "linux": {
if (process.arch === "arm64") {
throw new Error("Doxygen binaries are not available for Linux arm64")
}
const folderName = `doxygen-${version}`
return {
binRelativeDir: "bin/",
@ -90,33 +94,7 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
return installationInfo
}
case "linux": {
let installationInfo: InstallationInfo
if (version === "" || isArch() || hasDnf()) {
if (isArch()) {
installationInfo = await setupPacmanPack("doxygen", version)
} else if (hasDnf()) {
return setupDnfPack([{ name: "doxygen", version }])
} else if (isUbuntu()) {
installationInfo = await installAptPack([{ name: "doxygen", version }])
} else {
throw new Error("Unsupported linux distributions")
}
} else if (isUbuntu()) {
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)
try {
await installAptPack([{ name: "libclang-cpp9" }])
} catch (err) {
info(`Failed to download libclang-cpp9 that might be needed for running doxygen. ${err}`)
}
} catch (err) {
notice(`Failed to download doxygen binary. ${err}. Falling back to apt-get.`)
installationInfo = await installAptPack([{ name: "doxygen" }])
}
} else {
throw new Error("Unsupported linux distributions")
}
const installationInfo = await setupLinuxDoxygen(version, setupDir, arch)
await setupGraphviz(getVersion("graphviz", undefined, await ubuntuVersion()), "", arch)
return installationInfo
}
@ -125,6 +103,35 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
}
}
}
async function setupLinuxDoxygen(version: string, setupDir: string, arch: string) {
try {
if (isArch()) {
return await setupPacmanPack("doxygen", version)
} else if (hasDnf()) {
return setupDnfPack([{ name: "doxygen", version }])
} else if (isUbuntu()) {
return await installAptPack([{ name: "doxygen", version, fallBackToLatest: arm64.includes(arch) }])
} else {
throw new Error("Unsupported linux distributions")
}
} catch {
// fallback to setupBin if the installation failed
try {
const installationInfo = await setupBin("doxygen", version, getDoxygenPackageInfo, setupDir, arch)
if (isUbuntu()) {
try {
await installAptPack([{ name: "libclang-cpp-dev" }])
} catch (err) {
info(`Failed to download libclang-cpp-dev that might be needed for running doxygen. ${err}`)
}
}
return installationInfo
} catch (err) {
notice(`Failed to download doxygen binary. ${err}. Falling back to installing the latest version from apt-get.`)
return installAptPack([{ name: "doxygen" }])
}
}
}
async function activateWinDoxygen() {
switch (process.platform) {

View File

@ -3,6 +3,12 @@
"winlibs-x86_64-win32-seh-gcc-14.2.0-mingw-w64msvcrt-12.0.0-r1.7z",
"winlibs-x86_64-win32-seh-gcc-14.2.0-llvm-19.1.3-mingw-w64msvcrt-12.0.0-r1.7z"
],
"14.2.0posix-19.1.7-12.0.0-msvcrt-r3": [
"winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64msvcrt-12.0.0-r3.7z",
"winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.7-mingw-w64msvcrt-12.0.0-r3.7z",
"winlibs-i686-posix-dwarf-gcc-14.2.0-mingw-w64msvcrt-12.0.0-r3.7z",
"winlibs-i686-posix-dwarf-gcc-14.2.0-llvm-19.1.7-mingw-w64msvcrt-12.0.0-r3.7z"
],
"14.2.0posix-19.1.1-12.0.0-ucrt-r2": [
"winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64ucrt-12.0.0-r2.7z",
"winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.1-mingw-w64ucrt-12.0.0-r2.7z",
@ -27,6 +33,12 @@
"winlibs-i686-posix-dwarf-gcc-14.2.0-mingw-w64msvcrt-12.0.0-r1.7z",
"winlibs-i686-posix-dwarf-gcc-14.2.0-llvm-18.1.8-mingw-w64msvcrt-12.0.0-r1.7z"
],
"14.2.0posix-12.0.0-ucrt-r3": [
"winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64ucrt-12.0.0-r3.7z",
"winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.7-mingw-w64ucrt-12.0.0-r3.7z",
"winlibs-i686-posix-dwarf-gcc-14.2.0-mingw-w64ucrt-12.0.0-r3.7z",
"winlibs-i686-posix-dwarf-gcc-14.2.0-llvm-19.1.7-mingw-w64ucrt-12.0.0-r3.7z"
],
"14.2.0mcf-12.0.0-ucrt-r1": [
"winlibs-x86_64-mcf-seh-gcc-14.2.0-mingw-w64ucrt-12.0.0-r1.7z",
"winlibs-i686-mcf-dwarf-gcc-14.2.0-mingw-w64ucrt-12.0.0-r1.7z"

View File

@ -8,8 +8,8 @@ import { setupInfer } from "../infer.js"
jest.setTimeout(300000)
describe("setup-infer", () => {
if (process.platform === "win32") {
it("should skip infer tests on windows", () => {
if (process.platform === "win32" || (process.platform === "linux" && process.arch === "arm64")) {
it("should skip infer tests on Windows and Linux arm64", () => {
expect(true).toBe(true)
})
return

View File

@ -1,6 +1,31 @@
{
"llvmorg-20.1.0": [
"clang+llvm-20.1.0-x86_64-pc-windows-msvc.tar.xz",
"clang+llvm-20.1.0-armv7a-linux-gnueabihf.tar.gz",
"clang+llvm-20.1.0-aarch64-pc-windows-msvc.tar.xz",
"LLVM-20.1.0-woa64.exe",
"LLVM-20.1.0-win64.exe",
"LLVM-20.1.0-win32.exe",
"LLVM-20.1.0-macOS-ARM64.tar.xz",
"LLVM-20.1.0-Linux-X64.tar.xz",
"LLVM-20.1.0-Linux-ARM64.tar.xz"
],
"llvmorg-19.1.7": [
"clang+llvm-19.1.7-x86_64-pc-windows-msvc.tar.xz",
"clang+llvm-19.1.7-armv7a-linux-gnueabihf.tar.gz",
"clang+llvm-19.1.7-aarch64-linux-gnu.tar.xz",
"LLVM-19.1.7-woa64.exe",
"LLVM-19.1.7-win64.exe",
"LLVM-19.1.7-win32.exe",
"LLVM-19.1.7-macOS-X64.tar.xz",
"LLVM-19.1.7-macOS-ARM64.tar.xz",
"LLVM-19.1.7-Linux-X64.tar.xz"
],
"llvmorg-19.1.6": [
"clang+llvm-19.1.6-x86_64-pc-windows-msvc.tar.xz",
"clang+llvm-19.1.6-armv7a-linux-gnueabihf.tar.gz",
"clang+llvm-19.1.6-aarch64-linux-gnu.tar.xz",
"LLVM-19.1.6-woa64.exe",
"LLVM-19.1.6-win64.exe",
"LLVM-19.1.6-win32.exe",
"LLVM-19.1.6-macOS-X64.tar.xz",

View File

@ -5,7 +5,7 @@ import { info } from "ci-log"
import memoize from "memoizee"
import { DownloaderHelper } from "node-downloader-helper"
import { installAptPack } from "setup-apt"
import { arm64, x86_64 } from "../utils/env/arch.js"
import { getDebArch } from "../utils/env/arch.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
@ -17,11 +17,11 @@ import { majorLLVMVersion } from "./utils.js"
export async function setupLLVMBin(version: string, setupDir: string, arch: string) {
const installInfo = await setupBin("llvm", version, getLLVMPackageInfo, setupDir, arch)
await llvmBinaryDeps(majorLLVMVersion(version))
await llvmBinaryDeps(majorLLVMVersion(version), arch)
return installInfo
}
async function llvmBinaryDeps_(_majorVersion: number) {
async function llvmBinaryDeps_(_majorVersion: number, arch: string) {
if (isUbuntu()) {
for (const dep of ["libtinfo5", "libtinfo6"]) {
/* eslint-disable no-await-in-loop */
@ -32,14 +32,10 @@ async function llvmBinaryDeps_(_majorVersion: number) {
if (dep === "libtinfo5") {
// Manually install libtinfo5 if the package is not available
info(`Failed to install ${dep}\nManually installing the package`)
const arch = x86_64.includes(process.arch)
? "amd64"
: arm64.includes(process.arch)
? "arm64"
: process.arch
const fileName = `libtinfo5_6.3-2ubuntu0.1_${arch}.deb`
const url = `http://launchpadlibrarian.net/666971015/${fileName}`
const fileName = `libtinfo5_6.3-2ubuntu0.1_${getDebArch(arch)}.deb`
const url = `https://launchpad.net/ubuntu/+archive/primary/+files/${fileName}`
const dl = new DownloaderHelper(url, tmpdir(), { fileName })
dl.on("error", async (dlErr) => {
info(`Failed to download ${url}: ${dlErr}`)

View File

@ -4,6 +4,13 @@ import { setupSccache } from "../sccache.js"
jest.setTimeout(300000)
describe("setup-sccache", () => {
if (process.platform === "linux" && process.arch === "arm64") {
it("should skip sccache tests on Linux arm64", () => {
expect(true).toBe(true)
})
return
}
it("should setup sccache", async () => {
const installInfo = await setupSccache("", "", process.arch)

10
src/utils/env/arch.ts vendored
View File

@ -5,3 +5,13 @@ export const armv7 = ["armv7", "armv7a"]
export const powerpc64le = ["powerpc64le", "ppc64le"]
export const sparc64 = ["sparc64"]
export const sparcv9 = ["sparcv9"]
export function getDebArch(arch: string) {
if (arm64.includes(arch)) {
return "arm64"
} else if (x86_64.includes(arch)) {
return "amd64"
} else {
return arch
}
}

View File

@ -7,14 +7,17 @@ import { addExeExt } from "patha"
import { pathExists } from "path-exists"
export async function setupTmpDir(testName: string) {
const tempDirectory = path.join(tmpdir(), "setup cpp temp", testName)
export async function setupTmpDir(testName: string, useSpaces: boolean = false) {
const tempName = useSpaces ? "setup cpp temp" : "setup-cpp-temp"
const tempDirectory = path.join(tmpdir(), tempName, testName)
try {
await io.rmRF(tempDirectory)
await io.mkdirP(tempDirectory)
} catch {
console.log("Failed to remove test directories")
}
// eslint-disable-next-line require-atomic-updates
process.env.SETUP_CPP_DIR = tempDirectory
return tempDirectory
}

View File

@ -6,7 +6,9 @@ jest.setTimeout(300000)
describe("setup-vcpkg", () => {
let directory: string
beforeEach(async () => {
directory = await setupTmpDir("vcpkg")
// TODO setup-vcpkg bootstrap fails on Linux arm64 with spaces in the path
const noSpaces = process.platform === "linux" && process.arch === "arm64"
directory = await setupTmpDir("vcpkg", !noSpaces)
})
it("should setup vcpkg", async () => {

View File

@ -2,7 +2,7 @@ import { dirname, join } from "path"
import { grantUserWriteAccess } from "admina"
import { info, notice } from "ci-log"
import { addEnv, addPath } from "envosman"
import { execaSync } from "execa"
import { execa } from "execa"
import { pathExists } from "path-exists"
import { addShExt, addShRelativePrefix } from "patha"
import { installAptPack } from "setup-apt"
@ -57,17 +57,17 @@ export async function setupVcpkg(version: string, setupDir: string, arch: string
}
}
// clone if not already exists
if (!(await pathExists(join(setupDir, addShExt("bootstrap-vcpkg", ".bat"))))) {
execaSync("git", ["clone", "https://github.com/microsoft/vcpkg"], { cwd: dirname(setupDir), stdio: "inherit" })
} else {
if (await pathExists(join(setupDir, addShExt("bootstrap-vcpkg", ".bat")))) {
notice(`Vcpkg folder already exists at ${setupDir}. Skipping the clone`)
} else {
// clone if not already exists
await execa("git", ["clone", "https://github.com/microsoft/vcpkg"], { cwd: dirname(setupDir), stdio: "inherit" })
}
// if version specified, checkout the version
if (version !== "" && version !== "true") {
info(`Checking out vcpkg version ${version}`)
execaSync("git", ["checkout", version], {
await execa("git", ["checkout", version], {
cwd: setupDir,
stdio: "inherit",
})
@ -79,7 +79,7 @@ export async function setupVcpkg(version: string, setupDir: string, arch: string
}
// bootstrap vcpkg
execaSync(addShExt(addShRelativePrefix("bootstrap-vcpkg"), ".bat"), {
await execa(addShExt(addShRelativePrefix("bootstrap-vcpkg"), ".bat"), {
cwd: setupDir,
shell: true,
stdio: "inherit",

View File

@ -30,15 +30,15 @@
},
"doxygen": {
"linux": {
"archlinux": "1.12.0-2",
"archlinux": "1.13.2-1",
"ubuntu": {
"22": "1.12.0",
"22": "1.13.2",
"18": "1.10.0",
"else": "1.10.0"
},
"else": "1.12.0"
"else": "1.13.2"
},
"else": "1.12.0"
"else": "1.13.2"
},
"gcc": {
"win32": "14.2.0posix-18.1.8-12.0.0-ucrt-r1",