From 5f0c55ac416e6c2d605ef10a6165609e77fe970e Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Mon, 4 Aug 2025 19:57:57 -0700 Subject: [PATCH 1/3] feat: supporting defines in build recipes --- ecsact/cli/commands/build/build_recipe.cc | 79 ++++++++++++++++++----- ecsact/cli/commands/build/build_recipe.hh | 4 ++ ecsact/cli/commands/build/recipe/cook.cc | 61 +++++++++++------ test/build_recipe/ecsact_build_test.cc | 15 ++++- test/build_recipe/test-recipe.yml | 4 ++ 5 files changed, 128 insertions(+), 35 deletions(-) diff --git a/ecsact/cli/commands/build/build_recipe.cc b/ecsact/cli/commands/build/build_recipe.cc index cbf1115..f114a36 100644 --- a/ecsact/cli/commands/build/build_recipe.cc +++ b/ecsact/cli/commands/build/build_recipe.cc @@ -119,6 +119,11 @@ auto ecsact::build_recipe::system_libs() const -> std::span { return _system_libs; } +auto ecsact::build_recipe::defines() const + -> std::unordered_map { + return _defines; +} + static auto get_if_error( // const auto& result ) -> std::optional { @@ -166,6 +171,19 @@ static auto parse_system_libs( // return system_libs.as>(); } +static auto parse_defines( // + YAML::Node defines +) + -> std::variant< + std::unordered_map, + ecsact::build_recipe_parse_error> { + if(!defines) { + return {}; + } + + return defines.as>(); +} + static auto parse_sources( // fs::path recipe_path, YAML::Node sources @@ -225,13 +243,15 @@ static auto parse_sources( // if(src["outdir"]) { outdir = src["outdir"].as(); } - result.emplace_back(source_fetch{ - .url = fetch.as(), - .integrity = integrity, - .strip_prefix = strip_prefix, - .outdir = outdir, - .paths = paths, - }); + result.emplace_back( + source_fetch{ + .url = fetch.as(), + .integrity = integrity, + .strip_prefix = strip_prefix, + .outdir = outdir, + .paths = paths, + } + ); } else if(path) { auto src_path = fs::path{path.as()}; auto outdir = std::optional{}; @@ -248,17 +268,21 @@ static auto parse_sources( // src_path = src_path.lexically_normal(); } - result.emplace_back(source_path{ - .path = src_path, - .outdir = outdir, - }); + result.emplace_back( + source_path{ + .path = src_path, + .outdir = outdir, + } + ); } } else if(src.IsScalar()) { auto path = fs::path{src.as()}.lexically_normal(); - result.emplace_back(source_path{ - .path = path, - .outdir = ".", - }); + result.emplace_back( + source_path{ + .path = path, + .outdir = ".", + } + ); } } @@ -293,6 +317,11 @@ auto ecsact::build_recipe::build_recipe_from_yaml_node( // return *err; } + auto defines = parse_defines(doc["defines"]); + if(auto err = get_if_error(defines)) { + return *err; + } + auto recipe = ecsact::build_recipe{}; if(doc["name"]) { recipe._name = doc["name"].as(); @@ -304,6 +333,7 @@ auto ecsact::build_recipe::build_recipe_from_yaml_node( // recipe._imports = get_value(imports); recipe._sources = get_value(sources); recipe._system_libs = get_value(system_libs); + recipe._defines = get_value(defines); if(recipe._exports.empty()) { return build_recipe_parse_error::missing_exports; @@ -370,6 +400,13 @@ auto ecsact::build_recipe::to_yaml_string() const -> std::string { emitter << YAML::Key << "system_libs"; emitter << YAML::Value << _system_libs; + emitter << YAML::Key << "defines"; + emitter << YAML::Value << YAML::BeginMap; + for(auto&& [key, value] : _defines) { + emitter << YAML::Key << key << YAML::Value << value; + } + emitter << YAML::EndMap; + emitter << YAML::Key << "sources"; emitter << YAML::Value << _sources; @@ -423,6 +460,18 @@ auto ecsact::build_recipe::merge( // target._system_libs.end() ); + merged_build_recipe._defines.reserve( + merged_build_recipe._defines.size() + target._defines.size() + ); + + for(auto&& [k, v] : base._defines) { + merged_build_recipe._defines[k] = v; + } + + for(auto&& [k, v] : target._defines) { + merged_build_recipe._defines[k] = v; + } + merged_build_recipe._exports.reserve( merged_build_recipe._exports.size() + target._exports.size() ); diff --git a/ecsact/cli/commands/build/build_recipe.hh b/ecsact/cli/commands/build/build_recipe.hh index 70c9872..14d5e01 100644 --- a/ecsact/cli/commands/build/build_recipe.hh +++ b/ecsact/cli/commands/build/build_recipe.hh @@ -8,6 +8,7 @@ #include #include #include +#include namespace YAML { class Node; @@ -77,6 +78,7 @@ public: auto imports() const -> std::span; auto sources() const -> std::span; auto system_libs() const -> std::span; + auto defines() const -> std::unordered_map; auto to_yaml_string() const -> std::string; auto to_yaml_bytes() const -> std::vector; @@ -92,6 +94,8 @@ private: std::vector _sources; std::vector _system_libs; + std::unordered_map _defines; + build_recipe(); build_recipe(const build_recipe&); diff --git a/ecsact/cli/commands/build/recipe/cook.cc b/ecsact/cli/commands/build/recipe/cook.cc index 85242ba..ebcfdfc 100644 --- a/ecsact/cli/commands/build/recipe/cook.cc +++ b/ecsact/cli/commands/build/recipe/cook.cc @@ -452,15 +452,16 @@ static auto generate_dylib_imports( // struct compile_options { fs::path work_dir; - ecsact::cli::cc_compiler compiler; - std::vector inc_dirs; - std::vector system_libs; - std::vector srcs; - fs::path output_path; - std::vector imports; - std::vector exports; - std::optional tracy_dir; - bool debug; + ecsact::cli::cc_compiler compiler; + std::vector inc_dirs; + std::vector system_libs; + std::unordered_map defines; + std::vector srcs; + fs::path output_path; + std::vector imports; + std::vector exports; + std::optional tracy_dir; + bool debug; }; struct tracy_compile_options { @@ -519,6 +520,14 @@ auto clang_gcc_compile(compile_options options) -> int { compile_proc_args.push_back("-DECSACT_BUILD"); + for(auto&& [name, value] : options.defines) { + if(value.empty()) { + compile_proc_args.push_back(std::format("-D{}", name)); + } else { + compile_proc_args.push_back(std::format("-D{}={}", name, value)); + } + } + for(auto def : generated_defines) { compile_proc_args.push_back(std::format("-D{}", def)); } @@ -756,6 +765,15 @@ auto cl_compile(compile_options options) -> int { cl_args.push_back("/D_WIN32_WINNT=0x0A00"); cl_args.push_back("/diagnostics:column"); cl_args.push_back("/DECSACT_BUILD"); + + for(auto&& [name, value] : options.defines) { + if(value.empty()) { + cl_args.push_back(std::format("/D{}", name)); + } else { + cl_args.push_back(std::format("/D{}={}", name, value)); + } + } + if(options.tracy_dir) { cl_args.push_back("/DTRACY_ENABLE"); cl_args.push_back("/DTRACY_DELAYED_INIT"); @@ -836,8 +854,8 @@ auto cl_compile(compile_options options) -> int { src_compile_exit_code_futures.reserve(valid_srcs.size()); for(auto src : valid_srcs) { - src_compile_exit_code_futures - .emplace_back(std::async(std::launch::async, [&, src] { + src_compile_exit_code_futures.emplace_back( + std::async(std::launch::async, [&, src] { auto src_cl_args = cl_args; src_cl_args.push_back("/c"); src_cl_args.push_back(std::format("@{}", main_params_file.string())); @@ -850,17 +868,20 @@ auto cl_compile(compile_options options) -> int { src_cl_args.push_back("/std:c++20"); } - src_cl_args.push_back(std::format( - "/Fo{}\\", // typos:disable-line - long_path_workaround(intermediate_dir).string() - )); + src_cl_args.push_back( + std::format( + "/Fo{}\\", // typos:disable-line + long_path_workaround(intermediate_dir).string() + ) + ); return ecsact::cli::detail::spawn_and_report( options.compiler.compiler_path, src_cl_args, reporter ); - })); + }) + ); } auto any_src_compile_failures = false; @@ -890,9 +911,9 @@ auto cl_compile(compile_options options) -> int { cl_args.push_back(obj_f.string()); } - auto obj_params_file = - create_params_file(long_path_workaround(options.work_dir / "object.params") - ); + auto obj_params_file = create_params_file( + long_path_workaround(options.work_dir / "object.params") + ); cl_args.push_back("/Fo:"); // typos:disable-line cl_args.push_back( @@ -1078,6 +1099,7 @@ auto ecsact::cli::cook_recipe( // .compiler = compiler, .inc_dirs = inc_dirs, .system_libs = as_vec(recipe.system_libs()), + .defines = recipe.defines(), .srcs = source_files, .output_path = output_path, .imports = as_vec(recipe.imports()), @@ -1091,6 +1113,7 @@ auto ecsact::cli::cook_recipe( // .compiler = compiler, .inc_dirs = inc_dirs, .system_libs = as_vec(recipe.system_libs()), + .defines = recipe.defines(), .srcs = source_files, .output_path = output_path, .imports = as_vec(recipe.imports()), diff --git a/test/build_recipe/ecsact_build_test.cc b/test/build_recipe/ecsact_build_test.cc index 37b27cd..2ab5491 100644 --- a/test/build_recipe/ecsact_build_test.cc +++ b/test/build_recipe/ecsact_build_test.cc @@ -5,7 +5,20 @@ // This define is _always_ defined when using the Ecsact CLI build command #ifndef ECSACT_BUILD -# error "This test should only have been built through 'ecsact build'" +# error This test should only have been built through 'ecsact build' +#endif + +#ifndef EXAMPLE_DEFINE +# error EXAMPLE_DEFINE should be been set in test-recipe.yml +#endif + +#ifdef EXAMPLE_DEFINE_WITH_VALUE +static_assert( + EXAMPLE_DEFINE_WITH_VALUE == 1, + "EXAMPLE_DEFINE_WITH_VALUE should be been set to 1 in test-recipe.yml" +); +#else +# error EXAMPLE_DEFINE_WITH_VALUE should be been set in test-recipe.yml #endif ecsact_registry_id ecsact_create_registry( // diff --git a/test/build_recipe/test-recipe.yml b/test/build_recipe/test-recipe.yml index babce17..3f1859c 100644 --- a/test/build_recipe/test-recipe.yml +++ b/test/build_recipe/test-recipe.yml @@ -2,6 +2,10 @@ $schema: ../../schema/ecsact-build-recipe.schema.json name: Example Recipe +defines: + EXAMPLE_DEFINE: '' + EXAMPLE_DEFINE_WITH_VALUE: '1' + sources: - ecsact_build_test.cc - codegen: ./test_codegen_plugin From 269b2f53c5b494c446baa9f783f69a3033468e35 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Mon, 4 Aug 2025 20:01:20 -0700 Subject: [PATCH 2/3] chore: update clang-format --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 261ee61..2897fa0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v4 - uses: greut/eclint-action@v0 - uses: jidicula/clang-format-action@v4.11.0 - with: { clang-format-version: "19" } + with: { clang-format-version: "20" } test-windows: if: >- From d5e4f2da452194a2f2385ce9bca957aa8176d494 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Mon, 4 Aug 2025 20:26:13 -0700 Subject: [PATCH 3/3] chore: undo format update --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2897fa0..261ee61 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v4 - uses: greut/eclint-action@v0 - uses: jidicula/clang-format-action@v4.11.0 - with: { clang-format-version: "20" } + with: { clang-format-version: "19" } test-windows: if: >-