Improved fetch-content support

Closes #38
main
Duncan Ogilvie 2 years ago
parent 06a4c04df6
commit 85370968f8

@ -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 {

@ -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) {
@ -710,6 +701,11 @@ 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.handle_condition(content.include_before,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(content.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
std::string version_info = "";
if (content.arguments.contains("GIT_TAG")) {
version_info = " (" + content.arguments.at("GIT_TAG") + ")";
@ -723,6 +719,10 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
}
ss << ")\n";
cmd("FetchContent_MakeAvailable")(content.name).endl();
gen.handle_condition(content.include_after,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(content.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
}
}

@ -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()) {
@ -145,7 +148,7 @@ class TomlChecker {
class TomlCheckerRoot {
const TomlBasicValue &m_root;
std::deque<TomlChecker> m_checkers;
tsl::ordered_map<toml::key, bool> m_visisted;
tsl::ordered_set<toml::key> m_visisted;
bool m_checked = false;
public:
@ -154,7 +157,7 @@ class TomlCheckerRoot {
TomlCheckerRoot(TomlCheckerRoot &&) = delete;
bool contains(const toml::key &ky) {
m_visisted[ky] = true;
m_visisted.emplace(ky);
return m_root.contains(ky);
}
@ -353,19 +356,49 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
}
}
// TODO: perform checking here
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") {
@ -378,18 +411,23 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
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));
}
std::string value;
if (argItr.second.is_boolean()) {
value = argItr.second.as_boolean() ? "ON" : "OFF";
} else {
value = argItr.second.as_string();
}
c.visit(argItr.first);
content.arguments.emplace(key, value);
}
contents.emplace_back(std::move(content));

Loading…
Cancel
Save