setup-cpp
Version:
Install all the tools required for building and testing C++/C projects.
191 lines (169 loc) • 5.71 kB
text/typescript
import path, { join } from "path"
import { fileURLToPath } from "url"
import { info } from "ci-log"
import { addExeExt } from "patha"
import { loadAssetList, matchAsset } from "../utils/asset/load-assets.js"
import { arm64, armv7, powerpc64le, sparc64, sparcv9, x86, x86_64 } from "../utils/env/arch.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
import { extractTarByExe, getArchiveType, getExtractFunction } from "../utils/setup/extract.js"
import type { PackageInfo } from "../utils/setup/setupBin.js"
const dirname = typeof __dirname === "string" ? __dirname : path.dirname(fileURLToPath(import.meta.url))
export async function getLLVMPackageInfo(
version: string,
platform: NodeJS.Platform,
arch: string,
): Promise<PackageInfo> {
const url = await getLLVMAssetURL(platform, arch, version)
info(`Downloading LLVM from ${url}`)
return {
url,
extractedFolderName: "",
binRelativeDir: "bin",
binFileName: addExeExt("clang"),
extractFunction: platform === "win32"
? getExtractFunction(getArchiveType(url))
: (file: string, dest: string) => {
return extractTarByExe(file, dest, 1)
},
}
}
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-/, "")
},
},
)
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://releases.llvm.org/${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 | string[])[] = []
const optionalKeywords: (string | string[])[] = []
switch (platform) {
case "win32": {
// prefer exe over tar.xz for windows
optionalKeywords.push(".exe", ".exe")
const osKeywordsChoice: string[] = []
if (x86_64.includes(arch)) {
osKeywordsChoice.push("win64")
optionalKeywords.push(["x86_64", "X64"])
// TODO fallback to win32 if win64 is not available (e.g. for LLVM 3.6.2 and older)
} else if (x86.includes(arch)) {
osKeywordsChoice.push("win32")
} else if (arm64.includes(arch)) {
osKeywordsChoice.push("woa64")
} else {
info(`Using arch ${arch} for LLVM`)
osKeywordsChoice.push(arch)
}
osKeywordsChoice.push("windows", "Windows")
keywords.push(osKeywordsChoice)
break
}
case "linux": {
const osKeywordsChoice = ["linux", "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")
}
if (x86_64.includes(arch)) {
keywords.push(["x86_64", "X64"])
} else if (x86.includes(arch)) {
keywords.push("x86")
} else if (arm64.includes(arch)) {
keywords.push("aarch64")
} else if (armv7.includes(arch)) {
keywords.push("armv7a")
} else if (powerpc64le.includes(arch)) {
keywords.push("powerpc64le")
} else if (sparc64.includes(arch)) {
keywords.push("sparc64")
} else {
info(`Using arch ${arch} for LLVM`)
keywords.push(arch)
}
keywords.push(osKeywordsChoice)
break
}
case "darwin": {
keywords.push(["apple", "macos", "macOS"])
if (x86_64.includes(arch)) {
optionalKeywords.push(["x86_64", "X64"])
} else if (arm64.includes(arch)) {
// allow falling back to x86_64 if arm64 is not available
optionalKeywords.push(["arm64", "ARM64"])
} else {
info(`Using arch ${arch} for LLVM`)
keywords.push(arch)
}
break
}
case "freebsd": {
keywords.push("freebsd")
if (x86_64.includes(arch)) {
keywords.push("amd64")
} else if (x86.includes(arch)) {
keywords.push("i386")
} else {
info(`Using arch ${arch} for LLVM`)
keywords.push(arch)
}
break
}
case "solaris": {
keywords.push("solaris")
if (x86_64.includes(arch)) {
keywords.push("amd64")
} else if (sparcv9.includes(arch)) {
keywords.push("sparcv9")
} else {
info(`Using arch ${arch} for LLVM`)
keywords.push(arch)
}
break
}
default:
info(`Using ${platform} ${arch} for LLVM`)
keywords.push(platform, arch)
break
}
return { keywords, optionalKeywords }
}