[M3] add codegen::flake_nix
This commit is contained in:
@@ -1,7 +1,24 @@
|
||||
export module cargoxx.codegen;
|
||||
|
||||
import std;
|
||||
import cargoxx.util;
|
||||
import cargoxx.manifest;
|
||||
import cargoxx.lockfile;
|
||||
import cargoxx.layout;
|
||||
import cargoxx.linkdb;
|
||||
import cargoxx.lockfile;
|
||||
|
||||
export namespace cargoxx::codegen {
|
||||
|
||||
// All inputs the generators need. Held by const reference; the caller owns
|
||||
// the underlying objects. Not copyable.
|
||||
struct GenerateInputs {
|
||||
const manifest::Manifest& manifest;
|
||||
const layout::DiscoveredLayout& layout;
|
||||
const lockfile::Lockfile& lock;
|
||||
std::vector<linkdb::Recipe> recipes; // one per manifest dep, same order
|
||||
std::filesystem::path project_root;
|
||||
};
|
||||
|
||||
auto flake_nix(const GenerateInputs& in) -> std::string;
|
||||
|
||||
} // namespace cargoxx::codegen
|
||||
|
||||
108
src/codegen/flake.cpp
Normal file
108
src/codegen/flake.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
module cargoxx.codegen;
|
||||
|
||||
import std;
|
||||
import cargoxx.manifest;
|
||||
import cargoxx.linkdb;
|
||||
import cargoxx.lockfile;
|
||||
|
||||
namespace cargoxx::codegen {
|
||||
|
||||
namespace {
|
||||
|
||||
// SPEC.md §7 plus a `buildInputs` slot for resolved dep attrs (TECH_SPEC §10).
|
||||
// `${...}` in the env.NIX_CFLAGS_COMPILE block is literal Nix, not a marker —
|
||||
// our markers use the @@MARKER@@ form.
|
||||
constexpr std::string_view FLAKE_TEMPLATE = R"({
|
||||
description = "@@DESCRIPTION@@";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/@@NIXPKGS_REV@@";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
llvmPkgs = pkgs.llvmPackages;
|
||||
in {
|
||||
devShell = llvmPkgs.libcxxStdenv.mkDerivation {
|
||||
name = "shell";
|
||||
version = "1.0";
|
||||
nativeBuildInputs = [
|
||||
pkgs.ninja
|
||||
pkgs.cmake
|
||||
pkgs.clang-tools
|
||||
];
|
||||
buildInputs = [
|
||||
@@DEP_LINES@@ ];
|
||||
env.NIX_CFLAGS_COMPILE = toString [
|
||||
"-stdlib=libc++"
|
||||
"-Wno-unused-command-line-argument"
|
||||
"-B${pkgs.lib.getLib pkgs.libcxx}/lib"
|
||||
"-isystem ${pkgs.lib.getDev pkgs.libcxx}/include/c++/v1"
|
||||
];
|
||||
hardeningDisable = [
|
||||
"all"
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
||||
)";
|
||||
|
||||
auto substitute(std::string_view tmpl, std::string_view marker, std::string_view value)
|
||||
-> std::string {
|
||||
std::string out;
|
||||
out.reserve(tmpl.size());
|
||||
std::size_t pos = 0;
|
||||
while (pos < tmpl.size()) {
|
||||
auto next = tmpl.find(marker, pos);
|
||||
if (next == std::string_view::npos) {
|
||||
out.append(tmpl.substr(pos));
|
||||
break;
|
||||
}
|
||||
out.append(tmpl.substr(pos, next - pos));
|
||||
out.append(value);
|
||||
pos = next + marker.size();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
auto stable_dedup(const std::vector<std::string>& xs) -> std::vector<std::string> {
|
||||
std::vector<std::string> out;
|
||||
std::set<std::string> seen;
|
||||
for (const auto& x : xs) {
|
||||
if (seen.insert(x).second) {
|
||||
out.push_back(x);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto flake_nix(const GenerateInputs& in) -> std::string {
|
||||
auto rev = in.lock.nixpkgs_rev().value_or("nixos-unstable");
|
||||
|
||||
std::vector<std::string> attrs;
|
||||
attrs.reserve(in.recipes.size());
|
||||
for (const auto& r : in.recipes) {
|
||||
attrs.push_back(r.nixpkgs_attr);
|
||||
}
|
||||
auto deduped = stable_dedup(attrs);
|
||||
|
||||
std::string dep_lines;
|
||||
for (const auto& a : deduped) {
|
||||
dep_lines += " pkgs.";
|
||||
dep_lines += a;
|
||||
dep_lines += '\n';
|
||||
}
|
||||
|
||||
auto out = std::string{FLAKE_TEMPLATE};
|
||||
out = substitute(out, "@@DESCRIPTION@@", in.manifest.package.name);
|
||||
out = substitute(out, "@@NIXPKGS_REV@@", rev);
|
||||
out = substitute(out, "@@DEP_LINES@@", dep_lines);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace cargoxx::codegen
|
||||
Reference in New Issue
Block a user