[M7] lockfile carries full recipe (find_package, targets, pkg_config_module, brute_force_*)

This commit is contained in:
2026-05-15 23:05:40 +00:00
parent 815e5b1be2
commit f62cff49c6
4 changed files with 147 additions and 8 deletions

View File

@@ -92,6 +92,11 @@ auto merge_lockfile(const manifest::Manifest& m,
.nixpkgs_attr = std::move(attr),
.nixpkgs_rev = std::move(rev),
.linkdb_source = rec.source,
.find_package = rec.find_package,
.targets = rec.targets,
.pkg_config_module = rec.pkg_config_module,
.brute_force_libs = rec.brute_force_libs,
.brute_force_includes = rec.brute_force_includes,
});
};
for (std::size_t i = 0; i < m.dependencies.size(); ++i) {
@@ -176,11 +181,45 @@ auto cmd_build(const fs::path& project_root, bool no_build, bool release,
return {};
};
lockfile::Lockfile prior;
if (std::error_code ec; std::filesystem::exists(project_root / "Cargoxx.lock", ec)) {
if (auto r = lockfile::parse(project_root / "Cargoxx.lock"); r) {
prior = std::move(*r);
}
}
auto recipe_from_lock = [&](const std::string& name, const std::string& version)
-> std::optional<linkdb::Recipe> {
for (const auto& p : prior.packages) {
if (p.name != name || p.version != version) {
continue;
}
if (!p.find_package || p.targets.empty()) {
if (p.brute_force_libs.empty() && p.brute_force_includes.empty()) {
return std::nullopt;
}
}
return linkdb::Recipe{
.nixpkgs_attr = p.nixpkgs_attr.value_or(""),
.find_package = p.find_package.value_or(""),
.targets = p.targets,
.source = p.linkdb_source.value_or(""),
.pkg_config_module = p.pkg_config_module,
.brute_force_libs = p.brute_force_libs,
.brute_force_includes = p.brute_force_includes,
};
}
return std::nullopt;
};
auto resolve_list = [&](const std::vector<manifest::Dependency>& deps)
-> util::Result<std::vector<linkdb::Recipe>> {
std::vector<linkdb::Recipe> out;
out.reserve(deps.size());
for (const auto& dep : deps) {
if (auto cached = recipe_from_lock(dep.name, dep.version_spec); cached) {
out.push_back(std::move(*cached));
continue;
}
auto r = db->resolve(dep.name, dep.version_spec, dep.components);
if (!r && r.error().code == util::ErrorCode::LinkdbUnknownPackage) {
if (auto resolved = auto_resolve(dep.name, dep.version_spec,
@@ -205,13 +244,6 @@ auto cmd_build(const fs::path& project_root, bool no_build, bool release,
if (!dev_recipes) {
return std::unexpected(dev_recipes.error());
}
lockfile::Lockfile prior;
if (std::error_code ec; std::filesystem::exists(project_root / "Cargoxx.lock", ec)) {
if (auto r = lockfile::parse(project_root / "Cargoxx.lock"); r) {
prior = std::move(*r);
}
}
auto lock = merge_lockfile(*m, *recipes, *dev_recipes, prior);
codegen::GenerateInputs in{

View File

@@ -79,6 +79,33 @@ auto parse_package(const toml::table& tbl, const std::filesystem::path& path)
if (auto v = tbl["linkdb_source"].value<std::string>()) {
pkg.linkdb_source = *v;
}
if (auto v = tbl["find_package"].value<std::string>()) {
pkg.find_package = *v;
}
if (const auto* arr = tbl["targets"].as_array()) {
auto r = extract_string_array(*arr, "targets", path);
if (!r) {
return std::unexpected(r.error());
}
pkg.targets = std::move(*r);
}
if (auto v = tbl["pkg_config_module"].value<std::string>()) {
pkg.pkg_config_module = *v;
}
if (const auto* arr = tbl["brute_force_libs"].as_array()) {
auto r = extract_string_array(*arr, "brute_force_libs", path);
if (!r) {
return std::unexpected(r.error());
}
pkg.brute_force_libs = std::move(*r);
}
if (const auto* arr = tbl["brute_force_includes"].as_array()) {
auto r = extract_string_array(*arr, "brute_force_includes", path);
if (!r) {
return std::unexpected(r.error());
}
pkg.brute_force_includes = std::move(*r);
}
return pkg;
}
@@ -149,6 +176,33 @@ auto write(const Lockfile& lock, const std::filesystem::path& path) -> util::Res
if (p.linkdb_source) {
tbl.insert_or_assign("linkdb_source", *p.linkdb_source);
}
if (p.find_package) {
tbl.insert_or_assign("find_package", *p.find_package);
}
if (!p.targets.empty()) {
toml::array arr;
for (const auto& t : p.targets) {
arr.push_back(t);
}
tbl.insert_or_assign("targets", std::move(arr));
}
if (p.pkg_config_module) {
tbl.insert_or_assign("pkg_config_module", *p.pkg_config_module);
}
if (!p.brute_force_libs.empty()) {
toml::array arr;
for (const auto& l : p.brute_force_libs) {
arr.push_back(l);
}
tbl.insert_or_assign("brute_force_libs", std::move(arr));
}
if (!p.brute_force_includes.empty()) {
toml::array arr;
for (const auto& i : p.brute_force_includes) {
arr.push_back(i);
}
tbl.insert_or_assign("brute_force_includes", std::move(arr));
}
packages.push_back(std::move(tbl));
}
root.insert_or_assign("package", std::move(packages));

View File

@@ -9,10 +9,15 @@ export namespace cargoxx::lockfile {
struct LockfilePackage {
std::string name;
std::string version;
std::vector<std::string> dependencies; // "<name> <version>" entries; non-empty for the root
std::vector<std::string> dependencies;
std::optional<std::string> nixpkgs_attr;
std::optional<std::string> nixpkgs_rev;
std::optional<std::string> linkdb_source;
std::optional<std::string> find_package;
std::vector<std::string> targets;
std::optional<std::string> pkg_config_module;
std::vector<std::string> brute_force_libs;
std::vector<std::string> brute_force_includes;
bool operator==(const LockfilePackage&) const = default;
};

View File

@@ -70,6 +70,54 @@ TEST_CASE("write round-trips a lockfile with deps", "[lockfile]") {
REQUIRE(round_trip(l) == l);
}
TEST_CASE("write round-trips lockfile recipe fields", "[lockfile]") {
Lockfile l{
1,
{
LockfilePackage{
.name = "fmt",
.version = "10.2.1",
.dependencies = {},
.nixpkgs_attr = "fmt_10",
.nixpkgs_rev = std::nullopt,
.linkdb_source = "conan",
.find_package = "fmt CONFIG REQUIRED",
.targets = {"fmt::fmt"},
.pkg_config_module = std::nullopt,
.brute_force_libs = {},
.brute_force_includes = {},
},
LockfilePackage{
.name = "sqlite",
.version = "*",
.dependencies = {},
.nixpkgs_attr = "sqlite",
.nixpkgs_rev = std::nullopt,
.linkdb_source = "pkg-config",
.find_package = "PkgConfig REQUIRED",
.targets = {"PkgConfig::SQLITE3"},
.pkg_config_module = "sqlite3",
.brute_force_libs = {},
.brute_force_includes = {},
},
LockfilePackage{
.name = "obscure",
.version = "*",
.dependencies = {},
.nixpkgs_attr = "obscure",
.nixpkgs_rev = std::nullopt,
.linkdb_source = "brute-force",
.find_package = "",
.targets = {"obscure::obscure"},
.pkg_config_module = std::nullopt,
.brute_force_libs = {"/nix/store/abc/lib/libobscure.a"},
.brute_force_includes = {"/nix/store/abc/include"},
},
},
};
REQUIRE(round_trip(l) == l);
}
TEST_CASE("Lockfile::nixpkgs_rev returns the shared rev", "[lockfile]") {
Lockfile l{
1,