Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for cmakelang, cmake-lint, cmake-format + skip pipx/pip package install if not requested #294

Merged
merged 8 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Setting up a **cross-platform** environment for building and testing C++/C proje
| category | tools |
| --------------------- | --------------------------------------------------------------------------- |
| compiler and analyzer | llvm, gcc, msvc, apple-clang, vcvarsall, cppcheck, clang-tidy, clang-format |
| build system | cmake, ninja, meson, make, task, bazel |
| build system | cmake, ninja, meson, make, task, bazel, cmakelang, cmake-format, cmake-lint |
| package manager | vcpkg, conan, choco, brew, nala |
| cache | ccache, sccache |
| documentation | doxygen, graphviz |
Expand Down
15 changes: 15 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ inputs:
cmake:
description: "Wether to install cmake (true/false) or the specific version to install."
required: false
cmakelang:
description: "Wether to install cmakelang (true/false) or the specific version to install."
required: false
cmake-lint:
description: "Wether to install cmake-lint (true/false) or the specific version to install."
required: false
cmakelint:
description: "Wether to install cmake-lint (true/false) or the specific version to install."
required: false
cmake-format:
description: "Wether to install cmake-format (true/false) or the specific version to install."
required: false
cmakeformat:
description: "Wether to install cmake-format (true/false) or the specific version to install."
required: false
ninja:
description: "Wether to install ninja (true/false) or the specific version to install."
required: false
Expand Down
1 change: 1 addition & 0 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ words:
- choco
- clangd
- cmake
- cmakeformat
- cobertura
- copr
- CPATH
Expand Down
2 changes: 1 addition & 1 deletion dist/legacy/setup-cpp.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/legacy/setup-cpp.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/modern/setup-cpp.mjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/modern/setup-cpp.mjs.map

Large diffs are not rendered by default.

85 changes: 45 additions & 40 deletions packages/setup-apt/src/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,55 +68,60 @@ const retryErrors = [
* ```
*/
export async function installAptPack(packages: AptPackage[], update = false): Promise<InstallationInfo> {
const apt: string = getApt()

for (const { name, version } of packages) {
info(`Installing ${name} ${version ?? ""} via ${apt}`)
}
try {
const apt: string = getApt()

// Update the repos if needed
if (update) {
updateAptReposMemoized(apt)
}
for (const { name, version } of packages) {
info(`Installing ${name} ${version ?? ""} via ${apt}`)
}

// Add the repos if needed
await addRepositories(apt, packages)
// Update the repos if needed
if (update) {
updateAptReposMemoized(apt)
}

const needToInstall = await filterAndQualifyAptPackages(packages, apt)
// Add the repos if needed
await addRepositories(apt, packages)

if (needToInstall.length === 0) {
info("All packages are already installed")
return { binDir: "/usr/bin/" }
}
const needToInstall = await filterAndQualifyAptPackages(packages, apt)

// Initialize apt if needed
await initAptMemoized(apt)
if (needToInstall.length === 0) {
info("All packages are already installed")
return { binDir: "/usr/bin/" }
}

try {
// Add the keys if needed
await addAptKeys(packages)

// Install
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], {
...defaultExecOptions,
env: getAptEnv(apt),
})
} catch (err) {
if (isExecaError(err)) {
if (retryErrors.some((error) => err.stderr.includes(error))) {
warning(`Failed to install packages ${needToInstall}. Retrying...`)
execRootSync(
apt,
["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstall],
{ ...defaultExecOptions, env: getAptEnv(apt) },
)
// Initialize apt if needed
await initAptMemoized(apt)

try {
// Add the keys if needed
await addAptKeys(packages)

// Install
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], {
...defaultExecOptions,
env: getAptEnv(apt),
})
} catch (err) {
if (isExecaError(err)) {
if (retryErrors.some((error) => err.stderr.includes(error))) {
warning(`Failed to install packages ${needToInstall}. Retrying...`)
execRootSync(
apt,
["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstall],
{ ...defaultExecOptions, env: getAptEnv(apt) },
)
}
} else {
throw err
}
} else {
throw err
}
}

return { binDir: "/usr/bin/" }
return { binDir: "/usr/bin/" }
} catch (err) {
const msg = err instanceof Error ? `${err.message}\n${err.stack}` : String(err)
throw new Error(`Failed to install apt packages: ${msg}`)
}
}

async function addRepositories(apt: string, packages: AptPackage[]) {
Expand Down
4 changes: 3 additions & 1 deletion src/cli-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ All the available tools:
"compiler and analyzer": {
tools: "--llvm, --gcc, --msvc, --apple-clang, --vcvarsall, --cppcheck, --clang-tidy, --clang-format",
},
"build system": { tools: "--cmake, --ninja, --meson, --make, --task, --bazel" },
"build system": {
tools: "--cmake, --ninja, --meson, --make, --task, --bazel, --cmakelang, --cmake-lint, --cmake-format",
},
"package manager": { tools: "--vcpkg, --conan, --choco, --brew, --nala" },
cache: { tools: "--ccache, --sccache" },
documentation: { tools: "--doxygen, --graphviz" },
Expand Down
13 changes: 13 additions & 0 deletions src/cmakelang/__tests__/cmakelang.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import { testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupCmakelang } from "../cmakelang.js"

jest.setTimeout(300000)
describe("setup-cmakelang", () => {
it("should setup cmakelang", async () => {
const installInfo = await setupCmakelang(getVersion("cmakelang", "true", await ubuntuVersion()), "", process.arch)
await testBin("cmake-lint", ["--version"], installInfo.binDir)
await testBin("cmake-format", ["--version"], installInfo.binDir)
})
})
6 changes: 6 additions & 0 deletions src/cmakelang/cmakelang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { setupPipPack } from "../utils/setup/setupPipPack.js"

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setupCmakelang(version: string | undefined, _setupDir: string, _arch: string) {
return setupPipPack("cmakelang[YAML]", version)
}
30 changes: 20 additions & 10 deletions src/python/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ import { isBinUptoDate } from "../utils/setup/version.js"
import { unique } from "../utils/std/index.js"
import { MinVersions } from "../versions/default_versions.js"

export async function setupPython(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
export async function setupPython(
version: string,
setupDir: string,
arch: string,
): Promise<InstallationInfo & { bin: string }> {
const installInfo = await findOrSetupPython(version, setupDir, arch)
assert(installInfo.bin !== undefined)
const foundPython = installInfo.bin
Expand All @@ -41,7 +45,7 @@ export async function setupPython(version: string, setupDir: string, arch: strin

await setupWheel(foundPython)

return installInfo
return installInfo as InstallationInfo & { bin: string }
}

async function setupPipx(foundPython: string) {
Expand All @@ -56,12 +60,20 @@ async function setupPipx(foundPython: string) {
}
}
await execa(foundPython, ["-m", "pipx", "ensurepath"], { stdio: "inherit" })
await setupPipPackWithPython(foundPython, "venv", undefined, { upgrade: false, usePipx: false })
await setupVenv(foundPython)
} catch (err) {
warning(`Failed to install pipx: ${(err as Error).toString()}. Ignoring...`)
}
}

async function setupVenv(foundPython: string) {
try {
await setupPipPackWithPython(foundPython, "venv", undefined, { upgrade: false, usePipx: false })
} catch (err) {
warning(`Failed to install venv: ${(err as Error).toString()}. Ignoring...`)
}
}

/** Setup wheel and setuptools */
async function setupWheel(foundPython: string) {
try {
Expand All @@ -70,9 +82,9 @@ async function setupWheel(foundPython: string) {
isLibrary: true,
usePipx: false,
})
await setupPipPackWithPython(foundPython, "wheel", undefined, { upgrade: true, isLibrary: true, usePipx: false })
await setupPipPackWithPython(foundPython, "wheel", undefined, { upgrade: false, isLibrary: true, usePipx: false })
} catch (err) {
warning(`Failed to install setuptools or wheel: ${(err as Error).toString()}. Ignoring...`)
warning(`Failed to install setuptools/wheel: ${(err as Error).toString()}. Ignoring...`)
}
}

Expand Down Expand Up @@ -171,7 +183,7 @@ async function setupPythonSystem(setupDir: string, version: string) {
}

async function findPython(binDir?: string) {
for (const pythonBin of ["python3", "python"]) {
for (const pythonBin of ["python", "python3"]) {
// eslint-disable-next-line no-await-in-loop
const foundPython = await isPythonUpToDate(pythonBin, binDir)
if (foundPython !== undefined) {
Expand Down Expand Up @@ -203,10 +215,8 @@ async function isPythonUpToDate(candidate: string, binDir?: string) {
try {
if (binDir !== undefined) {
const pythonBinPath = join(binDir, addExeExt(candidate))
if (await pathExists(pythonBinPath)) {
if (await isBinUptoDate(pythonBinPath, MinVersions.python!)) {
return pythonBinPath
}
if (await pathExists(pythonBinPath) && await isBinUptoDate(pythonBinPath, MinVersions.python!)) {
return pythonBinPath
}
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
Expand Down
22 changes: 16 additions & 6 deletions src/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { setupBazel } from "./bazel/bazel.js"
import { setupCcache } from "./ccache/ccache.js"
import { setupChocolatey } from "./chocolatey/chocolatey.js"
import { setupCmake } from "./cmake/cmake.js"
import { setupCmakelang } from "./cmakelang/cmakelang.js"
import { setupConan } from "./conan/conan.js"
import { setupCppcheck } from "./cppcheck/cppcheck.js"
import { setupDoxygen } from "./doxygen/doxygen.js"
Expand Down Expand Up @@ -42,30 +43,39 @@ export const appleClangSetups = {
"apple-llvm": setupAppleClang,
} as const

const cmakeLangSetups = {
cmakelang: setupCmakelang,
"cmake-lint": setupCmakelang,
"cmake-format": setupCmakelang,
cmakelint: setupCmakelang,
cmakeformat: setupCmakelang,
} as const

export const llvmTools = ["llvm", "clang", "clang++", "clang-tidy", "clang-format", "clangtidy", "clangformat"]

/** The setup functions */
export const setups = {
nala: setupNala,
brew: setupBrew,
choco: setupChocolatey,
python: setupPython,
powershell: setupPowershell,
pwsh: setupPowershell,
...llvmSetups,
...gccSetups,
...mingwSetups,
...msvcSetups,
...appleClangSetups,
nala: setupNala,
...cmakeLangSetups,
cmake: setupCmake,
ninja: setupNinja,
python: setupPython,
vcpkg: setupVcpkg,
bazel: setupBazel,
conan: setupConan,
meson: setupMeson,
gcovr: setupGcovr,
opencppcoverage: setupOpencppcoverage,
OpenCppCoverage: setupOpencppcoverage,
choco: setupChocolatey,
brew: setupBrew,
powershell: setupPowershell,
pwsh: setupPowershell,
ccache: setupCcache,
sccache: setupSccache,
doxygen: setupDoxygen,
Expand Down
91 changes: 91 additions & 0 deletions src/utils/compat/node.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// the installed @types/node package is version 12 so that backwards compatibility is maintained
// node: prefix is removed by Babel, so define the types of those packages here so that TypeScript can find them

declare module "node:fs" {
import fs from "fs"
export = fs
}

declare module "node:path" {
import path from "path"
export = path
}

declare module "node:child_process" {
import child_process from "child_process"
export = child_process
}

declare module "node:os" {
import os from "os"
export = os
}

declare module "node:util" {
import util from "util"
export = util
}

declare module "node:stream" {
import stream from "stream"
export = stream
}

declare module "node:zlib" {
import zlib from "zlib"
export = zlib
}

declare module "node:crypto" {
import crypto from "crypto"
export = crypto
}
declare module "node:http" {
import http from "http"
export = http
}

declare module "node:https" {
import https from "https"
export = https
}

declare module "node:events" {
import events from "events"
export = events
}

declare module "node:assert" {
import assert from "assert"
export = assert
}

declare module "node:constants" {
import constants from "constants"
export = constants
}

declare module "node:querystring" {
import querystring from "querystring"
export = querystring
}

declare module "node:url" {
import url from "url"
export = url
}

declare module "node:fs/promises" {
import fsPromises from "fs/promises"
export = fsPromises
}

declare module "node:path/posix" {
import pathPosix from "path/posix"
export = pathPosix
}

declare module "node:path/win32" {
import pathWin32 from "path/win32"
export = pathWin32
}
Loading
Loading