Restore [vcpkg].version functionality and add a test + documentation

toml-checker
Duncan Ogilvie 3 years ago
parent ffdedbdace
commit 7b20d8c54c

@ -0,0 +1,36 @@
---
# Automatically generated from tests/vcpkg/cmake.toml - DO NOT EDIT
layout: default
title: Dependencies from vcpkg
permalink: /examples/vcpkg
parent: Examples
nav_order: 4
---
# Dependencies from vcpkg
Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it:
```toml
[project]
name = "vcpkg"
description = "Dependencies from vcpkg"
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions
# See https://vcpkg.io/en/packages.html for available packages
[vcpkg]
version = "2021.05.12"
packages = ["fmt"]
[find-package]
fmt = {}
[target.example]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["fmt::fmt"]
```
The bootstrapping of vcpkg is fully automated and no user interaction is necessary. You can disable vcpkg by setting `CMKR_DISABLE_VCPKG=ON`.
<sup><sub>This page was automatically generated from [tests/vcpkg/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/vcpkg/cmake.toml).</sub></sup>

@ -33,6 +33,7 @@ struct Package {
};
struct Vcpkg {
std::string version;
std::string url;
std::vector<std::string> packages;
};

@ -257,7 +257,8 @@ CMake::CMake(const std::string &path, bool build) {
if (toml.contains("vcpkg")) {
const auto &v = toml::find(toml, "vcpkg");
vcpkg.url = toml::find(v, "url").as_string();
get_optional(v, "url", vcpkg.url);
get_optional(v, "version", vcpkg.version);
vcpkg.packages = toml::find<decltype(vcpkg.packages)>(v, "packages");
}

@ -163,7 +163,7 @@ struct Command {
~Command() {
if (!generated) {
assert(false && "Incorrect usage of cmd()");
assert(false && "Incorrect usage of cmd(), you probably forgot ()");
}
}
@ -297,7 +297,7 @@ struct Command {
}
template <class... Ts>
CommandEndl operator()(Ts &&... values) {
CommandEndl operator()(Ts &&...values) {
generated = true;
ss << indent(depth) << command << '(';
(void)std::initializer_list<bool>{print_arg(values)...};
@ -406,6 +406,31 @@ struct Generator {
}
};
static std::string vcpkg_escape_identifier(const std::string &name) {
// Do a reasonable effort to escape the project name for use with vcpkg
std::string escaped;
for (char ch : name) {
if ((ch & 0x80) != 0) {
throw std::runtime_error("Non-ASCII characters are not allowed in [project].name when using [vcpkg]");
}
if (ch == '_' || ch == ' ') {
ch = '-';
}
escaped += std::tolower(ch);
}
const std::regex reserved("prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default");
const std::regex ok("[a-z0-9]+(-[a-z0-9]+)*");
std::cmatch m;
if (!std::regex_match(escaped.c_str(), m, reserved) && std::regex_match(escaped.c_str(), m, ok)) {
return escaped;
} else {
throw std::runtime_error("The escaped project name '" + escaped + "' is not usable with [vcpkg]");
}
}
int generate_cmake(const char *path, bool root) {
if (!fs::exists(fs::path(path) / "cmake.toml")) {
throw std::runtime_error("No cmake.toml found!");
@ -422,8 +447,9 @@ int generate_cmake(const char *path, bool root) {
auto inject_includes = [&gen](const std::vector<std::string> &includes) { gen.inject_includes(includes); };
auto inject_cmake = [&gen](const std::string &cmake) { gen.inject_cmake(cmake); };
std::string cmkr_url = "https://github.com/build-cpp/cmkr";
comment("This file is automatically generated from cmake.toml - DO NOT EDIT");
comment("See https://github.com/build-cpp/cmkr for more information");
comment("See " + cmkr_url + " for more information");
endl();
if (root) {
@ -523,30 +549,40 @@ int generate_cmake(const char *path, bool root) {
}
}
if (!cmake.vcpkg.packages.empty() && !cmake.vcpkg.url.empty()) {
auto vcpkg_escape_identifier = [](const std::string &name) -> std::string {
const std::regex ok("[a-z0-9]+(-[a-z0-9]+)*");
const std::regex reserved("prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default");
std::cmatch m;
if (!std::regex_match(name.c_str(), m, reserved) && std::regex_match(name.c_str(), m, ok)) {
return name;
} else {
// should probably throw!
return "project-name";
if (!cmake.vcpkg.packages.empty()) {
// Allow the user to specify a url or derive it from the version
auto url = cmake.vcpkg.url;
if (url.empty()) {
if (cmake.vcpkg.version.empty()) {
throw std::runtime_error("You need either [vcpkg].version or [vcpkg].url");
}
};
url = "https://github.com/microsoft/vcpkg/archive/refs/tags/" + cmake.vcpkg.version + ".tar.gz";
}
// CMake to bootstrap vcpkg and download the packages
// clang-format off
cmd("if")("CMKR_ROOT_PROJECT", "AND", "NOT", "CMKR_DISABLE_VCPKG");
cmd("include")("FetchContent");
cmd("message")("STATUS", "Fetching vcpkg...");
cmd("FetchContent_Declare")("vcpkg", "URL", url);
cmd("FetchContent_MakeAvailable")("vcpkg");
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
cmd("endif")();
// clang-format on
// Generate vcpkg.json
using namespace nlohmann;
json j;
j["$cmkr"] = "This file is automatically generated from cmake.toml - DO NOT EDIT";
j["$cmkr-url"] = cmkr_url;
j["$schema"] = "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json";
j["name"] = vcpkg_escape_identifier(cmake.project_name);
if (!cmake.project_version.empty())
j["version"] = cmake.project_version;
j["version-string"] = cmake.project_version;
j["dependencies"] = cmake.vcpkg.packages;
cmd("include")("FetchContent");
cmd("message")("STATUS", "Fetching vcpkg...");
cmd("FetchContent_Declare")("vcpkg", "URL", cmake.vcpkg.url);
cmd("FetchContent_MakeAvailable")("vcpkg");
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
if (!cmake.project_description.empty()) {
j["description"] = cmake.project_description;
}
std::ofstream ofs("vcpkg.json");
if (!ofs) {
throw std::runtime_error("Failed to create a vcpkg.json manifest file!");

10
tests/CMakeLists.txt generated

@ -48,3 +48,13 @@ add_test(
build
)
add_test(
NAME
vcpkg
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/vcpkg"
COMMAND
$<TARGET_FILE:cmkr>
build
)

@ -20,4 +20,10 @@ arguments = ["build"]
name = "conditions"
command = "$<TARGET_FILE:cmkr>"
working-directory = "conditions"
arguments = ["build"]
[[test]]
name = "vcpkg"
command = "$<TARGET_FILE:cmkr>"
working-directory = "vcpkg"
arguments = ["build"]

@ -0,0 +1,21 @@
# Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it:
[project]
name = "vcpkg"
description = "Dependencies from vcpkg"
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions
# See https://vcpkg.io/en/packages.html for available packages
[vcpkg]
version = "2021.05.12"
packages = ["fmt"]
[find-package]
fmt = {}
[target.example]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["fmt::fmt"]
# The bootstrapping of vcpkg is fully automated and no user interaction is necessary. You can disable vcpkg by setting `CMKR_DISABLE_VCPKG=ON`.

@ -0,0 +1,6 @@
#include <fmt/core.h>
int main()
{
fmt::print("Hello, world!\n");
}

@ -0,0 +1,11 @@
{
"$cmkr": "This file is automatically generated from cmake.toml - DO NOT EDIT",
"$cmkr-url": "https://github.com/build-cpp/cmkr",
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"dependencies": [
"fmt"
],
"description": "Example of using vcpkg",
"name": "vcpkg",
"version-string": ""
}
Loading…
Cancel
Save