fix: sync LLVM compiler version and clang tools version

This commit is contained in:
Amin Yahyaabadi 2024-09-19 14:53:36 -07:00
parent 5d12f41e90
commit 3a86553eb1
No known key found for this signature in database
GPG Key ID: F52AF77F636088F0
8 changed files with 101 additions and 33 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

View File

@ -25,15 +25,39 @@ describe("getCompilerInfo", () => {
})
})
describe("getCompilerInfo", () => {
it("getCompilerInfo with semver", () => {
const { compiler, version } = getCompilerInfo("llvm-12.0.0")
expect(compiler).toBe("llvm")
expect(version).toBe("12.0.0")
})
it("getCompilerInfo with major version", () => {
const { compiler, version } = getCompilerInfo("llvm-12")
expect(compiler).toBe("llvm")
expect(version).toBe("12")
})
it("getCompilerInfo without version", () => {
const { compiler, version } = getCompilerInfo("llvm")
expect(compiler).toBe("llvm")
expect(version).toBeUndefined()
})
})
describe("syncVersion", () => {
it("Syncs llvm tools versions", () => {
expect(syncVersions(parseArgs(["--llvm", "14.0.0", "--clangtidy", "true"]), llvmTools as Inputs[])).toBe(true)
expect(syncVersions(parseArgs(["--llvm", "13.0.0", "--clangtidy", "true"]), llvmTools as Inputs[])).toBe(true)
expect(syncVersions(parseArgs(["--compiler", "llvm-13.0.0", "--clangtidy", "true"]), llvmTools as Inputs[])).toBe(
true,
)
expect(syncVersions(parseArgs(["--llvm", "13.0.0", "--clangtidy", "12.0.0"]), llvmTools as Inputs[])).toBe(false)
const opts1 = parseArgs(["--llvm", "14.0.0", "--clangtidy", "true"])
expect(syncVersions(opts1, llvmTools as Inputs[])).toBe(true)
expect(opts1.llvm).toBe(opts1.clangtidy)
expect(opts1.llvm).toBe("14.0.0")
expect(opts1.clangtidy).toBe("14.0.0")
expect(opts1.clangformat).toBe(undefined)
const opts2 = parseArgs(["--clangtidy", "15.0.0", "--clangformat", "true"])
@ -45,8 +69,14 @@ describe("syncVersion", () => {
const opts3 = parseArgs(["--llvm", "true", "--clangformat", "true"])
expect(syncVersions(opts3, llvmTools as Inputs[])).toBe(true)
expect(opts3.llvm).toBe("true")
expect(opts3.clangtidy).toBe(undefined)
expect(opts3.clangformat).toBe("true")
expect(opts3.clangtidy).toBe(undefined)
const opts4 = parseArgs(["--compiler", "llvm-13.0.0", "--clangtidy", "true"])
expect(syncVersions(opts4, [...llvmTools, "compiler"] as Inputs[], getCompilerInfo("llvm-13.0.0"))).toBe(true)
expect(opts4.compiler).toBe("llvm-13.0.0")
expect(opts4.clangtidy).toBe("13.0.0")
expect(opts4.clangformat).toBe(undefined)
})
})

View File

@ -12,6 +12,11 @@ import { appleClangSetups, gccSetups, llvmSetups, mingwSetups, msvcSetups } from
import type { InstallationInfo } from "./utils/setup/setupBin.js"
import { getVersion } from "./versions/versions.js"
export type CompilerInfo = {
compiler: string
version: string | undefined
}
/**
* Detecting the compiler version. Divide the given string by `-` and use the second element as the version
*
@ -20,7 +25,7 @@ import { getVersion } from "./versions/versions.js"
*
* @nothrow It doesn't throw any error, but it logs the error if it fails to parse the compiler info
*/
export function getCompilerInfo(compilerAndVersion: string) {
export function getCompilerInfo(compilerAndVersion: string): CompilerInfo {
try {
const compilerAndMaybeVersion = compilerAndVersion.split("-")
const compiler = compilerAndMaybeVersion[0]
@ -40,15 +45,14 @@ export function getCompilerInfo(compilerAndVersion: string) {
/** Installing the specified compiler */
export async function installCompiler(
compilerAndVersion: string,
compiler: string,
version: string | undefined,
osVersion: number[] | null,
setupCppDir: string,
arch: string,
successMessages: string[],
errorMessages: string[],
) {
const { compiler, version } = getCompilerInfo(compilerAndVersion)
let installationInfo: InstallationInfo | undefined | void | null // null means the compiler is not supported
try {
// install the compiler. We allow some aliases for the compiler name
@ -82,7 +86,7 @@ export async function installCompiler(
}
} catch (err) {
error(err as string | Error)
errorMessages.push(`Failed to install the ${compilerAndVersion}`)
errorMessages.push(`Failed to install the ${compiler} ${version}`)
}
if (installationInfo !== null) {

View File

@ -11,7 +11,7 @@ import timeDeltaLocale from "time-delta/locales/en.js"
import { untildifyUser } from "untildify-user"
import { checkUpdates } from "./check-updates.js"
import { parseArgs, printHelp, rcOptions } from "./cli-options.js"
import { installCompiler } from "./compilers.js"
import { getCompilerInfo, installCompiler } from "./compilers.js"
import { installTool } from "./installTool.js"
import { type Inputs, llvmTools, tools } from "./tool.js"
import { isArch } from "./utils/env/isArch.js"
@ -55,8 +55,10 @@ async function main(args: string[]): Promise<number> {
const osVersion = await ubuntuVersion()
const compilerInfo = opts.compiler !== undefined ? getCompilerInfo(opts.compiler) : undefined
// sync the version for the llvm tools
if (!syncVersions(opts, llvmTools as Inputs[])) {
if (!syncVersions(opts, [...llvmTools, "compiler"] as Inputs[], compilerInfo)) {
error("The same version must be used for llvm, clang-format and clang-tidy")
return 1
}
@ -71,11 +73,9 @@ async function main(args: string[]): Promise<number> {
let failedFast = false
for (const tool of tools) {
// fail fast inside CI when any tool fails
if (isCI) {
if (errorMessages.length !== 0) {
failedFast = true
break
}
if (isCI && errorMessages.length !== 0) {
failedFast = true
break
}
// get the version or "true" or undefined for this tool from the options
@ -101,15 +101,20 @@ async function main(args: string[]): Promise<number> {
}
}
if (!failedFast) {
// installing the specified compiler
const maybeCompiler = opts.compiler
if (maybeCompiler !== undefined) {
const time1Compiler = Date.now()
await installCompiler(maybeCompiler, osVersion, setupCppDir, arch, successMessages, errorMessages)
const time2Compiler = Date.now()
info(`took ${timeFormatter.format(time1Compiler, time2Compiler) || "0 seconds"}`)
}
if (!failedFast && compilerInfo !== undefined) {
// install the specified compiler
const time1Compiler = Date.now()
await installCompiler(
compilerInfo.compiler,
compilerInfo.version,
osVersion,
setupCppDir,
arch,
successMessages,
errorMessages,
)
const time2Compiler = Date.now()
info(`took ${timeFormatter.format(time1Compiler, time2Compiler) || "0 seconds"}`)
}
await finalizeRC(rcOptions)

View File

@ -1,4 +1,5 @@
import type { Opts } from "../cli-options.js"
import type { CompilerInfo } from "../compilers.js"
import type { Inputs } from "../tool.js"
import { DefaultUbuntuVersion, DefaultVersions } from "./default_versions.js"
@ -34,21 +35,49 @@ function getDefaultLinuxVersion(osVersion: number[], toolLinuxVersions: Record<n
/**
* Sync the versions for the given inputs
*
* It modifies the opts object to have the same version for all the tools
* If the return is false, it means that versions don't match the target version
* @param opts - The options object (modified in place)
* @param tools - The tools to sync the versions for (it can include `compiler`)
* @param compilerInfo - The compiler info to sync the versions for (if any)
*/
export function syncVersions(opts: Opts, tools: Inputs[]): boolean {
export function syncVersions(opts: Opts, tools: Inputs[], compilerInfo: CompilerInfo | undefined = undefined): boolean {
// filter out the tools that are in use in the options
const toolsInUse = tools.filter((tool) => opts[tool] !== undefined)
const toolsNonDefaultVersion = toolsInUse.filter((tool) => !isVersionDefault(opts[tool]))
const targetVersion = toolsNonDefaultVersion.length >= 1 ? opts[toolsNonDefaultVersion[0]] : "true"
// filter out the tools that are not default
const toolsNonDefaultVersion = toolsInUse.filter((tool) => {
const version = (tool === "compiler" && compilerInfo !== undefined)
? compilerInfo.version
: opts[tool]
return !isVersionDefault(version)
})
if (toolsNonDefaultVersion.some((tool) => opts[tool] !== targetVersion)) {
// error if any explicit versions don't match the target version
// find the target version to sync to
const targetVersion: string = (toolsNonDefaultVersion.length !== 0)
? (toolsNonDefaultVersion[0] === "compiler" && compilerInfo !== undefined)
? compilerInfo.version ?? "true"
: opts[toolsNonDefaultVersion[0]] ?? "true"
: "true"
// error if any explicit versions don't match the target version
if (
toolsNonDefaultVersion.some((tool) => {
if (tool === "compiler" && compilerInfo !== undefined) {
return opts.compiler !== `${compilerInfo.compiler}-${targetVersion}`
}
return opts[tool] !== targetVersion
})
) {
return false
}
// update the version of all the tools to the target version
for (const tool of toolsInUse) {
opts[tool] = targetVersion
opts[tool] = (tool === "compiler" && compilerInfo !== undefined)
? `${compilerInfo.compiler}-${targetVersion}`
: targetVersion
}
return true