Compare commits

...

14 Commits

Author SHA1 Message Date
Duncan Ogilvie 1596a8143d Bump to 0.2.12 2022-03-06 06:07:55 +01:00
Duncan Ogilvie 9b0f18ee94 Fix a bug in fetch-content generation 2022-03-06 06:05:17 +01:00
Duncan Ogilvie 887086dc05 Credits 2022-02-23 21:32:58 +01:00
Duncan Ogilvie edc8e1e02e Bump to 0.2.11 2022-02-12 04:42:19 +01:00
Duncan Ogilvie 1f6e31e0ef Add optional CMKR_COMMIT_HASH for the paranoid 2022-02-12 04:39:34 +01:00
Duncan Ogilvie 4de1500bb3 Refactor cmake injection 2022-02-12 04:14:47 +01:00
Duncan Ogilvie 85370968f8 Improved fetch-content support
Closes #38
2022-02-12 04:05:51 +01:00
Duncan Ogilvie 06a4c04df6 Add support for 'shallow' in fetch-content 2022-02-12 03:10:25 +01:00
Duncan Ogilvie fef2a0215b Error when recursively globbing in the project root
Closes #48
2022-02-12 03:03:57 +01:00
Duncan Ogilvie fc74a5e802 Bump to 0.2.10 2022-02-12 02:45:10 +01:00
Duncan Ogilvie e48d402e21 Improve version bumping script 2022-02-12 02:44:45 +01:00
Duncan Ogilvie f6a245618e Merge pull request #53 from build-cpp/better-validation
Better TOML validation
2022-02-12 02:44:05 +01:00
Duncan Ogilvie c713606fd4 Error when using an unknown key in the root of the TOML
[error] Unknown key 'fetch-cntent'
 --> cmake.toml:2
   |
 2 | [fetch-cntent.blah]
   |  ~~~~~~~~~~~~
2022-02-12 02:19:37 +01:00
Duncan Ogilvie fe9b6587a9 Error when trying to parse an empty cmake.toml file 2022-02-12 02:07:30 +01:00
8 changed files with 176 additions and 82 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ project(cmkr
LANGUAGES
CXX
VERSION
0.2.9
0.2.12
DESCRIPTION
"CMakeLists generator from TOML"
)
+1
View File
@@ -69,3 +69,4 @@ arguments:
- https://github.com/ToruNiina/toml11
- https://github.com/mpark/variant
- https://www.svgrepo.com/svg/192268/hammer
- https://github.com/can1357 for buying `cmkr.build` ❤️
+1 -1
View File
@@ -4,7 +4,7 @@ cmkr-include = false
[project]
name = "cmkr"
version = "0.2.9"
version = "0.2.12"
description = "CMakeLists generator from TOML"
languages = ["CXX"]
subdirs = ["third_party", "tests"]
+9 -1
View File
@@ -12,6 +12,14 @@ if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake")
message(FATAL_ERROR "Cannot find cmkr.cmake")
endif()
# Validate branch
find_package(Git REQUIRED)
execute_process(COMMAND "${GIT_EXECUTABLE}" branch --show-current OUTPUT_VARIABLE GIT_BRANCH)
string(STRIP "${GIT_BRANCH}" GIT_BRANCH)
if(NOT GIT_BRANCH STREQUAL "main")
message(FATAL_ERROR "You need to be on the main branch, you are on: ${GIT_BRANCH}")
endif()
file(READ "${CMAKE_SOURCE_DIR}/cmake.toml" CMAKE_TOML)
string(FIND "${CMAKE_TOML}" "[project]" PROJECT_INDEX)
string(SUBSTRING "${CMAKE_TOML}" ${PROJECT_INDEX} -1 CMAKE_TOML_PROJECT)
@@ -38,7 +46,7 @@ endif()
message(STATUS "Version ${OLDVERSION} -> ${NEWVERSION}")
find_program(CMKR_EXECUTABLE "cmkr" PATHS "${CMAKE_SOURCE_DIR}/build" NO_CACHE REQUIRED)
find_program(CMKR_EXECUTABLE "cmkr" PATHS "${CMAKE_SOURCE_DIR}/build" PATH_SUFFIXES Debug Release RelWithDebInfo MinSizeRel NO_CACHE REQUIRED)
message(STATUS "Found cmkr: ${CMKR_EXECUTABLE}")
# Replace version in cmake.toml
+13 -2
View File
@@ -2,7 +2,8 @@ include_guard()
# Change these defaults to point to your infrastructure if desired
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "v0.2.9" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_TAG "v0.2.12" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
if(CMAKE_SCRIPT_MODE_FILE)
@@ -15,7 +16,7 @@ endif()
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration")
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
# Disable cmkr if generation is disabled
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
@@ -115,6 +116,16 @@ else()
${CMKR_REPO}
"${CMKR_DIRECTORY}"
)
if(CMKR_COMMIT_HASH)
execute_process(
COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}"
RESULT_VARIABLE CMKR_EXEC_RESULT
WORKING_DIRECTORY "${CMKR_DIRECTORY}"
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'")
endif()
endif()
message(STATUS "[cmkr] Building cmkr (using system compiler)...")
cmkr_exec("${CMAKE_COMMAND}"
--no-warn-unused-cli
+6
View File
@@ -133,6 +133,7 @@ struct Install {
struct Subdir {
std::string name;
std::string condition;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
ConditionVector include_before;
@@ -143,6 +144,11 @@ struct Content {
std::string name;
std::string condition;
tsl::ordered_map<std::string, std::string> arguments;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
ConditionVector include_before;
ConditionVector include_after;
};
struct Project {
+46 -45
View File
@@ -13,15 +13,6 @@
namespace cmkr {
namespace gen {
static std::string to_upper(const std::string &str) {
std::string temp;
temp.reserve(str.size());
for (auto c : str) {
temp.push_back(::toupper(c));
}
return temp;
}
static std::string format(const char *format, tsl::ordered_map<std::string, std::string> variables) {
std::string s = format;
for (const auto &itr : variables) {
@@ -34,7 +25,7 @@ static std::string format(const char *format, tsl::ordered_map<std::string, std:
return s;
}
static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs::path &toml_dir) {
static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs::path &toml_dir, bool root_project) {
std::vector<std::string> temp;
auto extract_suffix = [](const fs::path &base, const fs::path &full) {
@@ -47,6 +38,10 @@ static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs
auto stem = name.filename().stem().string();
auto ext = name.extension();
if (root_project && stem == "**" && name == name.filename()) {
throw std::runtime_error("Recursive globbing not allowed in project root: " + name.string());
}
if (stem == "*") {
for (const auto &f : fs::directory_iterator(toml_dir / name.parent_path(), fs::directory_options::follow_directory_symlink)) {
if (!f.is_directory() && f.path().extension() == ext) {
@@ -71,11 +66,11 @@ static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs
return temp;
}
static std::vector<std::string> expand_cmake_paths(const std::vector<std::string> &sources, const fs::path &toml_dir) {
static std::vector<std::string> expand_cmake_paths(const std::vector<std::string> &sources, const fs::path &toml_dir, bool root_project) {
// TODO: add duplicate checking
std::vector<std::string> result;
for (const auto &src : sources) {
auto expanded = expand_cmake_path(src, toml_dir);
auto expanded = expand_cmake_path(src, toml_dir, root_project);
for (const auto &f : expanded) {
result.push_back(f);
}
@@ -402,6 +397,14 @@ struct Generator {
}
}
}
void conditional_includes(const parser::ConditionVector &include) {
handle_condition(include, [this](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
}
void conditional_cmake(const parser::Condition<std::string> &cmake) {
handle_condition(cmake, [this](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
}
};
struct ConditionScope {
@@ -476,6 +479,9 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
throw std::runtime_error("No cmake.toml found!");
}
// Root project doesn't have a parent
auto root_project = parent_project == nullptr;
parser::Project project(parent_project, path, false);
Generator gen(project);
@@ -484,16 +490,13 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
auto cmd = [&gen](const std::string &command) { return gen.cmd(command); };
auto comment = [&gen](const std::string &comment) { return gen.comment(comment); };
auto endl = [&gen]() { gen.endl(); };
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 " + cmkr_url + " for more information");
endl();
// Root project doesn't have a parent
if (parent_project == nullptr) {
if (root_project) {
cmd("cmake_minimum_required")("VERSION", project.cmake_version).endl();
if (!project.allow_in_tree) {
@@ -592,8 +595,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
endl();
}
gen.handle_condition(project.include_before, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(project.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(project.include_before);
gen.conditional_cmake(project.cmake_before);
if (!project.project_name.empty()) {
auto languages = std::make_pair("LANGUAGES", project.project_languages);
@@ -602,8 +605,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
cmd("project")(project.project_name, languages, version, description).endl();
}
gen.handle_condition(project.include_after, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(project.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(project.include_after);
gen.conditional_cmake(project.cmake_after);
if (!project.vcpkg.packages.empty()) {
// Allow the user to specify a url or derive it from the version
@@ -704,6 +707,10 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
cmd("include")("FetchContent").endl();
for (const auto &content : project.contents) {
ConditionScope cs(gen, content.condition);
gen.conditional_includes(content.include_before);
gen.conditional_cmake(content.cmake_before);
std::string version_info = "";
if (content.arguments.contains("GIT_TAG")) {
version_info = " (" + content.arguments.at("GIT_TAG") + ")";
@@ -711,12 +718,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
version_info = " (" + content.arguments.at("SVN_REVISION") + ")";
}
cmd("message")("STATUS", "Fetching " + content.name + version_info + "...");
ss << "FetchContent_Declare(\n\t" << content.name << "\n";
for (const auto &arg : content.arguments) {
ss << "\t" << arg.first << "\n\t\t" << arg.second << "\n";
}
ss << ")\n";
cmd("FetchContent_Declare")(content.name, content.arguments);
cmd("FetchContent_MakeAvailable")(content.name).endl();
gen.conditional_includes(content.include_after);
gen.conditional_cmake(content.cmake_after);
}
}
@@ -761,14 +767,13 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
for (const auto &subdir : project.subdirs) {
ConditionScope cs(gen, subdir.condition);
gen.handle_condition(subdir.include_before,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(subdir.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(subdir.include_before);
gen.conditional_cmake(subdir.cmake_before);
add_subdir(subdir.name);
gen.handle_condition(subdir.include_after, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(subdir.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(subdir.include_after);
gen.conditional_cmake(subdir.cmake_after);
}
if (!project.targets.empty()) {
@@ -798,14 +803,12 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
cmd("set")("CMKR_TARGET", target.name);
if (tmplate != nullptr) {
gen.handle_condition(tmplate->outline.include_before,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(tmplate->outline.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(tmplate->outline.include_before);
gen.conditional_cmake(tmplate->outline.cmake_before);
}
gen.handle_condition(target.include_before,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(target.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(target.include_before);
gen.conditional_cmake(target.cmake_before);
auto sources_var = target.name + "_SOURCES";
@@ -814,7 +817,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
if (tmplate != nullptr) {
gen.handle_condition(tmplate->outline.sources, [&](const std::string &condition, const std::vector<std::string> &condition_sources) {
auto sources = expand_cmake_paths(condition_sources, path);
auto sources = expand_cmake_paths(condition_sources, path, root_project);
if (sources.empty()) {
auto source_key = condition.empty() ? "sources" : (condition + ".sources");
throw std::runtime_error(target.name + " " + source_key + " wildcard found 0 files");
@@ -824,7 +827,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
}
gen.handle_condition(target.sources, [&](const std::string &condition, const std::vector<std::string> &condition_sources) {
auto sources = expand_cmake_paths(condition_sources, path);
auto sources = expand_cmake_paths(condition_sources, path, root_project);
if (sources.empty()) {
auto source_key = condition.empty() ? "sources" : (condition + ".sources");
throw std::runtime_error(target.name + " " + source_key + " wildcard found 0 files");
@@ -986,14 +989,12 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
});
}
gen.handle_condition(target.include_after,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(target.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(target.include_after);
gen.conditional_cmake(target.cmake_after);
if (tmplate != nullptr) {
gen.handle_condition(tmplate->outline.include_after,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(tmplate->outline.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.conditional_includes(tmplate->outline.include_after);
gen.conditional_cmake(tmplate->outline.cmake_after);
}
cmd("unset")("CMKR_TARGET");
@@ -1026,7 +1027,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
auto dirs = std::make_pair("DIRS", inst.dirs);
std::vector<std::string> files_data;
if (!inst.files.empty()) {
files_data = expand_cmake_paths(inst.files, path);
files_data = expand_cmake_paths(inst.files, path, root_project);
if (files_data.empty()) {
throw std::runtime_error("[[install]] files wildcard did not resolve to any files");
}
+99 -32
View File
@@ -5,6 +5,7 @@
#include <stdexcept>
#include <toml.hpp>
#include <tsl/ordered_map.h>
#include <tsl/ordered_set.h>
namespace cmkr {
namespace parser {
@@ -49,8 +50,8 @@ static std::string format_key_error(const std::string &error, const toml::key &k
class TomlChecker {
const TomlBasicValue &m_v;
tsl::ordered_map<toml::key, bool> m_visited;
tsl::ordered_map<toml::key, bool> m_conditionVisited;
tsl::ordered_set<toml::key> m_visited;
tsl::ordered_set<toml::key> m_conditionVisited;
public:
TomlChecker(const TomlBasicValue &v, const toml::key &ky) : m_v(toml::find(v, ky)) {}
@@ -77,7 +78,7 @@ class TomlChecker {
// Handle visiting logic
for (const auto &itr : destination) {
if (!itr.first.empty()) {
m_conditionVisited.emplace(itr.first, true);
m_conditionVisited.emplace(itr.first);
}
}
visit(ky);
@@ -108,7 +109,9 @@ class TomlChecker {
return toml::find(m_v, ky);
}
void visit(const toml::key &ky) { m_visited.emplace(ky, true); }
void visit(const toml::key &ky) { m_visited.emplace(ky); }
bool visisted(const toml::key &ky) const { return m_visited.contains(ky); }
void check(const tsl::ordered_map<std::string, std::string> &conditions) const {
for (const auto &itr : m_v.as_table()) {
@@ -143,14 +146,21 @@ class TomlChecker {
};
class TomlCheckerRoot {
const TomlBasicValue &m_root;
std::deque<TomlChecker> m_checkers;
tsl::ordered_set<toml::key> m_visisted;
bool m_checked = false;
public:
TomlCheckerRoot() = default;
TomlCheckerRoot(const TomlBasicValue &root) : m_root(root) {}
TomlCheckerRoot(const TomlCheckerRoot &) = delete;
TomlCheckerRoot(TomlCheckerRoot &&) = delete;
bool contains(const toml::key &ky) {
m_visisted.emplace(ky);
return m_root.contains(ky);
}
TomlChecker &create(const TomlBasicValue &v) {
m_checkers.emplace_back(v);
return m_checkers.back();
@@ -161,7 +171,14 @@ class TomlCheckerRoot {
return m_checkers.back();
}
void check(const tsl::ordered_map<std::string, std::string> &conditions) {
void check(const tsl::ordered_map<std::string, std::string> &conditions, bool check_root) {
if (check_root) {
for (const auto &itr : m_root.as_table()) {
if (!m_visisted.contains(itr.first)) {
throw std::runtime_error(format_key_error("Unknown key '" + itr.first + "'", itr.first, itr.second));
}
}
}
for (const auto &checker : m_checkers) {
checker.check(conditions);
}
@@ -171,13 +188,16 @@ class TomlCheckerRoot {
Project::Project(const Project *parent, const std::string &path, bool build) {
const auto toml_path = fs::path(path) / "cmake.toml";
if (!fs::exists(toml_path)) {
throw std::runtime_error("No cmake.toml was found!");
throw std::runtime_error("File not found '" + toml_path.string() + "'");
}
const auto toml = toml::parse<toml::discard_comments, tsl::ordered_map, std::vector>(toml_path.string());
if (toml.size() == 0) {
throw std::runtime_error("Empty TOML '" + toml_path.string() + "'");
}
TomlCheckerRoot checker;
TomlCheckerRoot checker(toml);
if (toml.contains("cmake")) {
if (checker.contains("cmake")) {
auto &cmake = checker.create(toml, "cmake");
cmake.required("version", cmake_version);
@@ -209,7 +229,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
// Skip the rest of the parsing when building
if (build) {
checker.check(conditions);
checker.check(conditions, false);
return;
}
@@ -231,14 +251,14 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
templates = parent->templates;
}
if (toml.contains("conditions")) {
if (checker.contains("conditions")) {
auto conds = toml::find<decltype(conditions)>(toml, "conditions");
for (const auto &cond : conds) {
conditions[cond.first] = cond.second;
}
}
if (toml.contains("project")) {
if (checker.contains("project")) {
auto &project = checker.create(toml, "project");
project.required("name", project_name);
project.optional("version", project_version);
@@ -251,7 +271,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
project.optional("subdirs", project_subdirs);
}
if (toml.contains("subdir")) {
if (checker.contains("subdir")) {
const auto &subs = toml::find(toml, "subdir").as_table();
for (const auto &itr : subs) {
Subdir subdir;
@@ -268,7 +288,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("settings")) {
if (checker.contains("settings")) {
using set_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &sets = toml::find<set_map>(toml, "settings");
for (const auto &itr : sets) {
@@ -297,7 +317,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("options")) {
if (checker.contains("options")) {
using opts_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &opts = toml::find<opts_map>(toml, "options");
for (const auto &itr : opts) {
@@ -315,7 +335,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("find-package")) {
if (checker.contains("find-package")) {
using pkg_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &pkgs = toml::find<pkg_map>(toml, "find-package");
for (const auto &itr : pkgs) {
@@ -336,41 +356,88 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
// TODO: perform checking here
if (toml.contains("fetch-content")) {
if (checker.contains("fetch-content")) {
const auto &fc = toml::find(toml, "fetch-content").as_table();
for (const auto &itr : fc) {
Content content;
content.name = itr.first;
auto &c = checker.create(itr.second);
c.optional("condition", content.condition);
c.optional("cmake-before", content.cmake_before);
c.optional("cmake-after", content.cmake_after);
c.optional("include-before", content.include_before);
c.optional("include-after", content.include_after);
for (const auto &argItr : itr.second.as_table()) {
auto key = argItr.first;
if (key == "condition") {
content.condition = argItr.second.as_string();
continue;
std::string value;
if (argItr.second.is_array()) {
for (const auto &list_val : argItr.second.as_array()) {
if (!value.empty()) {
value += ';';
}
value += list_val.as_string();
}
} else if (argItr.second.is_boolean()) {
value = argItr.second.as_boolean() ? "ON" : "OFF";
} else {
value = argItr.second.as_string();
}
auto is_cmake_arg = [](const std::string &s) {
for (auto c : s) {
if (!(std::isdigit(c) || std::isupper(c) || c == '_')) {
return false;
}
}
return true;
};
// https://cmake.org/cmake/help/latest/command/string.html#supported-hash-algorithms
tsl::ordered_set<std::string> hash_algorithms = {
"md5", "sha1", "sha224", "sha256", "sha384", "sha512", "sha3_224", "sha3_256", "sha3_384", "sha3_512",
};
auto key = argItr.first;
if (key == "git") {
key = "GIT_REPOSITORY";
} else if (key == "tag") {
key = "GIT_TAG";
} else if (key == "shallow") {
key = "GIT_SHALLOW";
} else if (key == "svn") {
key = "SVN_REPOSITORY";
} else if (key == "rev") {
key = "SVN_REVISION";
} else if (key == "url") {
key = "URL";
} else if (hash_algorithms.contains(key)) {
std::string algo;
for (auto c : key) {
algo.push_back(std::toupper(c));
}
key = "URL_HASH";
value = algo + "=" + value;
} else if (key == "hash") {
key = "URL_HASH";
} else {
// don't change arg
} else if (is_cmake_arg(key)) {
// allow passthrough of ExternalProject options
} else if (!c.visisted(key)) {
throw std::runtime_error(format_key_error("Unknown key '" + argItr.first + "'", argItr.first, argItr.second));
}
content.arguments.emplace(key, argItr.second.as_string());
// Make sure not to emit keys like "condition" in the FetchContent call
if (!c.visisted(key)) {
content.arguments.emplace(key, value);
}
c.visit(argItr.first);
}
contents.emplace_back(std::move(content));
}
}
if (toml.contains("bin")) {
if (checker.contains("bin")) {
throw std::runtime_error("[[bin]] has been renamed to [[target]]");
}
@@ -489,7 +556,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
return target;
};
if (toml.contains("template")) {
if (checker.contains("template")) {
const auto &ts = toml::find(toml, "template").as_table();
for (const auto &itr : ts) {
auto &t = checker.create(itr.second);
@@ -517,7 +584,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("target")) {
if (checker.contains("target")) {
const auto &ts = toml::find(toml, "target").as_table();
for (const auto &itr : ts) {
auto &t = checker.create(itr.second);
@@ -525,7 +592,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("test")) {
if (checker.contains("test")) {
const auto &ts = toml::find(toml, "test").as_array();
for (const auto &value : ts) {
auto &t = checker.create(value);
@@ -540,7 +607,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("install")) {
if (checker.contains("install")) {
const auto &is = toml::find(toml, "install").as_array();
for (const auto &value : is) {
auto &i = checker.create(value);
@@ -556,7 +623,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
if (toml.contains("vcpkg")) {
if (checker.contains("vcpkg")) {
auto &v = checker.create(toml, "vcpkg");
v.optional("url", vcpkg.url);
v.optional("version", vcpkg.version);
@@ -582,7 +649,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
checker.check(conditions);
checker.check(conditions, true);
}
bool is_root_path(const std::string &path) {