feat: find LLVM assets based on platform/arch/version heuristics

This commit is contained in:
Amin Yahyaabadi 2024-09-07 17:30:18 -07:00
parent 22bfbec1e0
commit e003dfdeac
No known key found for this signature in database
GPG Key ID: F52AF77F636088F0
13 changed files with 362 additions and 435 deletions

View File

@ -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

View File

@ -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])
}
})
})

View File

@ -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++"),

View File

@ -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)),
)
})

View File

@ -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 }
}

View File

@ -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 }
}

View File

@ -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]
}

View File

@ -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",

View File

@ -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") {