[M6] codegen: dev_recipes, [build].include_dirs, baseline warnings, catch_discover_tests
This commit is contained in:
@@ -168,7 +168,14 @@ auto cmd_build(const fs::path& project_root, bool no_build, bool release,
|
||||
}
|
||||
auto lock = merge_lockfile(*m, recipes, prior);
|
||||
|
||||
codegen::GenerateInputs in{*m, *layout_result, lock, recipes, project_root};
|
||||
codegen::GenerateInputs in{
|
||||
.manifest = *m,
|
||||
.layout = *layout_result,
|
||||
.lock = lock,
|
||||
.recipes = recipes,
|
||||
.dev_recipes = {},
|
||||
.project_root = project_root,
|
||||
};
|
||||
auto flake_text = codegen::flake_nix(in);
|
||||
auto cmake_text = codegen::cmake_lists(in);
|
||||
|
||||
|
||||
@@ -60,8 +60,6 @@ auto emit_header(const manifest::Manifest& m) -> std::string {
|
||||
return std::format(
|
||||
"cmake_minimum_required(VERSION 3.30)\n"
|
||||
"\n"
|
||||
"# Opt into experimental C++ modules dyndep + `import std;` support.\n"
|
||||
"# Required until CMake declares these stable.\n"
|
||||
"set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)\n"
|
||||
"set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD \"d0edc3af-4c50-42ea-a356-e2862fe7a444\")\n"
|
||||
"set(CMAKE_CXX_MODULE_STD ON)\n"
|
||||
@@ -71,29 +69,43 @@ auto emit_header(const manifest::Manifest& m) -> std::string {
|
||||
"# Generated by cargoxx — do not edit.\n"
|
||||
"# Source of truth: ../Cargoxx.toml\n"
|
||||
"\n"
|
||||
"# ----- toolchain configuration -----\n"
|
||||
"set(CMAKE_CXX_STANDARD {})\n"
|
||||
"set(CMAKE_CXX_STANDARD_REQUIRED ON)\n"
|
||||
"# EXTENSIONS=ON for libc++ std-module compatibility (clang 21).\n"
|
||||
"set(CMAKE_CXX_EXTENSIONS ON)\n"
|
||||
"set(CMAKE_CXX_SCAN_FOR_MODULES ON)\n"
|
||||
"set(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n",
|
||||
"set(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n"
|
||||
"\n"
|
||||
"add_compile_options(-Wall -Wextra -Wpedantic -Wconversion)\n",
|
||||
m.package.name, edition_to_int(m.package.edition));
|
||||
}
|
||||
|
||||
auto emit_find_packages(const std::vector<linkdb::Recipe>& recipes) -> std::string {
|
||||
if (recipes.empty()) {
|
||||
auto emit_find_packages(const std::vector<linkdb::Recipe>& recipes,
|
||||
const std::vector<linkdb::Recipe>& dev_recipes)
|
||||
-> std::string {
|
||||
if (recipes.empty() && dev_recipes.empty()) {
|
||||
return {};
|
||||
}
|
||||
std::string out = "\n# ----- dependencies -----\n";
|
||||
for (const auto& r : recipes) {
|
||||
out += std::format("find_package({})\n", r.find_package);
|
||||
}
|
||||
for (const auto& r : dev_recipes) {
|
||||
out += std::format("find_package({})\n", r.find_package);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
auto recipe_is_catch2(const linkdb::Recipe& r) -> bool {
|
||||
return r.find_package.starts_with("Catch2 ");
|
||||
}
|
||||
|
||||
auto any_recipe_is_catch2(const std::vector<linkdb::Recipe>& dev_recipes) -> bool {
|
||||
return std::ranges::any_of(dev_recipes, recipe_is_catch2);
|
||||
}
|
||||
|
||||
auto emit_library(const layout::Target& lib, const std::string& package_name,
|
||||
const std::vector<linkdb::Recipe>& recipes,
|
||||
const std::vector<std::string>& include_dirs,
|
||||
const fs::path& project_root) -> std::string {
|
||||
std::string out = "\n# ----- library target -----\n";
|
||||
out += std::format("add_library({} STATIC)\n", package_name);
|
||||
@@ -110,6 +122,13 @@ auto emit_library(const layout::Target& lib, const std::string& package_name,
|
||||
}
|
||||
}
|
||||
out += ")\n";
|
||||
if (!include_dirs.empty()) {
|
||||
out += std::format("target_include_directories({} SYSTEM PRIVATE", package_name);
|
||||
for (const auto& d : include_dirs) {
|
||||
out += std::format(" ../{}", d);
|
||||
}
|
||||
out += ")\n";
|
||||
}
|
||||
out += link_block(package_name, "PUBLIC", false, package_name,
|
||||
collect_dep_targets(recipes));
|
||||
return out;
|
||||
@@ -140,14 +159,22 @@ auto emit_extra_binary(const layout::Target& bin, const std::string& package_nam
|
||||
}
|
||||
|
||||
auto emit_test(const layout::Target& t, const std::string& package_name,
|
||||
const std::vector<linkdb::Recipe>& recipes, bool has_lib,
|
||||
const fs::path& project_root) -> std::string {
|
||||
const std::vector<linkdb::Recipe>& recipes,
|
||||
const std::vector<linkdb::Recipe>& dev_recipes, bool has_lib,
|
||||
bool use_catch_discover, const fs::path& project_root) -> std::string {
|
||||
auto target = std::format("test_{}", t.name);
|
||||
std::string out = std::format("add_executable({} {})\n", target,
|
||||
rel_to_build(t.entry, project_root));
|
||||
out += link_block(target, "PRIVATE", has_lib, package_name,
|
||||
collect_dep_targets(recipes));
|
||||
out += std::format("add_test(NAME {} COMMAND {})\n", t.name, target);
|
||||
std::vector<std::string> link_targets = collect_dep_targets(recipes);
|
||||
for (const auto& dt : collect_dep_targets(dev_recipes)) {
|
||||
link_targets.push_back(dt);
|
||||
}
|
||||
out += link_block(target, "PRIVATE", has_lib, package_name, link_targets);
|
||||
if (use_catch_discover) {
|
||||
out += std::format("catch_discover_tests({})\n", target);
|
||||
} else {
|
||||
out += std::format("add_test(NAME {} COMMAND {})\n", t.name, target);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -250,13 +277,15 @@ auto emit_build_flags(const manifest::BuildSettings& build,
|
||||
auto cmake_lists(const GenerateInputs& in) -> std::string {
|
||||
const auto& pkg_name = in.manifest.package.name;
|
||||
const bool has_lib = in.layout.library.has_value();
|
||||
const bool use_catch_discover = any_recipe_is_catch2(in.dev_recipes);
|
||||
|
||||
std::string out;
|
||||
out += emit_header(in.manifest);
|
||||
out += emit_find_packages(in.recipes);
|
||||
out += emit_find_packages(in.recipes, in.dev_recipes);
|
||||
|
||||
if (in.layout.library) {
|
||||
out += emit_library(*in.layout.library, pkg_name, in.recipes, in.project_root);
|
||||
out += emit_library(*in.layout.library, pkg_name, in.recipes,
|
||||
in.manifest.build.include_dirs, in.project_root);
|
||||
}
|
||||
|
||||
const auto* primary = find_primary_bin(in.layout);
|
||||
@@ -277,8 +306,12 @@ auto cmake_lists(const GenerateInputs& in) -> std::string {
|
||||
|
||||
if (!in.layout.tests.empty()) {
|
||||
out += "\n# ----- tests -----\nenable_testing()\n";
|
||||
if (use_catch_discover) {
|
||||
out += "include(Catch)\n";
|
||||
}
|
||||
for (const auto& t : in.layout.tests) {
|
||||
out += emit_test(t, pkg_name, in.recipes, has_lib, in.project_root);
|
||||
out += emit_test(t, pkg_name, in.recipes, in.dev_recipes, has_lib,
|
||||
use_catch_discover, in.project_root);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ struct GenerateInputs {
|
||||
const layout::DiscoveredLayout& layout;
|
||||
const lockfile::Lockfile& lock;
|
||||
std::vector<linkdb::Recipe> recipes; // one per manifest dep, same order
|
||||
std::vector<linkdb::Recipe> dev_recipes; // one per dev_dependency, same order
|
||||
std::filesystem::path project_root;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user