setup-cpp/src/main.ts

250 lines
7.0 KiB
TypeScript
Raw Normal View History

2021-09-14 15:03:59 +08:00
import * as core from "@actions/core"
2021-09-16 16:26:53 +08:00
import { setupBrew } from "./brew/brew"
2021-09-16 16:41:47 +08:00
import { setupCcache } from "./ccache/ccache"
2021-09-15 05:01:08 +08:00
import { setupChocolatey } from "./chocolatey/chocolatey"
import { setupCmake } from "./cmake/cmake"
2021-09-15 01:06:20 +08:00
import { setupConan } from "./conan/conan"
2021-09-16 16:47:47 +08:00
import { setupCppcheck } from "./cppcheck/cppcheck"
import { setupDoxygen } from "./doxygen/doxygen"
2021-09-15 01:42:08 +08:00
import { setupGcovr } from "./gcovr/gcovr"
import { setupLLVM } from "./llvm/llvm"
2021-09-15 01:09:58 +08:00
import { setupMeson } from "./meson/meson"
2021-09-15 18:25:02 +08:00
import { setupMSVC } from "./msvc/msvc"
import { setupNinja } from "./ninja/ninja"
2021-09-16 16:49:25 +08:00
import { setupOpencppcoverage } from "./opencppcoverage/opencppcoverage"
import { setupPython } from "./python/python"
2021-09-18 01:51:59 +08:00
import mri from "mri"
2021-09-18 02:54:30 +08:00
import untildify from "untildify"
2021-09-18 21:27:06 +08:00
import { isCI } from "./utils/env/isci"
2021-09-16 19:07:52 +08:00
import semverValid from "semver/functions/valid"
2021-09-16 19:36:35 +08:00
import { getVersion } from "./default_versions"
2021-09-16 22:03:54 +08:00
import { setupGcc } from "./gcc/gcc"
2021-09-18 01:51:59 +08:00
import { InstallationInfo } from "./utils/setup/setupBin"
2021-09-18 21:21:22 +08:00
import { error, success } from "./utils/io/io"
2021-09-16 22:03:54 +08:00
2021-09-18 01:51:59 +08:00
/** The setup functions */
const setups = {
cmake: setupCmake,
ninja: setupNinja,
python: setupPython,
conan: setupConan,
meson: setupMeson,
gcovr: setupGcovr,
opencppcoverage: setupOpencppcoverage,
llvm: setupLLVM,
gcc: setupGcc,
choco: setupChocolatey,
brew: setupBrew,
ccache: setupCcache,
doxygen: setupDoxygen,
cppcheck: setupCppcheck,
msvc: setupMSVC,
}
2021-09-18 01:51:59 +08:00
/** The tools that can be installed */
const tools: Array<keyof typeof setups> = [
"choco",
"brew",
"python",
2021-09-16 22:03:54 +08:00
"cmake",
"ninja",
"conan",
"meson",
"gcovr",
"opencppcoverage",
"ccache",
"doxygen",
"cppcheck",
"llvm",
"gcc",
2021-09-16 22:03:54 +08:00
"msvc",
]
2021-09-18 01:51:59 +08:00
/** The possible inputs to the program */
type Inputs = keyof typeof setups | "compiler" | "architecture"
2021-09-18 01:51:59 +08:00
// an array of possible inputs
const inputs: Array<Inputs> = ["compiler", "architecture", ...tools]
/** The main entry function */
export async function main(args: string[]): Promise<number> {
2021-09-18 21:27:06 +08:00
if (!isCI()) {
process.env.ACTIONS_ALLOW_UNSECURE_COMMANDS = "true"
}
2021-09-18 01:51:59 +08:00
// parse options using mri or github actions
2021-09-18 02:09:00 +08:00
const opts = mri<Record<Inputs, string | undefined> & { help: boolean }>(args, {
2021-09-18 01:51:59 +08:00
string: inputs,
default: Object.fromEntries(inputs.map((inp) => [inp, maybeGetInput(inp)])),
2021-09-18 02:09:00 +08:00
alias: { h: "help" },
boolean: "help",
2021-09-18 01:51:59 +08:00
})
2021-09-14 15:03:59 +08:00
2021-09-18 02:09:00 +08:00
// print help
if (opts.help) {
printHelp()
}
2021-09-18 01:51:59 +08:00
// cpu architecture
const arch = opts.architecture ?? process.arch
// the installation dir for the tools that are downloaded directly
2021-09-18 02:54:30 +08:00
const setupCppDir = process.env.SETUP_CPP_DIR ?? untildify("~/setup_cpp")
2021-09-18 01:51:59 +08:00
// report messages
const successMessages: string[] = []
const errorMessages: string[] = []
// installing the specified tools
// loop over the tools and run their setup function
for (const tool of tools) {
// get the version or "true" or undefined for this tool from the options
const value = opts[tool]
// skip if undefined
if (value !== undefined) {
// get the setup function
const setupFunction = setups[tool]
// runnig the setup function for this tool
try {
// eslint-disable-next-line no-await-in-loop
const installationInfo = await setupFunction(getVersion(tool, value), setupCppDir, arch)
// preparing a report string
if (installationInfo !== undefined) {
successMessages.push(getSuccessMessage(tool, installationInfo))
} else {
successMessages.push(`${tool} was successfully installed`)
}
} catch (e) {
// push error message to the logger
2021-09-18 21:21:22 +08:00
error(e as string | Error)
errorMessages.push(`${tool} failed to install`)
}
}
}
2021-09-18 01:51:59 +08:00
// installing the specified compiler
const maybeCompiler = opts.compiler
2021-09-14 15:03:59 +08:00
try {
2021-09-16 19:07:52 +08:00
if (maybeCompiler !== undefined) {
2021-09-18 01:51:59 +08:00
// detecting the compiler version. Devide the given string by `-` and use the second element as the version
2021-09-16 19:07:52 +08:00
const compilerAndMaybeVersion = maybeCompiler.split("-")
const compiler = compilerAndMaybeVersion[0]
let version: string | undefined
if (1 in compilerAndMaybeVersion) {
const maybeVersion = compilerAndMaybeVersion[1]
if (semverValid(maybeVersion) !== null) {
version = maybeVersion
} else {
2021-09-18 21:21:22 +08:00
error(`Invalid version ${maybeVersion} used for the compiler. Using the default version...`)
2021-09-16 19:07:52 +08:00
}
}
2021-09-18 01:51:59 +08:00
// install the compiler. We allow some aliases for the compiler name
2021-09-16 19:07:52 +08:00
switch (compiler) {
case "llvm":
case "clang":
case "clang++": {
await setupLLVM(getVersion("llvm", version) as string, setupCppDir, arch)
2021-09-16 19:07:52 +08:00
break
}
2021-09-16 22:03:54 +08:00
case "gcc":
case "mingw":
case "cygwin":
case "msys": {
await setupGcc(getVersion("gcc", version) as string, setupCppDir, arch)
break
}
2021-09-16 19:07:52 +08:00
case "cl":
case "msvc":
case "msbuild":
case "vs":
case "visualstudio":
case "visualcpp":
case "visualc++": {
await setupMSVC(getVersion("msvc", version) as string, setupCppDir, arch)
2021-09-16 19:07:52 +08:00
break
}
default: {
2021-09-18 01:51:59 +08:00
errorMessages.push(`Unsupported compiler ${compiler}`)
2021-09-16 19:07:52 +08:00
}
}
}
2021-09-18 01:51:59 +08:00
} catch (e) {
2021-09-18 21:21:22 +08:00
error(e as string | Error)
2021-09-18 01:51:59 +08:00
errorMessages.push(`Failed to install the ${maybeCompiler}`)
}
// report the messages in the end
2021-09-18 21:21:22 +08:00
successMessages.forEach((tool) => success(tool))
errorMessages.forEach((tool) => error(tool))
2021-09-18 01:51:59 +08:00
2021-09-18 02:19:10 +08:00
core.info("setup_cpp finished")
2021-09-18 01:51:59 +08:00
return errorMessages.length === 0 ? 0 : 1 // exit with non-zero if any error message
2021-09-14 15:03:59 +08:00
}
2021-09-18 01:51:59 +08:00
// Run main
main(process.argv)
2021-09-14 15:03:59 +08:00
.then((ret) => {
process.exitCode = ret
})
2021-09-18 21:21:22 +08:00
.catch((err) => {
error("main() panicked!")
error(err as string | Error)
2021-09-14 15:03:59 +08:00
process.exitCode = 1
})
2021-09-18 01:51:59 +08:00
2021-09-18 02:09:00 +08:00
function printHelp() {
core.info(`
2021-09-18 02:19:10 +08:00
setup_cpp [options]
setup_cpp --compiler llvm --cmake true --ninja true --ccache true --conan "1.40.1"
2021-09-18 02:09:00 +08:00
Install all the tools required for building and testing C++/C projects.
--architecture\t the cpu architecture to install the tools for. By default it uses the current CPU architecture.
--compiler\t the <compiler> to install.
\t You can specify the version instead of specifying just the name e.g: --compiler 'llvm-11'
--tool_name\t pass "true" or pass the <version> you would like to install for this tool.
All the available tools:
--llvm
--gcc
--cmake
--ninja
--meson
--conan
--ccache
--cppcheck
--doxygen
--gcovr
--opencppcoverage
--python
--choco
--brew
`)
}
2021-09-18 01:51:59 +08:00
/** Get an object from github actions */
function maybeGetInput(key: string) {
const value = core.getInput(key.toLowerCase())
if (value !== "false" && value !== "") {
return value
}
return undefined // skip installation
}
function getSuccessMessage(tool: string, installationInfo: InstallationInfo) {
2021-09-18 21:21:22 +08:00
let msg = `${tool} was successfully installed`
2021-09-18 01:51:59 +08:00
if ("installDir" in installationInfo) {
2021-09-18 21:21:22 +08:00
msg += `\nThe installation direcotry is ${installationInfo.installDir}`
2021-09-18 01:51:59 +08:00
}
if (installationInfo.binDir !== "") {
2021-09-18 21:21:22 +08:00
msg += `\nThe binary direcotry is ${installationInfo.binDir}`
2021-09-18 01:51:59 +08:00
}
2021-09-18 21:21:22 +08:00
return msg
2021-09-18 01:51:59 +08:00
}