From 03c4b11893d53f106eac5c3c41e27e571838552b Mon Sep 17 00:00:00 2001 From: Austin Kelway Date: Fri, 9 Aug 2024 09:59:05 -0700 Subject: [PATCH] feat: Validate recipe plugins on build and bundles (#121) --- ecsact/cli/commands/BUILD.bazel | 23 +++++++++--------- ecsact/cli/commands/build.cc | 28 ++++++++++++++++++++++ ecsact/cli/commands/build/recipe/cook.cc | 23 ++++++++++-------- ecsact/cli/commands/recipe-bundle.cc | 30 +++++++++++++++++++++++- 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/ecsact/cli/commands/BUILD.bazel b/ecsact/cli/commands/BUILD.bazel index df88e66..639e547 100644 --- a/ecsact/cli/commands/BUILD.bazel +++ b/ecsact/cli/commands/BUILD.bazel @@ -34,15 +34,14 @@ cc_library( hdrs = ["common.hh"], copts = copts, deps = [ - "@docopt.cpp//:docopt", "//ecsact/cli:report", "//ecsact/cli:report_message", "//ecsact/cli/detail:json_report", "//ecsact/cli/detail:text_report", + "@docopt.cpp//:docopt", ], ) - cc_library( name = "codegen", srcs = ["codegen.cc"], @@ -51,15 +50,15 @@ cc_library( deps = [ ":command", ":common", - "//ecsact/cli/commands/codegen:codegen", - "@magic_enum", - "@docopt.cpp//:docopt", + "//ecsact/cli/commands/codegen", "@boost.dll", - "@ecsact_interpret", + "@docopt.cpp//:docopt", "@ecsact_codegen//:plugin", "@ecsact_codegen//:plugin_validate", + "@ecsact_interpret", "@ecsact_runtime//:dylib", "@ecsact_runtime//:meta", + "@magic_enum", ], ) @@ -86,13 +85,14 @@ cc_library( ":common", "//ecsact/cli:report", "//ecsact/cli:report_message", - "//ecsact/cli/commands/build/recipe:taste", - "//ecsact/cli/commands/build/recipe:cook", - "//ecsact/cli/commands/build:cc_compiler", "//ecsact/cli/commands/build:build_recipe", + "//ecsact/cli/commands/build:cc_compiler", + "//ecsact/cli/commands/build/recipe:cook", + "//ecsact/cli/commands/build/recipe:taste", "//ecsact/cli/commands/recipe-bundle:build_recipe_bundle", - "@ecsact_interpret", "@docopt.cpp//:docopt", + "@ecsact_codegen//:plugin_validate", + "@ecsact_interpret", "@magic_enum", ], ) @@ -110,8 +110,9 @@ cc_library( "//ecsact/cli/commands/build:build_recipe", "//ecsact/cli/commands/recipe-bundle:build_recipe_bundle", "//ecsact/cli/detail:argv0", - "@ecsact_interpret", "@docopt.cpp//:docopt", + "@ecsact_codegen//:plugin_validate", + "@ecsact_interpret", "@magic_enum", ], ) diff --git a/ecsact/cli/commands/build.cc b/ecsact/cli/commands/build.cc index 98294d4..21674e8 100644 --- a/ecsact/cli/commands/build.cc +++ b/ecsact/cli/commands/build.cc @@ -21,10 +21,12 @@ #include "ecsact/cli/commands/build/recipe/cook.hh" #include "ecsact/cli/commands/build/recipe/taste.hh" #include "ecsact/cli/commands/recipe-bundle/build_recipe_bundle.hh" +#include "ecsact/codegen/plugin_validate.hh" namespace fs = std::filesystem; using namespace std::string_view_literals; +using namespace std::string_literals; constexpr auto USAGE = R"docopt(Ecsact Build Command @@ -173,6 +175,32 @@ auto ecsact::cli::detail::build_command( // } auto recipe = std::move(std::get(recipe_result)); + + for(auto& source : recipe.sources()) { + auto result = std::get_if(&source); + if(result) { + if(result->plugins.empty()) { + ecsact::cli::report_error( + "Recipe source has no plugins {}", + recipe_path_str + ); + return 1; + } + + for(auto plugin : result->plugins) { + auto validate_result = ecsact::codegen::plugin_validate(plugin); + if(!validate_result.ok()) { + auto err_msg = "Plugin validation failed for '" + plugin + "'\n"; + for(auto err : validate_result.errors) { + err_msg += " - "s + to_string(err) + "\n"; + } + ecsact::cli::report_error("{}", err_msg); + return 1; + } + } + } + } + if(!recipe_composite) { recipe_composite.emplace(std::move(recipe)); } else { diff --git a/ecsact/cli/commands/build/recipe/cook.cc b/ecsact/cli/commands/build/recipe/cook.cc index e56bf0a..3ed0255 100644 --- a/ecsact/cli/commands/build/recipe/cook.cc +++ b/ecsact/cli/commands/build/recipe/cook.cc @@ -584,16 +584,7 @@ auto cl_compile(compile_options options) -> int { cl_args.push_back("/diagnostics:column"); cl_args.push_back("/DECSACT_BUILD"); - // TODO(zaucy): Add debug mode - // if(options.debug) { - // compile_proc_args.push_back("/DEBUG:FULL"); - // compile_proc_args.push_back("/MDd"); - // compile_proc_args.push_back("/Z7"); - // compile_proc_args.push_back("/EHsc"); - // compile_proc_args.push_back("/bigobj"); - // } - - // cl_args.push_back("/we4530"); // treat exceptions as errors + cl_args.push_back("/we4530"); // treat exceptions as errors cl_args.push_back("/wd4530"); // ignore use of exceptions warning cl_args.push_back("/MD"); cl_args.push_back("/DNDEBUG"); @@ -605,6 +596,18 @@ auto cl_compile(compile_options options) -> int { std::format("{}\\", fs::path{options.work_dir}.lexically_normal().string()) ); + if(!options.debug) { + cl_args.push_back("/MD"); + cl_args.push_back("/DNDEBUG"); + } else { + cl_args.push_back("/FC"); // full source paths + cl_args.push_back("/MD"); + cl_args.push_back("/Z7"); + cl_args.push_back("/EHsc"); + cl_args.push_back("/bigobj"); + cl_args.push_back("/Od"); + } + auto generated_defines = ecsact::cli::cc_defines_gen(options.imports, options.exports); diff --git a/ecsact/cli/commands/recipe-bundle.cc b/ecsact/cli/commands/recipe-bundle.cc index 23073fc..00b57bb 100644 --- a/ecsact/cli/commands/recipe-bundle.cc +++ b/ecsact/cli/commands/recipe-bundle.cc @@ -17,10 +17,12 @@ #include "ecsact/cli/commands/common.hh" #include "ecsact/cli/commands/build/build_recipe.hh" #include "ecsact/cli/commands/recipe-bundle/build_recipe_bundle.hh" +#include "ecsact/codegen/plugin_validate.hh" namespace fs = std::filesystem; using namespace std::string_view_literals; +using namespace std::string_literals; constexpr auto USAGE = R"docopt(Ecsact Recipe Bundle Command @@ -82,7 +84,7 @@ auto ecsact::cli::detail::recipe_bundle_command( // auto recipe_composite = std::optional{}; auto recipe_paths = args.at("").asStringList(); - for(auto recipe_path : args.at("").asStringList()) { + for(auto recipe_path : recipe_paths) { auto recipe_result = build_recipe::from_yaml_file(recipe_path); if(std::holds_alternative(recipe_result)) { @@ -95,6 +97,32 @@ auto ecsact::cli::detail::recipe_bundle_command( // } auto recipe = std::move(std::get(recipe_result)); + + for(auto& source : recipe.sources()) { + auto result = std::get_if(&source); + if(result) { + if(result->plugins.empty()) { + ecsact::cli::report_error( + "Recipe source has no plugins {}", + recipe_path + ); + return 1; + } + + for(auto plugin : result->plugins) { + auto validate_result = ecsact::codegen::plugin_validate(plugin); + if(!validate_result.ok()) { + auto err_msg = "Plugin validation failed for '" + plugin + "'\n"; + for(auto err : validate_result.errors) { + err_msg += " - "s + to_string(err) + "\n"; + } + ecsact::cli::report_error("{}", err_msg); + return 1; + } + } + } + } + if(!recipe_composite) { recipe_composite.emplace(std::move(recipe)); } else {