Compare commits

...

5 Commits

Author SHA1 Message Date
Amin Yahyaabadi d7f5466d92
Merge pull request #293 from aminya/aliases [skip ci] 2024-09-17 14:45:49 -07:00
Amin Yahyaabadi 8a39523391
feat: support more compiler/tool aliases (e.g. clang, clang-tidy) 2024-09-17 14:32:10 -07:00
Amin Yahyaabadi fc60b25730
chore: v0.41.1 [skip test] 2024-09-17 13:03:34 -07:00
Amin Yahyaabadi 5d06e63ba4
Merge pull request #290 from aminya/llvm-flags [skip ci] 2024-09-17 13:01:31 -07:00
Amin Yahyaabadi 22ad634883
fix(llvm): set LLVM_CPPFLAGS/LDFLAGS instead of CPPFLAGS/LDFLAGS 2024-09-17 12:06:23 -07:00
39 changed files with 869 additions and 793 deletions

View File

@ -241,12 +241,12 @@ jobs:
pnpm:
- 9.10.0
container:
- { file: "ubuntu-llvm.dockerfile", image: "setup-cpp-ubuntu-llvm", tag: "22.04-0.41.0" }
- { file: "fedora-llvm.dockerfile", image: "setup-cpp-fedora-llvm", tag: "40-0.41.0" }
- { file: "arch-llvm.dockerfile", image: "setup-cpp-arch-llvm", tag: "base-0.41.0" }
- { file: "ubuntu-mingw.dockerfile", image: "setup-cpp-ubuntu-mingw", tag: "22.04-0.41.0" }
# - { file: "fedora-mingw.dockerfile", image: "setup-cpp-fedora-mingw", tag: "40-0.41.0" }
# - { file: "arch-mingw.dockerfile", image: "setup-cpp-arch-mingw", tag: "base-0.41.0" }
- { file: "ubuntu-llvm.dockerfile", image: "setup-cpp-ubuntu-llvm", tag: "22.04-0.41.1" }
- { file: "fedora-llvm.dockerfile", image: "setup-cpp-fedora-llvm", tag: "40-0.41.1" }
- { file: "arch-llvm.dockerfile", image: "setup-cpp-arch-llvm", tag: "base-0.41.1" }
- { file: "ubuntu-mingw.dockerfile", image: "setup-cpp-ubuntu-mingw", tag: "22.04-0.41.1" }
# - { file: "fedora-mingw.dockerfile", image: "setup-cpp-fedora-mingw", tag: "40-0.41.1" }
# - { file: "arch-mingw.dockerfile", image: "setup-cpp-arch-mingw", tag: "base-0.41.1" }
steps:
- uses: actions/checkout@v4
with:

View File

@ -3,6 +3,7 @@
"orta.vscode-jest",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"biomejs.biome"
"biomejs.biome",
"p42ai.refactor"
]
}

View File

@ -15,8 +15,8 @@ Setting up a **cross-platform** environment for building and testing C++/C proje
`setup-cpp` is **modular** and you can choose to install any of these tools:
| category | tools |
| --------------------- | ------------------------------------------------------------ |
| compiler and analyzer | llvm, gcc, msvc, vcvarsall, cppcheck, clangtidy, clangformat |
| --------------------- | --------------------------------------------------------------------------- |
| compiler and analyzer | llvm, gcc, msvc, apple-clang, vcvarsall, cppcheck, clang-tidy, clang-format |
| build system | cmake, ninja, meson, make, task, bazel |
| package manager | vcpkg, conan, choco, brew, nala |
| cache | ccache, sccache |
@ -56,22 +56,22 @@ NOTE: setup-cpp requires Nodejs 12 or higher. If Nodejs shipped with your distri
#### With executable
Download the executable for your platform from [here](https://github.com/aminya/setup-cpp/releases/tag/v0.41.0), and run it with the available options. You can also automate downloading using `curl`, or other similar tools.
Download the executable for your platform from [here](https://github.com/aminya/setup-cpp/releases/tag/v0.41.1), and run it with the available options. You can also automate downloading using `curl`, or other similar tools.
```shell
# windows x64
curl -o ./setup-cpp.exe -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.0/setup-cpp-x64-windows.exe"
curl -o ./setup-cpp.exe -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.1/setup-cpp-x64-windows.exe"
# linux x64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.0/setup-cpp-x64-linux"
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.1/setup-cpp-x64-linux"
chmod +x ./setup-cpp
# macos arm64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.0/setup-cpp-arm64-macos"
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.1/setup-cpp-arm64-macos"
chmod +x ./setup-cpp
# macos x64
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.0/setup-cpp-x64-macos"
curl -o ./setup-cpp -LJ "https://github.com/aminya/setup-cpp/releases/download/v0.41.1/setup-cpp-x64-macos"
chmod +x ./setup-cpp
```
@ -149,7 +149,7 @@ jobs:
ninja: true
vcpkg: true
cppcheck: true
clangtidy: true # instead of `true`, which chooses the default version, you can pass a specific version.
clang-tidy: true # instead of `true`, which chooses the default version, you can pass a specific version.
# ...
```
@ -160,19 +160,19 @@ To provide fast development environments, `setup-cpp` provides several prebuilt
You can use these images as a base image for your project.
```dockerfile
FROM aminya/setup-cpp-ubuntu-llvm:22.04-0.41.0 AS builder
FROM aminya/setup-cpp-ubuntu-llvm:22.04-0.41.1 AS builder
```
```dockerfile
FROM aminya/setup-cpp-ubuntu-mingw:22.04-0.41.0 AS builder
FROM aminya/setup-cpp-ubuntu-mingw:22.04-0.41.1 AS builder
```
```dockerfile
FROM aminya/setup-cpp-fedora-llvm:40-0.41.0 AS builder
FROM aminya/setup-cpp-fedora-llvm:40-0.41.1 AS builder
```
```dockerfile
FROM aminya/setup-cpp-arch-llvm:base-0.41.0 AS builder
FROM aminya/setup-cpp-arch-llvm:base-0.41.1 AS builder
```
The names are in the format `aminya/setup-cpp-<platform>-<compiler>:<platform_version>-<setup_cpp_version>`.
@ -191,7 +191,7 @@ RUN apt-get update -qq && \
# install nodejs
apt-get install -y --no-install-recommends nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--nala true \
@ -300,7 +300,7 @@ stages:
apt-get install -y --no-install-recommends nodejs npm
# install setup-cpp
npm install -g setup-cpp@v0.41.0
npm install -g setup-cpp@v0.41.1
# install the compiler and tools
./setup-cpp-x64-linux --compiler $compiler --cmake true --ninja true --ccache true --vcpkg true

View File

@ -19,21 +19,51 @@ inputs:
llvm:
description: "Wether to install llvm (true/false) or the specific version to install"
required: false
clang:
description: "Wether to install clang (true/false) or the specific version to install"
required: false
gcc:
description: "Wether to install gcc (true/false) or the specific version to install"
required: false
msvc:
description: "Wether to install msvc (true/false) or the specific version to install"
required: false
cl:
description: "Wether to install cl (true/false) or the specific version to install"
required: false
msbuild:
description: "Wether to install msbuild (true/false) or the specific version to install"
required: false
visualstudio:
description: "Wether to install visualstudio (true/false) or the specific version to install"
required: false
apple-clang:
description: "Wether to install apple-clang (true/false) or the specific version to install"
required: false
apple-llvm:
description: "Wether to install apple-llvm (true/false) or the specific version to install"
required: false
appleclang:
description: "Wether to install apple-clang (true/false) or the specific version to install"
required: false
applellvm:
description: "Wether to install apple-llvm (true/false) or the specific version to install"
required: false
vcvarsall:
description: "If should run vcvarsall?"
required: false
cppcheck:
description: "Wether to install cppcheck (true/false) or the specific version to install."
required: false
clang-tidy:
description: "Wether to install clang-tidy (true/false) or the specific version to install."
required: false
clangtidy:
description: "The clangWether to install tidy (true/false) or the specific version to install."
required: false
clang-format:
description: "The clangWether to install format (true/false) or the specific version to install."
required: false
clangformat:
description: "The clangWether to install format (true/false) or the specific version to install."
required: false
@ -94,6 +124,9 @@ inputs:
powershell:
description: "Wether to install powershell (true/false) or the specific version to install."
required: false
pwsh:
description: "Wether to install pwsh (true/false) or the specific version to install."
required: false
python:
description: "Wether to install python (true/false) or the specific version to install."
required: false

View File

@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"$schema": "https://biomejs.dev/schemas/1.9.1/schema.json",
"files": {
"ignore": [
"**/node_modules/**",
@ -33,8 +33,18 @@
"suspicious": {
"noConfusingVoidType": "off"
},
"nursery": {
"useImportExtensions": "warn"
"correctness": {
"useImportExtensions": {
"level": "error",
"options": {
"suggestedExtensions": {
"ts": {
"component": "js",
"module": "js"
}
}
}
}
}
}
},

View File

@ -6,7 +6,7 @@ RUN pacman -Syuu --noconfirm && \
# install nodejs
pacman -S --noconfirm --needed nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--compiler llvm \

View File

@ -6,7 +6,7 @@ RUN pacman -Syuu --noconfirm && \
# install nodejs
pacman -S --noconfirm --needed nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--compiler mingw \

View File

@ -4,7 +4,7 @@ FROM fedora:40 AS setup-cpp-fedora
# install nodejs
RUN dnf -y install nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--compiler llvm \

View File

@ -4,7 +4,7 @@ FROM fedora:40 AS setup-cpp-fedora-mingw
# install nodejs
RUN dnf -y install nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--compiler mingw \

View File

@ -11,7 +11,7 @@ RUN apt-get update -qq && \
apt-get update -qq && \
apt-get install -y --no-install-recommends nodejs && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--nala true \

View File

@ -5,7 +5,7 @@ RUN apt-get update -qq && \
# install nodejs
apt-get install -y --no-install-recommends nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--nala true \

View File

@ -5,7 +5,7 @@ RUN apt-get update -qq && \
# install nodejs
apt-get install -y --no-install-recommends nodejs npm && \
# install setup-cpp
npm install -g setup-cpp@v0.41.0 && \
npm install -g setup-cpp@v0.41.1 && \
# install the compiler and tools
setup-cpp \
--nala true \

File diff suppressed because one or more lines are too long

2
dist/legacy/assets/hdi-HMjVj8JE.js vendored Normal file

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

File diff suppressed because one or more lines are too long

2
dist/modern/assets/hdi-DCb6yS8z.mjs vendored Normal file

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,4 +1,4 @@
{
"name": "setup-cpp",
"version": "0.41.0"
"version": "0.41.1"
}

View File

@ -1,6 +1,6 @@
{
"name": "setup-cpp",
"version": "0.41.0",
"version": "0.41.1",
"description": "Install all the tools required for building and testing C++/C projects.",
"repository": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
@ -61,7 +61,7 @@
"@actions/tool-cache": "^2.0.1",
"@aminya/minijson": "1.0.3",
"@babel/core": "^7.25.2",
"@biomejs/biome": "^1.8.3",
"@biomejs/biome": "^1.9.1",
"@iarna/toml": "^2.2.5",
"@liuli-util/vite-plugin-node": "^0.9.0",
"@octokit/core": "^6.1.2",
@ -77,7 +77,7 @@
"@types/escape-quotes": "~1.0.0",
"@types/eslint": "^8.56.12",
"@types/iarna__toml": "~2.0.5",
"@types/jest": "^29.5.12",
"@types/jest": "^29.5.13",
"@types/memoizee": "^0.4.11",
"@types/node": "^12.20.55",
"@types/semver": "^7.5.8",
@ -89,14 +89,14 @@
"ci-log": "workspace:*",
"cross-env": "7.0.3",
"cross-spawn": "^7.0.3",
"cspell": "^8.14.2",
"cspell": "^8.14.3",
"diagnostics_channel": "^1.1.0",
"dprint": "^0.47.2",
"envosman": "workspace:*",
"escape-path-with-spaces": "^1.0.2",
"escape-quotes": "^1.0.2",
"escape-string-regexp": "^5.0.0",
"eslint": "^8.57.0",
"eslint": "^8.57.1",
"eslint-config-atomic": "^1.22.1",
"exec-powershell": "workspace:*",
"execa": "^7.2.0",
@ -110,7 +110,7 @@
"msvc-dev-cmd": "github:aminya/msvc-dev-cmd#c01f519bd995460228ed3dec4df51df92dc290fd",
"node-downloader-helper": "2.1.9",
"npm-check-updates": "^17.1.1",
"npm-run-all2": "^6.2.2",
"npm-run-all2": "^6.2.3",
"numerous": "1.0.3",
"p-timeout": "^6.1.2",
"path-exists": "^5.0.0",
@ -119,7 +119,7 @@
"prettier-config-atomic": "^4.0.0",
"readme-md-generator": "^1.0.0",
"retry-as-promised": "^7.0.4",
"rollup": "^4.21.2",
"rollup": "^4.21.3",
"safe-stable-stringify": "^2.5.0",
"semver": "7.6.3",
"setup-apt": "workspace:*",
@ -127,17 +127,17 @@
"setup-python": "github:aminya/setup-python#a783db655c6e40317e2c0c96f9d162d9c9f4a751",
"shx": "0.3.4",
"simple-update-notifier": "^2.0.0",
"terser": "^5.31.6",
"terser": "^5.33.0",
"terser-config-atomic": "^1.0.0",
"time-delta": "github:aminya/time-delta#69d91a41cef28e569be9a2991129f5f7d1f0d00e",
"ts-node": "^10.9.2",
"ts-readme": "^1.1.3",
"turbo": "2.1.1",
"typescript": "^5.5.4",
"typescript": "^5.6.2",
"ubuntu-version": "^2.0.0",
"untildify-user": "workspace:*",
"util.types": "^0.0.2",
"vite": "^5.4.3",
"vite": "^5.4.6",
"vite-plugin-babel": "^1.2.0",
"web-streams-polyfill": "^4.0.0",
"which": "^4.0.0"

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import { parseArgs } from "../cli-options.js"
import { getCompilerInfo } from "../compilers.js"
import type { Inputs } from "../tool.js"
import { type Inputs, llvmTools } from "../tool.js"
import { DefaultUbuntuVersion, DefaultVersions } from "../versions/default_versions.js"
import { getVersion, syncVersions } from "../versions/versions.js"
@ -27,24 +27,23 @@ describe("getCompilerInfo", () => {
describe("syncVersion", () => {
it("Syncs llvm tools versions", () => {
const llvmTools = ["llvm", "clangtidy", "clangformat"] as Inputs[]
expect(syncVersions(parseArgs(["--llvm", "14.0.0", "--clangtidy", "true"]), llvmTools)).toBe(true)
expect(syncVersions(parseArgs(["--llvm", "13.0.0", "--clangtidy", "true"]), llvmTools)).toBe(true)
expect(syncVersions(parseArgs(["--llvm", "13.0.0", "--clangtidy", "12.0.0"]), llvmTools)).toBe(false)
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(["--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)).toBe(true)
expect(syncVersions(opts1, llvmTools as Inputs[])).toBe(true)
expect(opts1.llvm).toBe(opts1.clangtidy)
expect(opts1.clangformat).toBe(undefined)
const opts2 = parseArgs(["--clangtidy", "15.0.0", "--clangformat", "true"])
expect(syncVersions(opts2, llvmTools)).toBe(true)
expect(syncVersions(opts2, llvmTools as Inputs[])).toBe(true)
expect(opts2.llvm).toBe(undefined)
expect(opts2.clangtidy).toBe("15.0.0")
expect(opts2.clangformat).toBe("15.0.0")
const opts3 = parseArgs(["--llvm", "true", "--clangformat", "true"])
expect(syncVersions(opts3, llvmTools)).toBe(true)
expect(syncVersions(opts3, llvmTools as Inputs[])).toBe(true)
expect(opts3.llvm).toBe("true")
expect(opts3.clangtidy).toBe(undefined)
expect(opts3.clangformat).toBe("true")

View File

@ -32,7 +32,9 @@ All the available tools:
console.table(
{
"compiler and analyzer": { tools: "--llvm, --gcc, --msvc, --vcvarsall, --cppcheck, --clangtidy, --clangformat" },
"compiler and analyzer": {
tools: "--llvm, --gcc, --msvc, --apple-clang, --vcvarsall, --cppcheck, --clang-tidy, --clang-format",
},
"build system": { tools: "--cmake, --ninja, --meson, --make, --task, --bazel" },
"package manager": { tools: "--vcpkg, --conan, --choco, --brew, --nala" },
cache: { tools: "--ccache, --sccache" },

View File

@ -1,29 +1,41 @@
import { join } from "path"
import { endGroup, notice, startGroup } from "@actions/core"
import { endGroup, startGroup } from "@actions/core"
import { error, info } from "ci-log"
import { addEnv } from "envosman"
import semverValid from "semver/functions/valid"
import { getSuccessMessage, rcOptions } from "./cli-options.js"
import { getSuccessMessage } from "./cli-options.js"
import { setupGcc, setupMingw } from "./gcc/gcc.js"
import { activateGcovGCC, activateGcovLLVM } from "./gcovr/gcovr.js"
import { setupAppleClang } from "./llvm/apple-clang.js"
import { setupLLVM } from "./llvm/llvm.js"
import { setupMSVC } from "./msvc/msvc.js"
import { appleClangSetups, gccSetups, llvmSetups, mingwSetups, msvcSetups } from "./tool.js"
import type { InstallationInfo } from "./utils/setup/setupBin.js"
import { getVersion } from "./versions/versions.js"
/** Detecting the compiler version. Divide the given string by `-` and use the second element as the version */
/**
* Detecting the compiler version. Divide the given string by `-` and use the second element as the version
*
* @param compilerAndVersion - The compiler and version string
* @returns The compiler and version
*
* @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) {
try {
const compilerAndMaybeVersion = compilerAndVersion.split("-")
const compiler = compilerAndMaybeVersion[0]
if (1 in compilerAndMaybeVersion) {
const maybeVersion = compilerAndMaybeVersion[1]
if (semverValid(maybeVersion) !== null) {
return { compiler, version: maybeVersion }
} else {
if (semverValid(maybeVersion) === null) {
info(`Invalid semver version ${maybeVersion} used for the compiler.`)
return { compiler, version: maybeVersion }
}
return { compiler, version: maybeVersion }
}
return { compiler, version: undefined }
} catch (err) {
error(`Failed to parse the compiler info ${compilerAndVersion}: ${err}`)
return { compiler: compilerAndVersion, version: undefined }
}
}
/** Installing the specified compiler */
@ -33,86 +45,49 @@ export async function installCompiler(
setupCppDir: string,
arch: string,
successMessages: string[],
hasLLVM: boolean,
errorMessages: string[],
) {
try {
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
startGroup(`Installing ${compiler} ${version ?? ""}`)
switch (compiler) {
case "llvm":
case "clang":
case "clang++": {
const installationInfo = await setupLLVM(
if (compiler in llvmSetups) {
installationInfo = await setupLLVM(
getVersion("llvm", version, osVersion),
join(setupCppDir, "llvm"),
arch,
)
await activateGcovLLVM()
successMessages.push(getSuccessMessage("llvm", installationInfo))
break
}
case "gcc":
case "mingw":
case "cygwin":
case "msys": {
const gccVersion = compiler === "mingw"
? getVersion("mingw", version, osVersion)
: getVersion("gcc", version, osVersion)
const installationInfo = compiler === "mingw"
? await setupMingw(gccVersion, join(setupCppDir, "gcc"), arch)
: await setupGcc(gccVersion, join(setupCppDir, "gcc"), arch)
if (hasLLVM) {
// remove back the added CPPFLAGS of LLVM that include the LLVM headers
await addEnv("CPPFLAGS", "", rcOptions)
}
} else if (compiler in gccSetups) {
const gccVersion = getVersion("gcc", version, osVersion)
installationInfo = await setupGcc(gccVersion, join(setupCppDir, "gcc"), arch)
await activateGcovGCC(gccVersion)
successMessages.push(getSuccessMessage("gcc", installationInfo))
break
}
case "cl":
case "msvc":
case "msbuild":
case "vs":
case "visualstudio":
case "visualcpp":
case "visualc++": {
const installationInfo = await setupMSVC(
} else if (compiler in mingwSetups) {
const gccVersion = getVersion("mingw", version, osVersion)
installationInfo = await setupMingw(gccVersion, join(setupCppDir, "gcc"), arch)
await activateGcovGCC(gccVersion)
} else if (compiler in msvcSetups) {
installationInfo = await setupMSVC(
getVersion("msvc", version, osVersion),
join(setupCppDir, "msvc"),
arch,
)
if (hasLLVM) {
// remove the CPPFLAGS of LLVM that include the LLVM headers
await addEnv("CPPFLAGS", "", rcOptions)
}
successMessages.push(getSuccessMessage("msvc", installationInfo))
break
}
case "appleclang":
case "applellvm": {
notice("Assuming apple-clang is already installed")
await Promise.all([addEnv("CC", "clang", rcOptions), addEnv("CXX", "clang++", rcOptions)])
successMessages.push(getSuccessMessage("apple-clang", undefined))
break
}
default: {
} else if (compiler in appleClangSetups) {
await setupAppleClang()
} else {
installationInfo = null
errorMessages.push(`Unsupported compiler ${compiler}`)
}
}
} catch (err) {
error(err as string | Error)
errorMessages.push(`Failed to install the ${compilerAndVersion}`)
}
if (installationInfo !== null) {
successMessages.push(getSuccessMessage(compiler, installationInfo))
}
endGroup()
}

View File

@ -4,7 +4,7 @@ import { error } from "ci-log"
import pTimeout from "p-timeout"
import { setupBrew } from "setup-brew"
import { getSuccessMessage, rcOptions } from "./cli-options.js"
import { type ToolName, setups } from "./tool.js"
import { type ToolName, llvmTools, setups } from "./tool.js"
import type { InstallationInfo } from "./utils/setup/setupBin.js"
import { setupVCVarsall } from "./vcvarsall/vcvarsall.js"
import { getVersion } from "./versions/versions.js"
@ -22,9 +22,8 @@ export async function installTool(
timeout: number = DEFAULT_TIMEOUT,
) {
startGroup(`Installing ${tool} ${version}`)
let hasLLVM = false
try {
hasLLVM = await pTimeout(installToolImpl(tool, version, osVersion, arch, setupCppDir, successMessages), {
await pTimeout(installToolImpl(tool, version, osVersion, arch, setupCppDir, successMessages), {
milliseconds: timeout,
message: `Timeout while installing ${tool} ${version}. You can increase the timeout from options`,
})
@ -37,7 +36,6 @@ export async function installTool(
errorMessages.push(`${tool} failed to install`)
}
endGroup()
return hasLLVM
}
async function installToolImpl(
@ -48,8 +46,7 @@ async function installToolImpl(
setupCppDir: string,
successMessages: string[],
) {
// eslint-disable-next-line no-param-reassign
const hasLLVM = ["llvm", "clangformat", "clangtidy"].includes(tool)
const hasLLVM = llvmTools.includes(tool)
let installationInfo: InstallationInfo | undefined | void
if (tool === "vcvarsall") {
@ -72,5 +69,4 @@ async function installToolImpl(
}
// preparing a report string
successMessages.push(getSuccessMessage(tool, installationInfo))
return hasLLVM
}

19
src/llvm/apple-clang.ts Normal file
View File

@ -0,0 +1,19 @@
import { error } from "console"
import { notice } from "ci-log"
import { addEnv } from "envosman"
import which from "which"
import { rcOptions } from "../cli-options.js"
export async function setupAppleClang() {
if (process.platform !== "darwin") {
return
}
if (await which("clang", { nothrow: true }) !== null && await which("clang++", { nothrow: true }) !== null) {
notice("Assuming clang is an Apple Clang compiler")
await Promise.all([addEnv("CC", "clang", rcOptions), addEnv("CXX", "clang++", rcOptions)])
}
// TODO install Apple Clang automatically
error("Apple Clang automatic installation is not supported yet")
}

View File

@ -18,6 +18,7 @@ import { type InstallationInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
import { semverCoerceIfInvalid } from "../utils/setup/version.js"
import { quoteIfHasSpace } from "../utils/std/index.js"
import { getVersion } from "../versions/versions.js"
import { LLVMPackages, setupLLVMApt } from "./llvm_installer.js"
import { getLLVMPackageInfo } from "./llvm_url.js"
@ -26,11 +27,11 @@ const dirname = typeof __dirname === "string" ? __dirname : path.dirname(fileURL
export async function setupLLVM(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
const installationInfo = await setupLLVMWithoutActivation(version, setupDir, arch)
await activateLLVM(installationInfo.installDir ?? setupDir)
await activateLLVM(installationInfo.installDir ?? setupDir, version)
return installationInfo
}
async function setupLLVMWithoutActivation_raw(version: string, setupDir: string, arch: string) {
async function setupLLVMWithoutActivation_(version: string, setupDir: string, arch: string) {
// install LLVM
const [installationInfo, _1] = await Promise.all([
setupLLVMOnly(version, setupDir, arch),
@ -42,7 +43,7 @@ async function setupLLVMWithoutActivation_raw(version: string, setupDir: string,
return installationInfo
}
const setupLLVMWithoutActivation = memoize(setupLLVMWithoutActivation_raw, { promise: true })
const setupLLVMWithoutActivation = memoize(setupLLVMWithoutActivation_, { promise: true })
/**
* Setup clang-format
@ -64,8 +65,7 @@ async function setupLLVMOnly(
arch: string,
packages: LLVMPackages = LLVMPackages.All,
) {
const coeredVersion = semverCoerceIfInvalid(version)
const majorVersion = Number.parseInt(coeredVersion.split(".")[0], 10)
const majorVersion = majorLLVMVersion(version)
try {
if (isUbuntu()) {
return await setupLLVMApt(majorVersion, packages)
@ -79,7 +79,12 @@ async function setupLLVMOnly(
return installationInfo
}
async function llvmBinaryDeps_raw(majorVersion: number) {
function majorLLVMVersion(version: string) {
const coeredVersion = semverCoerceIfInvalid(version)
return Number.parseInt(coeredVersion.split(".")[0], 10)
}
async function llvmBinaryDeps_(majorVersion: number) {
if (isUbuntu()) {
if (majorVersion <= 10) {
await installAptPack([{ name: "libtinfo5" }])
@ -96,36 +101,45 @@ async function llvmBinaryDeps_raw(majorVersion: number) {
])
}
}
const llvmBinaryDeps = memoize(llvmBinaryDeps_raw, { promise: true })
const llvmBinaryDeps = memoize(llvmBinaryDeps_, { promise: true })
async function setupLLVMDeps_raw(arch: string) {
async function setupLLVMDeps_(arch: string) {
if (process.platform === "linux") {
// using llvm requires ld, an up to date libstdc++, etc. So, install gcc first,
// but with a lower priority than the one used by activateLLVM()
await setupGcc(getVersion("gcc", undefined, await ubuntuVersion()), "", arch, 40)
}
}
const setupLLVMDeps = memoize(setupLLVMDeps_raw, { promise: true })
const setupLLVMDeps = memoize(setupLLVMDeps_, { promise: true })
export async function activateLLVM(directory: string) {
export async function activateLLVM(directory: string, version: string) {
const ld = process.env.LD_LIBRARY_PATH ?? ""
const dyld = process.env.DYLD_LIBRARY_PATH ?? ""
const llvmMajor = majorLLVMVersion(version)
const actPromises: Promise<void>[] = [
// compiler paths
addEnv("CC", addExeExt(`${directory}/bin/clang`), rcOptions),
addEnv("CXX", addExeExt(`${directory}/bin/clang++`), rcOptions),
// the output of this action
addEnv("LLVM_PATH", directory, rcOptions),
// Setup LLVM as the compiler
addEnv("LD_LIBRARY_PATH", `${directory}/lib${delimiter}${ld}`, rcOptions),
addEnv("DYLD_LIBRARY_PATH", `${directory}/lib${delimiter}${dyld}`, rcOptions),
addEnv("LD_LIBRARY_PATH", `${ld}${delimiter}${directory}/lib`, rcOptions),
addEnv("DYLD_LIBRARY_PATH", `${dyld}${delimiter}${directory}/lib`, rcOptions),
// compiler flags
addEnv("LDFLAGS", `-L"${directory}/lib"`, rcOptions),
addEnv("CPPFLAGS", `-I"${directory}/include"`, rcOptions),
addEnv("LLVM_LDFLAGS", `-L${quoteIfHasSpace(`${directory}/lib`)}`, rcOptions),
addEnv("LLVM_CPPFLAGS", `-I${quoteIfHasSpace(`${directory}/include`)}`, rcOptions),
// compiler paths
addEnv("CC", addExeExt(`${directory}/bin/clang`), rcOptions),
addEnv("CXX", addExeExt(`${directory}/bin/clang++`), rcOptions),
// CPATH
await pathExists(`${directory}/lib/clang/${version}/include`)
? addEnv("LLVM_CPATH", `${directory}/lib/clang/${version}/include`, rcOptions)
: await pathExists(`${directory}/lib/clang/${llvmMajor}/include`)
? addEnv("LLVM_CPATH", `${directory}/lib/clang/${llvmMajor}/include`, rcOptions)
: Promise.resolve(),
addEnv("LIBRARY_PATH", `${directory}/lib`, rcOptions),
@ -133,16 +147,6 @@ export async function activateLLVM(directory: string) {
setupMacOSSDK(),
]
// TODO Causes issues with clangd
// TODO Windows builds fail with llvm's CPATH
// if (process.platform !== "win32") {
// if (await pathExists(`${directory}/lib/clang/${version}/include`)) {
// promises.push(addEnv("CPATH", `${directory}/lib/clang/${version}/include`, rcOptions))
// } else if (await pathExists(`${directory}/lib/clang/${llvmMajor}/include`)) {
// promises.push(addEnv("CPATH", `${directory}/lib/clang/${llvmMajor}/include`, rcOptions))
// }
// }
if (isUbuntu()) {
const priority = 60
actPromises.push(

View File

@ -293,7 +293,7 @@ async function ensurePipUpgrade(foundPython: string) {
return false
}
async function addPythonBaseExecPrefix_raw(python: string) {
async function addPythonBaseExecPrefix_(python: string) {
const dirs: string[] = []
// detection based on the platform
@ -317,4 +317,4 @@ async function addPythonBaseExecPrefix_raw(python: string) {
*
* The answer is cached for subsequent calls
*/
export const addPythonBaseExecPrefix = memoize(addPythonBaseExecPrefix_raw, { promise: true })
export const addPythonBaseExecPrefix = memoize(addPythonBaseExecPrefix_, { promise: true })

View File

@ -13,7 +13,7 @@ import { checkUpdates } from "./check-updates.js"
import { parseArgs, printHelp, rcOptions } from "./cli-options.js"
import { installCompiler } from "./compilers.js"
import { installTool } from "./installTool.js"
import { tools } from "./tool.js"
import { type Inputs, llvmTools, tools } from "./tool.js"
import { isArch } from "./utils/env/isArch.js"
import { ubuntuVersion } from "./utils/env/ubuntu_version.js"
import { setupPacmanPack } from "./utils/setup/setupPacmanPack.js"
@ -56,8 +56,8 @@ async function main(args: string[]): Promise<number> {
const osVersion = await ubuntuVersion()
// sync the version for the llvm tools
if (!syncVersions(opts, ["llvm", "clangtidy", "clangformat"])) {
error("The same version must be used for llvm, clangformat and clangtidy")
if (!syncVersions(opts, llvmTools as Inputs[])) {
error("The same version must be used for llvm, clang-format and clang-tidy")
return 1
}
@ -66,9 +66,6 @@ async function main(args: string[]): Promise<number> {
await setupPacmanPack("python-pygments")
}
/** Used to unset CPPFLAGS of LLVM when other compilers are used as the main compiler */
let hasLLVM = false
// loop over the tools and run their setup function
let failedFast = false
@ -89,7 +86,7 @@ async function main(args: string[]): Promise<number> {
// running the setup function for this tool
time1 = Date.now()
// eslint-disable-next-line no-await-in-loop
hasLLVM = await installTool(
await installTool(
tool,
version,
osVersion,
@ -109,7 +106,7 @@ async function main(args: string[]): Promise<number> {
const maybeCompiler = opts.compiler
if (maybeCompiler !== undefined) {
const time1Compiler = Date.now()
await installCompiler(maybeCompiler, osVersion, setupCppDir, arch, successMessages, hasLLVM, errorMessages)
await installCompiler(maybeCompiler, osVersion, setupCppDir, arch, successMessages, errorMessages)
const time2Compiler = Date.now()
info(`took ${timeFormatter.format(time1Compiler, time2Compiler) || "0 seconds"}`)
}

View File

@ -6,10 +6,11 @@ import { setupCmake } from "./cmake/cmake.js"
import { setupConan } from "./conan/conan.js"
import { setupCppcheck } from "./cppcheck/cppcheck.js"
import { setupDoxygen } from "./doxygen/doxygen.js"
import { setupGcc } from "./gcc/gcc.js"
import { setupGcc, setupMingw } from "./gcc/gcc.js"
import { setupGcovr } from "./gcovr/gcovr.js"
import { setupGraphviz } from "./graphviz/graphviz.js"
import { setupKcov } from "./kcov/kcov.js"
import { setupAppleClang } from "./llvm/apple-clang.js"
import { setupClangFormat, setupClangTools, setupLLVM } from "./llvm/llvm.js"
import { setupMake } from "./make/make.js"
import { setupMeson } from "./meson/meson.js"
@ -25,8 +26,31 @@ import { setupTask } from "./task/task.js"
import { setupVcpkg } from "./vcpkg/vcpkg.js"
import { setupVCVarsall } from "./vcvarsall/vcvarsall.js"
export const llvmSetups = { llvm: setupLLVM, clang: setupLLVM, "clang++": setupLLVM } as const
export const gccSetups = { gcc: setupGcc, "g++": setupGcc } as const
export const mingwSetups = { mingw: setupMingw } as const
export const msvcSetups = {
msvc: setupMSVC,
cl: setupMSVC,
msbuild: setupMSVC,
visualstudio: setupMSVC,
} as const
export const appleClangSetups = {
appleclang: setupAppleClang,
applellvm: setupAppleClang,
"apple-clang": setupAppleClang,
"apple-llvm": setupAppleClang,
} as const
export const llvmTools = ["llvm", "clang", "clang++", "clang-tidy", "clang-format", "clangtidy", "clangformat"]
/** The setup functions */
export const setups = {
...llvmSetups,
...gccSetups,
...mingwSetups,
...msvcSetups,
...appleClangSetups,
nala: setupNala,
cmake: setupCmake,
ninja: setupNinja,
@ -37,25 +61,28 @@ export const setups = {
meson: setupMeson,
gcovr: setupGcovr,
opencppcoverage: setupOpencppcoverage,
llvm: setupLLVM,
gcc: setupGcc,
OpenCppCoverage: setupOpencppcoverage,
choco: setupChocolatey,
brew: setupBrew,
powershell: setupPowershell,
pwsh: setupPowershell,
ccache: setupCcache,
sccache: setupSccache,
doxygen: setupDoxygen,
graphviz: setupGraphviz,
cppcheck: setupCppcheck,
"clang-tidy": setupClangTools,
clangtidy: setupClangTools,
"clang-format": setupClangFormat,
clangformat: setupClangFormat,
msvc: setupMSVC,
vcvarsall: setupVCVarsall,
kcov: setupKcov,
make: setupMake,
task: setupTask,
sevenzip: setupSevenZip,
}
"7zip": setupSevenZip,
"7z": setupSevenZip,
} as const
export type ToolName = keyof typeof setups

View File

@ -6,7 +6,7 @@ import memoize from "memoizee"
*
* @returns {number[]} - The macOS version as an array of numbers
*/
function macosVersion_raw() {
function macosVersion_() {
if (process.platform !== "darwin") {
return []
}
@ -14,4 +14,4 @@ function macosVersion_raw() {
const { version } = macosRelease()
return version.split(".").map((v) => Number.parseInt(v, 10))
}
export const macosVersion = memoize(macosVersion_raw)
export const macosVersion = memoize(macosVersion_)

View File

@ -6,7 +6,7 @@ import { getUbuntuVersion } from "ubuntu-version"
import which from "which"
import { isUbuntu } from "./isUbuntu.js"
async function ubuntuVersion_raw(): Promise<number[] | null> {
async function ubuntuVersion_(): Promise<number[] | null> {
try {
if (isUbuntu()) {
try {
@ -34,7 +34,7 @@ async function ubuntuVersion_raw(): Promise<number[] | null> {
}
/** Detect Ubuntu version */
export const ubuntuVersion = memoize(ubuntuVersion_raw, { promise: true })
export const ubuntuVersion = memoize(ubuntuVersion_, { promise: true })
/** Detect Ubuntu version using os.version() for Ubuntu based distros */
function detectUsingOsVersion() {

View File

@ -97,7 +97,7 @@ export async function hasPipx(givenPython: string) {
return (await execa(givenPython, ["-m", "pipx", "--help"], { stdio: "ignore", reject: false })).exitCode === 0
}
async function getPipxHome_raw() {
async function getPipxHome_() {
let pipxHome = process.env.PIPX_HOME
if (pipxHome !== undefined) {
return pipxHome
@ -130,9 +130,9 @@ async function getPipxHome_raw() {
await mkdirp(join(pipxHome, "venv"))
return pipxHome
}
const getPipxHome = memoize(getPipxHome_raw, { promise: true })
const getPipxHome = memoize(getPipxHome_, { promise: true })
async function getPipxBinDir_raw() {
async function getPipxBinDir_() {
if (process.env.PIPX_BIN_DIR !== undefined) {
return process.env.PIPX_BIN_DIR
}
@ -142,16 +142,16 @@ async function getPipxBinDir_raw() {
await mkdirp(pipxBinDir)
return pipxBinDir
}
const getPipxBinDir = memoize(getPipxBinDir_raw, { promise: true })
const getPipxBinDir = memoize(getPipxBinDir_, { promise: true })
async function getPython_raw(): Promise<string> {
async function getPython_(): Promise<string> {
const pythonBin = (await setupPython(getVersion("python", undefined, await ubuntuVersion()), "", process.arch)).bin
if (pythonBin === undefined) {
throw new Error("Python binary was not found")
}
return pythonBin
}
const getPython = memoize(getPython_raw, { promise: true })
const getPython = memoize(getPython_, { promise: true })
async function pipHasPackage(python: string, name: string) {
const result = await execa(python, ["-m", "pip", "-qq", "index", "versions", name], {

View File

@ -1,3 +1,7 @@
export function unique(dirs: string[]) {
return [...new Set(dirs)]
}
export function quoteIfHasSpace(str: string, quoteChar = "\"") {
return str.includes(" ") ? `${quoteChar}${str}${quoteChar}` : str
}

View File

@ -11,7 +11,11 @@ const defaultLLVM = process.platform === "darwin" && process.arch === "x64"
export const DefaultVersions: Record<string, string | undefined> = {
// https://github.com/llvm/llvm-project/releases
llvm: defaultLLVM,
clang: defaultLLVM,
"clang++": defaultLLVM,
"clang-tidy": defaultLLVM,
clangtidy: defaultLLVM,
"clang-format": defaultLLVM,
clangformat: defaultLLVM,
ninja: "1.12.1", // https://github.com/ninja-build/ninja/releases
cmake: "3.30.2", // https://github.com/Kitware/CMake/releases