[M6] manifest: add dev_dependencies and [build].include_dirs

This commit is contained in:
2026-05-13 23:53:23 +00:00
parent 654fd8d245
commit 1e6667a20a
6 changed files with 124 additions and 25 deletions

View File

@@ -16,6 +16,7 @@ struct Dependency {
struct BuildSettings {
bool warnings_as_errors = false;
std::vector<std::string> sanitizers;
std::vector<std::string> include_dirs;
bool operator==(const BuildSettings&) const = default;
};
@@ -35,6 +36,7 @@ struct Package {
struct Manifest {
Package package;
std::vector<Dependency> dependencies;
std::vector<Dependency> dev_dependencies;
BuildSettings build;
bool operator==(const Manifest&) const = default;

View File

@@ -76,13 +76,12 @@ constexpr std::array PACKAGE_KNOWN_KEYS = {
};
constexpr std::array BUILD_KNOWN_KEYS = {
"warnings_as_errors", "sanitizers",
"warnings_as_errors", "sanitizers", "include_dirs",
};
constexpr std::array TOPLEVEL_KNOWN_KEYS = {
"package", "dependencies", "build",
// reserved (accepted, ignored for v0.1)
"dev-dependencies", "features", "workspace",
"package", "dependencies", "dev-dependencies", "build",
"features", "workspace",
};
auto parse_package(const toml::table& tbl, const std::filesystem::path& path)
@@ -218,6 +217,24 @@ auto parse_build(const toml::table& tbl, const std::filesystem::path& path)
b.sanitizers = std::move(*r);
}
if (const auto* inc = tbl["include_dirs"].as_array()) {
auto r = extract_string_array(*inc, "[build].include_dirs", path);
if (!r) {
return std::unexpected(r.error());
}
for (const auto& p : *r) {
if (p.empty() || p.starts_with('/') || p.find("..") != std::string::npos) {
return std::unexpected(err(
ErrorCode::ManifestInvalidField,
std::format("[build].include_dirs entry '{}' must be a "
"relative path that does not contain '..'",
p),
path));
}
}
b.include_dirs = std::move(*r);
}
return b;
}
@@ -271,6 +288,14 @@ auto parse(const std::filesystem::path& path) -> util::Result<Manifest> {
m.dependencies = std::move(*deps);
}
if (const auto* dev_tbl = root["dev-dependencies"].as_table()) {
auto deps = parse_dependencies(*dev_tbl, path);
if (!deps) {
return std::unexpected(deps.error());
}
m.dev_dependencies = std::move(*deps);
}
if (const auto* build_tbl = root["build"].as_table()) {
auto build = parse_build(*build_tbl, path);
if (!build) {

View File

@@ -46,23 +46,32 @@ auto build_table(const Manifest& m) -> toml::table {
}
root.insert_or_assign("package", std::move(package));
if (!m.dependencies.empty()) {
toml::table deps;
for (const auto& dep : m.dependencies) {
auto deps_to_table = [](const std::vector<Dependency>& deps) {
toml::table out;
for (const auto& dep : deps) {
if (dep.components.empty()) {
deps.insert_or_assign(dep.name, dep.version_spec);
out.insert_or_assign(dep.name, dep.version_spec);
} else {
toml::table dep_tbl;
dep_tbl.insert_or_assign("version", dep.version_spec);
dep_tbl.insert_or_assign("components", to_array(dep.components));
dep_tbl.is_inline(true);
deps.insert_or_assign(dep.name, std::move(dep_tbl));
out.insert_or_assign(dep.name, std::move(dep_tbl));
}
}
root.insert_or_assign("dependencies", std::move(deps));
return out;
};
if (!m.dependencies.empty()) {
root.insert_or_assign("dependencies", deps_to_table(m.dependencies));
}
if (m.build.warnings_as_errors || !m.build.sanitizers.empty()) {
if (!m.dev_dependencies.empty()) {
root.insert_or_assign("dev-dependencies", deps_to_table(m.dev_dependencies));
}
if (m.build.warnings_as_errors || !m.build.sanitizers.empty()
|| !m.build.include_dirs.empty()) {
toml::table build;
if (m.build.warnings_as_errors) {
build.insert_or_assign("warnings_as_errors", true);
@@ -70,6 +79,9 @@ auto build_table(const Manifest& m) -> toml::table {
if (!m.build.sanitizers.empty()) {
build.insert_or_assign("sanitizers", to_array(m.build.sanitizers));
}
if (!m.build.include_dirs.empty()) {
build.insert_or_assign("include_dirs", to_array(m.build.include_dirs));
}
root.insert_or_assign("build", std::move(build));
}