mirror of https://github.com/aminya/setup-cpp
feat: find LLVM assets based on platform/arch/version heuristics
This commit is contained in:
parent
22bfbec1e0
commit
e003dfdeac
|
@ -13,11 +13,11 @@ ignorePaths:
|
|||
- patches/*.patch
|
||||
- "**/github_*.json"
|
||||
- "**/llvm_org_releases.json"
|
||||
|
||||
words:
|
||||
- aarch
|
||||
- aminya
|
||||
- applellvm
|
||||
- armv
|
||||
- bazel
|
||||
- bazelisk
|
||||
- biome
|
||||
|
|
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
|
@ -1,7 +1,7 @@
|
|||
import { parseArgs } from "../cli-options.js"
|
||||
import { getCompilerInfo } from "../compilers.js"
|
||||
import type { Inputs } from "../tool.js"
|
||||
import { DefaultLinuxVersion } from "../versions/default_versions.js"
|
||||
import { DefaultUbuntuVersion } from "../versions/default_versions.js"
|
||||
import { getVersion, syncVersions } from "../versions/versions.js"
|
||||
|
||||
jest.setTimeout(300000)
|
||||
|
@ -55,18 +55,18 @@ describe("getVersion", () => {
|
|||
it("gcovr", () => {
|
||||
expect(getVersion("gcovr", "5.0")).toBe("5.0")
|
||||
if (process.platform === "linux") {
|
||||
expect(getVersion("gcovr", "true", [22, 4])).toBe(DefaultLinuxVersion.gcovr![22])
|
||||
expect(getVersion("gcovr", "true", [20, 4])).toBe(DefaultLinuxVersion.gcovr![20])
|
||||
expect(getVersion("gcovr", "true", [18, 4])).toBe(DefaultLinuxVersion.gcovr![18])
|
||||
expect(getVersion("gcovr", "true", [22, 4])).toBe(DefaultUbuntuVersion.gcovr![22])
|
||||
expect(getVersion("gcovr", "true", [20, 4])).toBe(DefaultUbuntuVersion.gcovr![20])
|
||||
expect(getVersion("gcovr", "true", [18, 4])).toBe(DefaultUbuntuVersion.gcovr![18])
|
||||
}
|
||||
})
|
||||
|
||||
it("llvm", () => {
|
||||
expect(getVersion("llvm", "13.0.0")).toBe("13.0.0")
|
||||
if (process.platform === "linux") {
|
||||
expect(getVersion("llvm", "true", [20, 4])).toBe(DefaultLinuxVersion.llvm![20])
|
||||
expect(getVersion("llvm", "true", [18, 4])).toBe(DefaultLinuxVersion.llvm![18])
|
||||
expect(getVersion("llvm", "true", [16, 4])).toBe(DefaultLinuxVersion.llvm![16])
|
||||
expect(getVersion("llvm", "true", [20, 4])).toBe(DefaultUbuntuVersion.llvm![20])
|
||||
expect(getVersion("llvm", "true", [18, 4])).toBe(DefaultUbuntuVersion.llvm![18])
|
||||
expect(getVersion("llvm", "true", [16, 4])).toBe(DefaultUbuntuVersion.llvm![16])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -48,6 +48,10 @@ async function getGccPackageInfo(version: string, platform: NodeJS.Platform, arc
|
|||
},
|
||||
)
|
||||
|
||||
if (asset === undefined) {
|
||||
throw new Error(`No asset found for version ${version} and arch ${arch}`)
|
||||
}
|
||||
|
||||
return {
|
||||
binRelativeDir: "bin/",
|
||||
binFileName: addExeExt("g++"),
|
||||
|
|
|
@ -3,25 +3,16 @@ import { fileURLToPath } from "url"
|
|||
import * as io from "@actions/io"
|
||||
import { execaSync } from "execa"
|
||||
import { chmod } from "fs/promises"
|
||||
import { isUrlOnline } from "is-url-online"
|
||||
import { addExeExt } from "patha"
|
||||
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
|
||||
import { getSpecificVersionAndUrl } from "../../utils/setup/version.js"
|
||||
import { setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
|
||||
import { getVersion } from "../../versions/versions.js"
|
||||
import { setupClangFormat, setupClangTools, setupLLVM } from "../llvm.js"
|
||||
import { VERSIONS, getLinuxUrl, getUrl } from "../llvm_url.js"
|
||||
import { getLLVMAssetURL } from "../llvm_url.js"
|
||||
|
||||
const dirname = typeof __dirname === "string" ? __dirname : path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
jest.setTimeout(400000)
|
||||
async function testUrl(version: string) {
|
||||
const [specificVersion, url] = await getSpecificVersionAndUrl(VERSIONS, process.platform, version, getUrl)
|
||||
|
||||
if (!(await isUrlOnline(url))) {
|
||||
throw new Error(`Failed to install Version: ${version} => ${specificVersion} \n URL: ${url}`)
|
||||
}
|
||||
}
|
||||
|
||||
describe("setup-llvm", () => {
|
||||
let directory: string
|
||||
|
@ -31,38 +22,15 @@ describe("setup-llvm", () => {
|
|||
|
||||
it("Finds URL for ubuntu version", async () => {
|
||||
expect(
|
||||
await getSpecificVersionAndUrl(
|
||||
VERSIONS,
|
||||
"linux",
|
||||
"13.0.0-ubuntu-16.04",
|
||||
(_plantform, version) => getLinuxUrl(version),
|
||||
),
|
||||
).toStrictEqual([
|
||||
"13.0.0-ubuntu-16.04",
|
||||
await getLLVMAssetURL("linux", "x86_64", "13.0.0"),
|
||||
).toStrictEqual(
|
||||
"https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz",
|
||||
])
|
||||
)
|
||||
expect(
|
||||
await getSpecificVersionAndUrl(
|
||||
VERSIONS,
|
||||
"linux",
|
||||
"13.0.1-ubuntu-18.04",
|
||||
(_plantform, version) => getLinuxUrl(version),
|
||||
),
|
||||
).toStrictEqual([
|
||||
"13.0.1-ubuntu-18.04",
|
||||
await getLLVMAssetURL("linux", "x86_64", "13.0.1"),
|
||||
).toStrictEqual(
|
||||
"https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/clang+llvm-13.0.1-x86_64-linux-gnu-ubuntu-18.04.tar.xz",
|
||||
])
|
||||
expect(
|
||||
await getSpecificVersionAndUrl(
|
||||
VERSIONS,
|
||||
"linux",
|
||||
"13.0.0-ubuntu-20.04",
|
||||
(_plantform, version) => getLinuxUrl(version),
|
||||
),
|
||||
).toStrictEqual([
|
||||
"13.0.0-ubuntu-20.04",
|
||||
"https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz",
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("Finds valid LLVM URLs", async () => {
|
||||
|
@ -89,7 +57,7 @@ describe("setup-llvm", () => {
|
|||
"5",
|
||||
"5.0.0",
|
||||
"4",
|
||||
].map((version) => testUrl(version)),
|
||||
].map((version) => getLLVMAssetURL(process.platform, process.arch, version)),
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
@ -1,329 +1,24 @@
|
|||
import { info, warning } from "ci-log"
|
||||
import { isUrlOnline } from "is-url-online"
|
||||
import path, { join } from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import { info } from "ci-log"
|
||||
import { addExeExt } from "patha"
|
||||
import semverLte from "semver/functions/lte"
|
||||
import { loadAssetList, matchAsset } from "../utils/asset/load-assets.js"
|
||||
import { hasDnf } from "../utils/env/hasDnf.js"
|
||||
import { isUbuntu } from "../utils/env/isUbuntu.js"
|
||||
import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
|
||||
import { extractExe, extractTarByExe } from "../utils/setup/extract.js"
|
||||
import type { PackageInfo } from "../utils/setup/setupBin.js"
|
||||
import { getSpecificVersionAndUrl, getSpecificVersions, getVersions } from "../utils/setup/version.js"
|
||||
|
||||
// ================================================
|
||||
// Version
|
||||
// ================================================
|
||||
|
||||
/** The specific and minimum LLVM versions supported by this action. */
|
||||
export const VERSIONS: Set<string> = getVersions([
|
||||
"3.5.0",
|
||||
"3.5.1",
|
||||
"3.5.2",
|
||||
"3.6.0",
|
||||
"3.6.1",
|
||||
"3.6.2",
|
||||
"3.7.0",
|
||||
"3.7.1",
|
||||
"3.8.0",
|
||||
"3.8.1",
|
||||
"3.9.0",
|
||||
"3.9.1",
|
||||
"4.0.0",
|
||||
"4.0.1",
|
||||
"5.0.0",
|
||||
"5.0.1",
|
||||
"5.0.2",
|
||||
"6.0.0",
|
||||
"6.0.1",
|
||||
"7.0.0",
|
||||
"7.0.1",
|
||||
"7.1.0",
|
||||
"8.0.0",
|
||||
"8.0.1",
|
||||
"9.0.0",
|
||||
"9.0.1",
|
||||
"10.0.0",
|
||||
"10.0.1",
|
||||
"11.0.0",
|
||||
"11.0.1",
|
||||
"11.1.0",
|
||||
"12.0.0",
|
||||
"12.0.1",
|
||||
"13.0.0",
|
||||
"13.0.1",
|
||||
"14.0.0",
|
||||
"14.0.1",
|
||||
"14.0.2",
|
||||
"14.0.3",
|
||||
"14.0.4",
|
||||
"14.0.5",
|
||||
"14.0.6",
|
||||
"15.0.0",
|
||||
"15.0.1",
|
||||
"15.0.2",
|
||||
"15.0.3",
|
||||
"15.0.4",
|
||||
"15.0.5",
|
||||
"15.0.6",
|
||||
"15.0.7",
|
||||
"16.0.0",
|
||||
"16.0.1",
|
||||
"16.0.2",
|
||||
"16.0.3",
|
||||
"16.0.4",
|
||||
"16.0.5",
|
||||
"16.0.6",
|
||||
"17.0.1",
|
||||
"17.0.2",
|
||||
"17.0.3",
|
||||
"17.0.4",
|
||||
"17.0.5",
|
||||
"17.0.6",
|
||||
"18.1.0",
|
||||
"18.1.1",
|
||||
"18.1.2",
|
||||
"18.1.3",
|
||||
"18.1.4",
|
||||
"18.1.5",
|
||||
"18.1.6",
|
||||
"18.1.7",
|
||||
"18.1.8",
|
||||
])
|
||||
|
||||
/** The LLVM versions that were never released for the Windows platform. */
|
||||
const WIN32_MISSING: Set<string> = new Set(["10.0.1", "15.0.5", "15.0.6", "17.0.5"])
|
||||
|
||||
/** The LLVM versions that were never released for the Darwin platform. */
|
||||
const DARWIN_X64_MISSING = new Set([
|
||||
"3.5.1",
|
||||
"3.6.1",
|
||||
"3.6.2",
|
||||
"3.7.1",
|
||||
"3.8.1",
|
||||
"3.9.1",
|
||||
"6.0.1",
|
||||
"7.0.1",
|
||||
"7.1.0",
|
||||
"8.0.1",
|
||||
"11.0.1",
|
||||
"11.1.0",
|
||||
"12.0.1",
|
||||
"15.0.4",
|
||||
"15.0.5",
|
||||
"15.0.6",
|
||||
"16.0.0",
|
||||
"16.0.1",
|
||||
"16.0.2",
|
||||
"16.0.3",
|
||||
"16.0.4",
|
||||
"16.0.5",
|
||||
"16.0.6",
|
||||
"17.0.1",
|
||||
"17.0.2",
|
||||
"17.0.3",
|
||||
"17.0.4",
|
||||
"17.0.5",
|
||||
"17.0.6",
|
||||
"18.1.0",
|
||||
"18.1.1",
|
||||
"18.1.2",
|
||||
"18.1.3",
|
||||
"18.1.4",
|
||||
"18.1.5",
|
||||
"18.1.6",
|
||||
"18.1.7",
|
||||
"18.1.8",
|
||||
])
|
||||
|
||||
/**
|
||||
* The LLVM versions that should use the last RC version instead of the release version for the Linux (Ubuntu) platform.
|
||||
* This is useful when there were binaries released for the Linux (Ubuntu) platform for the last RC version but not for
|
||||
* the actual release version.
|
||||
*/
|
||||
const UBUNTU_RC: Map<string, string> = new Map()
|
||||
|
||||
/**
|
||||
* The (latest) Ubuntu versions for each LLVM version.
|
||||
*
|
||||
* https://github.com/llvm/llvm-project/releases/tag/llvmorg-14.0.1 or https://releases.llvm.org/6.0.1
|
||||
*/
|
||||
// TODO change based on ubuntu version
|
||||
const UBUNTU_X64_SUFFIX_MAP: { [key: string]: string } = {
|
||||
"3.5.0": "-ubuntu-14.04",
|
||||
"3.5.1": "",
|
||||
"3.5.2": "-ubuntu-14.04",
|
||||
"3.6.0": "-ubuntu-14.04",
|
||||
"3.6.1": "-ubuntu-14.04",
|
||||
"3.6.2": "-ubuntu-14.04",
|
||||
"3.7.0": "-ubuntu-14.04",
|
||||
"3.7.1": "-ubuntu-14.04",
|
||||
"3.8.0": "-ubuntu-16.04",
|
||||
"3.8.1": "-ubuntu-16.04",
|
||||
"3.9.0": "-ubuntu-16.04",
|
||||
"3.9.1": "-ubuntu-16.04",
|
||||
"4.0.0": "-ubuntu-16.04",
|
||||
"5.0.0": "-ubuntu16.04",
|
||||
"5.0.1": "-ubuntu-16.04",
|
||||
"5.0.2": "-ubuntu-16.04",
|
||||
"6.0.0": "-ubuntu-16.04",
|
||||
"6.0.1": "-ubuntu-16.04",
|
||||
"7.0.0": "-ubuntu-16.04",
|
||||
"7.0.1": "-ubuntu-18.04",
|
||||
"7.1.0": "-ubuntu-14.04",
|
||||
"8.0.0": "-ubuntu-18.04",
|
||||
"9.0.0": "-ubuntu-18.04",
|
||||
"9.0.1": "-ubuntu-16.04",
|
||||
"10.0.0": "-ubuntu-18.04",
|
||||
"10.0.1": "-ubuntu-16.04",
|
||||
"11.0.0": "-ubuntu-20.04",
|
||||
"11.0.1": "-ubuntu-16.04",
|
||||
"11.1.0": "-ubuntu-16.04",
|
||||
"12.0.0": "-ubuntu-20.04",
|
||||
"12.0.1": "-ubuntu-16.04",
|
||||
"13.0.0": "-ubuntu-20.04",
|
||||
"13.0.0-ubuntu-16.04": "-ubuntu-16.04",
|
||||
"13.0.0-ubuntu-20.04": "-ubuntu-20.04",
|
||||
"13.0.1": "-ubuntu-18.04",
|
||||
"13.0.1-ubuntu-18.04": "-ubuntu-18.04",
|
||||
"14.0.0": "-ubuntu-18.04",
|
||||
"15.0.2": "-rhel86",
|
||||
"15.0.5": "-ubuntu-18.04",
|
||||
"15.0.6": "-ubuntu-18.04",
|
||||
"16.0.0": "-ubuntu-18.04",
|
||||
"16.0.2": "-ubuntu-22.04",
|
||||
"16.0.3": "-ubuntu-22.04",
|
||||
"16.0.4": "-ubuntu-22.04",
|
||||
"17.0.2": "-ubuntu-22.04",
|
||||
"17.0.4": "-ubuntu-22.04",
|
||||
"17.0.5": "-ubuntu-22.04",
|
||||
"17.0.6": "-ubuntu-22.04",
|
||||
"18.1.4": "-ubuntu-18.04",
|
||||
"18.1.7": "-ubuntu-18.04",
|
||||
"18.1.8": "-ubuntu-18.04",
|
||||
}
|
||||
|
||||
/** The latest supported LLVM version for the Linux (Ubuntu) platform. */
|
||||
const MAX_UBUNTU: string = "18.1.8"
|
||||
|
||||
// ================================================
|
||||
// URL
|
||||
// ================================================
|
||||
|
||||
/** Gets a LLVM download URL for GitHub. */
|
||||
function getGitHubUrl(version: string, prefix: string, suffix: string): string {
|
||||
const file = `${prefix}${version}${suffix}`
|
||||
return `https://github.com/llvm/llvm-project/releases/download/llvmorg-${version}/${file}`
|
||||
}
|
||||
|
||||
/** Gets a LLVM download URL for https://releases.llvm.org. */
|
||||
function getReleaseUrl(version: string, prefix: string, suffix: string): string {
|
||||
const file = `${prefix}${version}${suffix}`
|
||||
return `https://releases.llvm.org/${version}/${file}`
|
||||
}
|
||||
|
||||
/** Gets an LLVM download URL for the Darwin platform. */
|
||||
function getDarwinUrl(version: string): string | null {
|
||||
if (DARWIN_X64_MISSING.has(version)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const darwin = version === "9.0.0" ? "-darwin-apple" : "-apple-darwin"
|
||||
const prefix = "clang+llvm-"
|
||||
const suffix = `-x86_64${darwin}.tar.xz`
|
||||
if (semverLte(version, "9.0.1")) {
|
||||
return getReleaseUrl(version, prefix, suffix)
|
||||
} else {
|
||||
return getGitHubUrl(version, prefix, suffix)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets an LLVM download URL for the Linux (Ubuntu) platform. */
|
||||
export function getLinuxUrl(versionGiven: string): string {
|
||||
let version = versionGiven
|
||||
|
||||
const rc = UBUNTU_RC.get(version)
|
||||
if (rc !== undefined) {
|
||||
version = rc
|
||||
}
|
||||
|
||||
let linuxVersion: string
|
||||
// ubuntu-version is specified
|
||||
if (version.includes("ubuntu")) {
|
||||
const givenUbuntuVersion = version.replace(/-ubuntu-.*/, "")
|
||||
if (!VERSIONS.has(givenUbuntuVersion)) {
|
||||
throw new Error(`Unsupported Ubuntu version: ${givenUbuntuVersion}`)
|
||||
}
|
||||
linuxVersion = version.replace(givenUbuntuVersion, "")
|
||||
version = getSpecificVersions(VERSIONS, givenUbuntuVersion)[0]
|
||||
} else if (version !== "" && version in UBUNTU_X64_SUFFIX_MAP) {
|
||||
linuxVersion = UBUNTU_X64_SUFFIX_MAP[version]
|
||||
} else {
|
||||
// default to the maximum version
|
||||
linuxVersion = UBUNTU_X64_SUFFIX_MAP[MAX_UBUNTU]
|
||||
warning(`Falling back to LLVM version ${MAX_UBUNTU} ${linuxVersion} for the Ubuntu.`)
|
||||
}
|
||||
|
||||
const prefix = "clang+llvm-"
|
||||
|
||||
let suffix: string
|
||||
if (version === "5.0.0") {
|
||||
suffix = `-linux-x86_64${linuxVersion}.tar.xz`
|
||||
} else if (linuxVersion.includes("-rhel86")) {
|
||||
suffix = `-x86_64-unknown-linux-gnu${linuxVersion}.tar.xz`
|
||||
} else {
|
||||
suffix = `-x86_64-linux-gnu${linuxVersion}.tar.xz`
|
||||
}
|
||||
|
||||
if (semverLte(version, "9.0.1")) {
|
||||
return getReleaseUrl(version, prefix, suffix)
|
||||
} else {
|
||||
return getGitHubUrl(version, prefix, suffix)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets an LLVM download URL for the Windows platform. */
|
||||
async function getWin32Url(version: string): Promise<string | null> {
|
||||
if (WIN32_MISSING.has(version)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const prefix = "LLVM-"
|
||||
const suffix = semverLte(version, "3.7.0") ? "-win32.exe" : "-win64.exe"
|
||||
|
||||
const olderThan9_1 = semverLte(version, "9.0.1")
|
||||
let url: string
|
||||
let fallback = false
|
||||
if (olderThan9_1) {
|
||||
url = getReleaseUrl(version, prefix, suffix)
|
||||
if (!(await isUrlOnline(url))) {
|
||||
fallback = true // fallback to github
|
||||
}
|
||||
}
|
||||
if (fallback || !olderThan9_1) {
|
||||
url = getGitHubUrl(version, prefix, suffix)
|
||||
}
|
||||
|
||||
return url!
|
||||
}
|
||||
|
||||
/** Gets an LLVM download URL. */
|
||||
export function getUrl(platform: string, version: string): string | null | Promise<string | null> {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return getDarwinUrl(version)
|
||||
case "linux":
|
||||
return getLinuxUrl(version)
|
||||
case "win32":
|
||||
return getWin32Url(version)
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
const dirname = typeof __dirname === "string" ? __dirname : path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
export async function getLLVMPackageInfo(
|
||||
version: string,
|
||||
platform: NodeJS.Platform,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_arch: string,
|
||||
arch: string,
|
||||
): Promise<PackageInfo> {
|
||||
const [specificVersion, url] = await getSpecificVersionAndUrl(VERSIONS, platform, version, getUrl)
|
||||
info(`specific llvm version: ${specificVersion}`)
|
||||
const url = await getLLVMAssetURL(platform, arch, version)
|
||||
info(`Downloading LLVM from ${url}`)
|
||||
|
||||
return {
|
||||
url,
|
||||
extractedFolderName: "",
|
||||
|
@ -336,3 +31,195 @@ export async function getLLVMPackageInfo(
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLLVMAssetURL(platform: string, arch: string, version: string) {
|
||||
const { keywords, optionalKeywords } = await getAssetKeywords(platform, arch)
|
||||
|
||||
// first check the github releases
|
||||
const llvmGitHubAssets = await loadAssetList(
|
||||
join(dirname, "github_llvm_llvm-project.json"),
|
||||
)
|
||||
const ghAsset = matchAsset(
|
||||
llvmGitHubAssets,
|
||||
{
|
||||
version,
|
||||
keywords,
|
||||
optionalKeywords,
|
||||
filterMapTag(tag) {
|
||||
return tag.replace(/^llvmorg-/, "")
|
||||
},
|
||||
filterName(name) {
|
||||
return name.startsWith("LLVM-") || name.startsWith("clang+llvm-")
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if (ghAsset !== undefined) {
|
||||
return `https://github.com/llvm/llvm-project/releases/download/${ghAsset.tag}/${ghAsset.name}`
|
||||
}
|
||||
|
||||
// check the llvm website
|
||||
const llvmWebsiteAssets = await loadAssetList(
|
||||
join(dirname, "llvm_org_releases.json"),
|
||||
)
|
||||
|
||||
const websiteAsset = matchAsset(
|
||||
llvmWebsiteAssets,
|
||||
{
|
||||
version,
|
||||
keywords,
|
||||
optionalKeywords,
|
||||
},
|
||||
)
|
||||
|
||||
if (websiteAsset !== undefined) {
|
||||
return `https://llvm.org/releases/${websiteAsset.tag}/${websiteAsset.name}`
|
||||
}
|
||||
|
||||
throw new Error(`No asset found for version ${version} matching ${keywords} and ${optionalKeywords}`)
|
||||
}
|
||||
|
||||
async function getAssetKeywords(platform: string, arch: string) {
|
||||
const keywords: string[] = []
|
||||
const optionalKeywords: string[] = []
|
||||
|
||||
switch (platform) {
|
||||
case "win32": {
|
||||
switch (arch) {
|
||||
case "win64":
|
||||
case "x64":
|
||||
case "amd64":
|
||||
case "x86_64":
|
||||
case "64":
|
||||
keywords.push("win64")
|
||||
break
|
||||
case "win32":
|
||||
case "x86":
|
||||
case "i386":
|
||||
case "ia32":
|
||||
case "32":
|
||||
keywords.push("win32")
|
||||
break
|
||||
case "woa64":
|
||||
case "aarch64":
|
||||
case "arm64":
|
||||
case "arm": {
|
||||
keywords.push("woa64")
|
||||
break
|
||||
}
|
||||
default:
|
||||
info(`Using arch ${arch} for LLVM`)
|
||||
keywords.push(arch)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
case "linux": {
|
||||
keywords.push("linux")
|
||||
|
||||
if (isUbuntu()) {
|
||||
optionalKeywords.push("ubuntu")
|
||||
|
||||
const ubuntuVer = await ubuntuVersion()
|
||||
if (ubuntuVer !== null) {
|
||||
optionalKeywords.push(`${ubuntuVer[0]}`)
|
||||
const ubuntuMin = ubuntuVer[1] < 10 ? `0${ubuntuVer[1]}` : `${ubuntuVer[1]}`
|
||||
|
||||
optionalKeywords.push(`${ubuntuVer[0]}.${ubuntuMin}`)
|
||||
optionalKeywords.push(`${ubuntuVer[0]}.${ubuntuMin}.${ubuntuVer[2]}`)
|
||||
}
|
||||
} else if (hasDnf()) {
|
||||
optionalKeywords.push("rhel")
|
||||
}
|
||||
|
||||
switch (arch) {
|
||||
case "x86_64":
|
||||
case "x64":
|
||||
case "amd64":
|
||||
case "64":
|
||||
keywords.push("x86_64")
|
||||
break
|
||||
case "x86":
|
||||
case "i386":
|
||||
case "ia32":
|
||||
case "32":
|
||||
keywords.push("x86")
|
||||
break
|
||||
case "aarch64":
|
||||
case "arm64":
|
||||
case "arm":
|
||||
keywords.push("aarch64")
|
||||
break
|
||||
case "armv7a":
|
||||
case "armv7":
|
||||
keywords.push("armv7a")
|
||||
break
|
||||
case "powerpc64le":
|
||||
case "ppc64le":
|
||||
keywords.push("powerpc64le")
|
||||
break
|
||||
case "sparc64":
|
||||
keywords.push("sparc64")
|
||||
break
|
||||
default:
|
||||
info(`Using arch ${arch} for LLVM`)
|
||||
keywords.push(arch)
|
||||
break
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
case "darwin": {
|
||||
keywords.push("darwin")
|
||||
|
||||
switch (arch) {
|
||||
case "x86_64":
|
||||
case "x64":
|
||||
case "amd64":
|
||||
case "64":
|
||||
keywords.push("x86_64")
|
||||
break
|
||||
case "arm64":
|
||||
case "arm":
|
||||
case "aarch64":
|
||||
// allow falling back to x86_64 if arm64 is not available
|
||||
optionalKeywords.push("arm64")
|
||||
break
|
||||
default:
|
||||
info(`Using arch ${arch} for LLVM`)
|
||||
keywords.push(arch)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
case "freebsd": {
|
||||
keywords.push("freebsd")
|
||||
|
||||
switch (arch) {
|
||||
case "x86_64":
|
||||
case "x64":
|
||||
case "amd64":
|
||||
case "64":
|
||||
keywords.push("amd64")
|
||||
break
|
||||
case "x86":
|
||||
case "i386":
|
||||
case "ia32":
|
||||
case "32":
|
||||
keywords.push("i386")
|
||||
break
|
||||
default:
|
||||
info(`Using arch ${arch} for LLVM`)
|
||||
keywords.push(arch)
|
||||
break
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
default:
|
||||
info(`Using ${platform} ${arch} for LLVM`)
|
||||
optionalKeywords.push(platform, arch)
|
||||
break
|
||||
}
|
||||
return { keywords, optionalKeywords }
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { info } from "ci-log"
|
||||
import { readFile } from "fs/promises"
|
||||
|
||||
/**
|
||||
|
@ -18,7 +19,8 @@ export async function loadAssetList(path: string): Promise<Assets> {
|
|||
type MatchAssetOpts = {
|
||||
version: string
|
||||
keywords?: string[]
|
||||
filterTag?: (version: string) => boolean
|
||||
optionalKeywords?: string[]
|
||||
filterMapTag?: (tag: string) => string | undefined
|
||||
filterName?: (asset: string) => boolean
|
||||
}
|
||||
|
||||
|
@ -28,58 +30,119 @@ type MatchAssetOpts = {
|
|||
export function matchAsset(
|
||||
assets: Assets,
|
||||
opts: MatchAssetOpts,
|
||||
): { tag: string; name: string } {
|
||||
// get the list of versions
|
||||
let tags = Object.keys(assets)
|
||||
): { tag: string; name: string } | undefined {
|
||||
// match the tag
|
||||
const assetVersion = matchAssetVersion(assets, opts)
|
||||
if (assetVersion === undefined) {
|
||||
return undefined
|
||||
}
|
||||
const { tag, assetNames } = assetVersion
|
||||
|
||||
// filter the versions
|
||||
if (opts.filterTag !== undefined) {
|
||||
tags = tags.filter(opts.filterTag)
|
||||
// if no keywords are given, return the first asset
|
||||
if (!opts.keywords?.length && !opts.optionalKeywords?.length) {
|
||||
return { tag, name: assetNames[0] }
|
||||
}
|
||||
|
||||
if (tags.length === 0) {
|
||||
throw new Error(`no tag found for version ${opts.version}`)
|
||||
// check if the asset contains all the keywords
|
||||
let candidates: string[] = []
|
||||
if (opts.keywords?.length) {
|
||||
for (const name of assetNames) {
|
||||
if (opts.keywords!.every((keyword) => name.includes(keyword))) {
|
||||
candidates.push(name)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
candidates = assetNames
|
||||
}
|
||||
|
||||
if (candidates.length === 0) {
|
||||
info(`no asset found for version ${opts.version} and keywords ${opts.keywords}`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
// prefer the candidates that contain more optional keywords
|
||||
if (opts.optionalKeywords?.length) {
|
||||
// rate the candidates based on the number of optional keywords they contain
|
||||
const candidateScores = candidates.map((name) => {
|
||||
let score = 0
|
||||
for (const keyword of opts.optionalKeywords!) {
|
||||
if (name.includes(keyword)) {
|
||||
score++
|
||||
}
|
||||
}
|
||||
return score
|
||||
})
|
||||
|
||||
// find the candidate with the highest score
|
||||
const maxScore = Math.max(...candidateScores)
|
||||
const maxIndex = candidateScores.indexOf(maxScore)
|
||||
return { tag, name: candidates[maxIndex] }
|
||||
}
|
||||
|
||||
// return the first candidate if no optional keywords are given
|
||||
return { tag, name: candidates[0] }
|
||||
}
|
||||
|
||||
function matchAssetVersion(assets: Assets, opts: MatchAssetOpts) {
|
||||
// get the list of versions
|
||||
const origTags = Object.keys(assets)
|
||||
|
||||
// filter/map the tags
|
||||
const versionMap: Map<string, string> = new Map()
|
||||
if (opts.filterMapTag === undefined) {
|
||||
for (const origTag of origTags) {
|
||||
versionMap.set(origTag, origTag)
|
||||
}
|
||||
} else {
|
||||
for (const origTag of origTags) {
|
||||
const mappedTag = opts.filterMapTag(origTag)
|
||||
if (mappedTag !== undefined) {
|
||||
versionMap.set(mappedTag, origTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (versionMap.size === 0) {
|
||||
info(`no tag found for version ${opts.version}`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
// find the first tag that starts with the version
|
||||
// loop over the versions starting with the latest
|
||||
let tag: string | undefined
|
||||
for (const mingwVersion of tags) {
|
||||
if (mingwVersion.startsWith(opts.version)) {
|
||||
tag = mingwVersion
|
||||
let foundVersion: string | undefined
|
||||
let foundOrigTag: string | undefined
|
||||
for (const [version, origTag] of versionMap.entries()) {
|
||||
if (
|
||||
version === opts.version
|
||||
|| version.startsWith(opts.version)
|
||||
) {
|
||||
foundVersion = version
|
||||
foundOrigTag = origTag
|
||||
break
|
||||
}
|
||||
}
|
||||
if (tag === undefined) {
|
||||
throw new Error(`version ${opts.version} is not supported`)
|
||||
|
||||
if (foundVersion === undefined || foundOrigTag === undefined) {
|
||||
info(`version ${opts.version} is not supported`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
// get the list of assets
|
||||
let matchedNames = assets[tag]
|
||||
let assetNames = assets[foundOrigTag]
|
||||
if (assetNames === undefined) {
|
||||
info(`no asset found for version ${opts.version}`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
// filter the assets
|
||||
if (opts.filterName !== undefined) {
|
||||
matchedNames = matchedNames.filter(opts.filterName)
|
||||
assetNames = assetNames.filter(opts.filterName)
|
||||
}
|
||||
|
||||
if (matchedNames.length === 0) {
|
||||
throw new Error(`no asset found for version ${opts.version}`)
|
||||
if (assetNames.length === 0) {
|
||||
info(`no asset found for version ${opts.version}`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (opts.keywords?.length === 0) {
|
||||
return { tag, name: matchedNames[0] }
|
||||
}
|
||||
|
||||
// find the first asset that matches the keywords
|
||||
for (const name of matchedNames) {
|
||||
if (opts.keywords!.every((keyword) => name.includes(keyword))) {
|
||||
return { tag, name }
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Could not find a matching asset for version ${opts.version} and keywords ${JSON.stringify(opts.keywords)} among ${
|
||||
JSON.stringify(matchedNames)
|
||||
}`,
|
||||
)
|
||||
return { tag: foundOrigTag, assetNames }
|
||||
}
|
||||
|
|
|
@ -42,12 +42,17 @@ function detectUsingOsVersion() {
|
|||
return null
|
||||
}
|
||||
|
||||
// #46~22.04.1-Ubuntu SMP ...
|
||||
// #40~22.04.3-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 30 17:30:19 UTC 2
|
||||
const osVersion: string = os.version()
|
||||
const versionSplitted = osVersion.split(".")
|
||||
const majorVersion = Number.parseInt(versionSplitted[0].replace("#", ""), 10)
|
||||
const minorVersion = Number.parseInt(versionSplitted[1].replace("~", ""), 10)
|
||||
const patchVersion = Number.parseInt(versionSplitted[2].split("-")[0], 10)
|
||||
// parse the version
|
||||
const versionMatch = osVersion.match(/(\d+)\.(\d+)\.(\d+)/)
|
||||
if (versionMatch === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const majorVersion = Number.parseInt(versionMatch[1], 10)
|
||||
const minorVersion = Number.parseInt(versionMatch[2], 10)
|
||||
const patchVersion = Number.parseInt(versionMatch[3], 10)
|
||||
|
||||
return [majorVersion, minorVersion, patchVersion]
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { isArch } from "../utils/env/isArch.js"
|
|||
// passing "" to a tool installed by a package manager (apt, brew, choco) will result in the default version of that package manager.
|
||||
// the directly downloaded tools require a given version ("" doesn't work).
|
||||
|
||||
function getLLVMDefault() {
|
||||
function getNonUbuntuLLVMDefault() {
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
return "17.0.6"
|
||||
|
@ -19,9 +19,9 @@ function getLLVMDefault() {
|
|||
}
|
||||
|
||||
export const DefaultVersions: Record<string, string | undefined> = {
|
||||
llvm: getLLVMDefault(), // https://github.com/llvm/llvm-project/releases
|
||||
clangtidy: getLLVMDefault(),
|
||||
clangformat: getLLVMDefault(),
|
||||
llvm: getNonUbuntuLLVMDefault(), // https://github.com/llvm/llvm-project/releases
|
||||
clangtidy: getNonUbuntuLLVMDefault(),
|
||||
clangformat: getNonUbuntuLLVMDefault(),
|
||||
ninja: "1.12.1", // https://github.com/ninja-build/ninja/releases
|
||||
cmake: "3.30.2", // https://github.com/Kitware/CMake/releases
|
||||
gcovr: "5.2", // "6.0", // https://pypi.org/project/gcovr/
|
||||
|
@ -45,7 +45,7 @@ export const MinVersions: Record<string, string | undefined> = {
|
|||
/// If an ubuntu versions is not in this map:
|
||||
// - the newer ubuntu versions use the first entry (e.g. v20),
|
||||
// - the older ones use ""
|
||||
export const DefaultLinuxVersion: Record<string, Record<number, string> | undefined> = {
|
||||
export const DefaultUbuntuVersion: Record<string, Record<number, string> | undefined> = {
|
||||
// https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=mingw-w64
|
||||
mingw: {
|
||||
24: "8.0.0-1",
|
||||
|
@ -54,28 +54,28 @@ export const DefaultLinuxVersion: Record<string, Record<number, string> | undefi
|
|||
},
|
||||
// the suffixes relate to the suffix in the llvm releases
|
||||
llvm: {
|
||||
24: "17.0.6-ubuntu-22.04",
|
||||
22: "17.0.6-ubuntu-22.04",
|
||||
20: "17.0.6-ubuntu-22.04",
|
||||
18: "15.0.6-ubuntu-18.04",
|
||||
16: "15.0.6-ubuntu-18.04",
|
||||
14: "13.0.0-ubuntu-16.04",
|
||||
24: "17.0.6",
|
||||
22: "17.0.6",
|
||||
20: "17.0.6",
|
||||
18: "15.0.6",
|
||||
16: "15.0.6",
|
||||
14: "13.0.0",
|
||||
},
|
||||
clangtidy: {
|
||||
24: "17.0.6-ubuntu-22.04",
|
||||
22: "17.0.6-ubuntu-22.04",
|
||||
20: "17.0.6-ubuntu-22.04",
|
||||
18: "15.0.6-ubuntu-18.04",
|
||||
16: "15.0.6-ubuntu-18.04",
|
||||
14: "13.0.0-ubuntu-16.04",
|
||||
24: "17.0.6",
|
||||
22: "17.0.6",
|
||||
20: "17.0.6",
|
||||
18: "15.0.6",
|
||||
16: "15.0.6",
|
||||
14: "13.0.0",
|
||||
},
|
||||
clangformat: {
|
||||
24: "17.0.6-ubuntu-22.04",
|
||||
22: "17.0.6-ubuntu-22.04",
|
||||
20: "17.0.6-ubuntu-22.04",
|
||||
18: "15.0.6-ubuntu-18.04",
|
||||
16: "15.0.6-ubuntu-18.04",
|
||||
14: "13.0.0-ubuntu-16.04",
|
||||
24: "17.0.6",
|
||||
22: "17.0.6",
|
||||
20: "17.0.6",
|
||||
18: "15.0.6",
|
||||
16: "15.0.6",
|
||||
14: "13.0.0",
|
||||
},
|
||||
gcovr: {
|
||||
24: "6.0",
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { Opts } from "../cli-options.js"
|
||||
import type { Inputs } from "../tool.js"
|
||||
import { DefaultLinuxVersion, DefaultVersions } from "./default_versions.js"
|
||||
import { DefaultUbuntuVersion, DefaultVersions } from "./default_versions.js"
|
||||
|
||||
/** Get the default version if passed true or undefined, otherwise return the version itself */
|
||||
export function getVersion(name: string, version: string | undefined, osVersion: number[] | null = null) {
|
||||
if (isVersionDefault(version) && process.platform === "linux" && osVersion !== null && name in DefaultLinuxVersion) {
|
||||
return getDefaultLinuxVersion(osVersion, DefaultLinuxVersion[name]!)
|
||||
if (isVersionDefault(version) && process.platform === "linux" && osVersion !== null && name in DefaultUbuntuVersion) {
|
||||
return getDefaultLinuxVersion(osVersion, DefaultUbuntuVersion[name]!)
|
||||
} else if (isVersionDefault(version) && name in DefaultVersions) {
|
||||
return DefaultVersions[name] ?? ""
|
||||
} else if (version === "true") {
|
||||
|
|
Loading…
Reference in New Issue