diff --git a/MODULE.bazel b/MODULE.bazel index 8c4fd6f..aa1eaaa 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -11,7 +11,7 @@ bazel_dep(name = "rules_pkg", version = "0.10.1") bazel_dep(name = "bazel_skylib", version = "1.6.1") bazel_dep(name = "ecsact_runtime", version = "0.6.6") bazel_dep(name = "ecsact_interpret", version = "0.6.4") -bazel_dep(name = "ecsact_codegen", version = "0.3.0") +bazel_dep(name = "ecsact_codegen", version = "0.4.1") bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2") bazel_dep(name = "magic_enum", version = "0.9.3") bazel_dep(name = "curl", version = "8.7.1.bcr.1") diff --git a/ecsact/cli/commands/codegen.cc b/ecsact/cli/commands/codegen.cc index 59bb80e..45cf3ee 100644 --- a/ecsact/cli/commands/codegen.cc +++ b/ecsact/cli/commands/codegen.cc @@ -10,6 +10,7 @@ #include #include "docopt.h" #include "ecsact/interpret/eval.hh" +#include "ecsact/cli/commands/codegen/codegen.hh" #include "ecsact/cli/commands/common.hh" #include "ecsact/cli/report.hh" #include "ecsact/runtime/dynamic.h" @@ -37,36 +38,12 @@ constexpr auto USAGE = R"(Ecsact Codegen Command --report_filter= Filtering out report logs [default: none] )"; -static void stdout_write_fn(const char* str, int32_t str_len) { - std::cout << std::string_view(str, str_len); -} - -static bool received_fatal_codegen_report = false; - -static auto codegen_report_fn( - ecsact_codegen_report_message_type type, - const char* str, - int32_t str_len +static auto stdout_write_fn( + int32_t filename_index, + const char* str, + int32_t str_len ) -> void { - auto msg = std::string{str, static_cast(str_len)}; - switch(type) { - default: - case ECSACT_CODEGEN_REPORT_INFO: - return report(ecsact::cli::info_message{msg}); - case ECSACT_CODEGEN_REPORT_WARNING: - return report(ecsact::cli::warning_message{msg}); - case ECSACT_CODEGEN_REPORT_ERROR: - return report(ecsact::cli::error_message{msg}); - case ECSACT_CODEGEN_REPORT_FATAL: - received_fatal_codegen_report = true; - return report(ecsact::cli::error_message{msg}); - } -} - -static thread_local std::ofstream file_write_stream; - -static void file_write_fn(const char* str, int32_t str_len) { - file_write_stream << std::string_view(str, str_len); + std::cout << std::string_view(str, str_len); } int ecsact::cli::detail::codegen_command(int argc, const char* argv[]) { @@ -161,135 +138,37 @@ int ecsact::cli::detail::codegen_command(int argc, const char* argv[]) { return 1; } - std::vector package_ids; - package_ids.resize(static_cast(ecsact_meta_count_packages())); - ecsact_meta_get_package_ids( - static_cast(package_ids.size()), - package_ids.data(), - nullptr - ); - - std::unordered_set output_paths; - bool has_plugin_error = false; - - for(auto& plugin : plugins) { - // precondition: these methods should've been checked in validation - assert(plugin.has("ecsact_codegen_plugin")); - assert(plugin.has("ecsact_codegen_plugin_name")); - assert(plugin.has("ecsact_dylib_set_fn_addr")); - - auto plugin_fn = - plugin.get("ecsact_codegen_plugin"); - auto plugin_name_fn = plugin.get( - "ecsact_codegen_plugin_name" - ); - std::string plugin_name = plugin_name_fn(); - - decltype(&ecsact_dylib_has_fn) dylib_has_fn = nullptr; - - if(plugin.has("ecsact_dylib_has_fn")) { - dylib_has_fn = - plugin.get("ecsact_dylib_has_fn"); - } - - auto dylib_set_fn_addr = - plugin.get("ecsact_dylib_set_fn_addr" - ); - - auto set_meta_fn_ptr = [&](const char* fn_name, auto fn_ptr) { - if(dylib_has_fn && !dylib_has_fn(fn_name)) { - return; - } - dylib_set_fn_addr(fn_name, reinterpret_cast(fn_ptr)); - }; - -#define CALL_SET_META_FN_PTR(fn_name, unused) \ - set_meta_fn_ptr(#fn_name, &::fn_name) - FOR_EACH_ECSACT_META_API_FN(CALL_SET_META_FN_PTR); -#undef CALL_SET_META_FN_PTR - - std::optional outdir; - if(args.at("--outdir").isString()) { - outdir = fs::path(args.at("--outdir").asString()); - if(!fs::exists(*outdir)) { - std::error_code ec; - fs::create_directories(*outdir, ec); - if(ec) { - report_error( - "Failed to create out directory {}: {}", - outdir->string(), - ec.message() - ); - return 3; - } - } - } - - if(args.at("--stdout").asBool()) { - plugin_fn(*package_ids.begin(), &stdout_write_fn, &codegen_report_fn); - std::cout.flush(); - if(received_fatal_codegen_report) { - received_fatal_codegen_report = false; - has_plugin_error = true; - report_error("Codegen plugin '{}' reported fatal error", plugin_name); - } - } else { - for(auto package_id : package_ids) { - fs::path output_file_path = ecsact_meta_package_file_path(package_id); - if(output_file_path.empty()) { - report_error( - "Could not find package source file path from " - "'ecsact_meta_package_file_path'" - ); - continue; - } - - output_file_path.replace_extension( - output_file_path.extension().string() + "." + plugin_name + std::optional outdir; + if(args.at("--outdir").isString()) { + outdir = fs::path(args.at("--outdir").asString()); + if(!fs::exists(*outdir)) { + std::error_code ec; + fs::create_directories(*outdir, ec); + if(ec) { + report_error( + "Failed to create out directory {}: {}", + outdir->string(), + ec.message() ); - - if(outdir) { - output_file_path = *outdir / output_file_path.filename(); - } - - if(output_paths.contains(output_file_path.string())) { - has_plugin_error = true; - report_error( - "Plugin '{}' has conflicts with another plugin output file '{}'", - plugin.location().filename().string(), - output_file_path.string() - ); - continue; - } - - output_paths.emplace(output_file_path.string()); - if(fs::exists(output_file_path)) { - fs::permissions(output_file_path, fs::perms::all); - } - file_write_stream.open(output_file_path); - plugin_fn(package_id, &file_write_fn, &codegen_report_fn); - file_write_stream.flush(); - file_write_stream.close(); - fs::permissions(output_file_path, file_readonly_perms); - if(received_fatal_codegen_report) { - received_fatal_codegen_report = false; - report_error( - "Codegen plugin '{}' reported fatal error while processing package " - "'{}'", - plugin_name, - ecsact::meta::package_name(package_id) - ); - has_plugin_error = true; - } + return 3; } } + } - plugin.unload(); + auto codegen_options = ecsact::cli::codegen_options{ + .plugin_paths = plugin_paths, + .outdir = outdir, + }; + + if(args.at("--stdout").asBool()) { + codegen_options.write_fn = &stdout_write_fn; } - if(has_plugin_error) { - return 2; + auto exit_code = ecsact::cli::codegen(codegen_options); + + if(args.at("--stdout").asBool()) { + std::cout.flush(); } - return 0; + return exit_code; } diff --git a/ecsact/cli/commands/codegen/codegen.cc b/ecsact/cli/commands/codegen/codegen.cc index 5d5837b..002298e 100644 --- a/ecsact/cli/commands/codegen/codegen.cc +++ b/ecsact/cli/commands/codegen/codegen.cc @@ -1,31 +1,53 @@ #include "ecsact/cli/commands/codegen/codegen.hh" -#include +#include +#include +#include #include #include +#include "ecsact/runtime/meta.h" #include "ecsact/cli/report.hh" -#include "ecsact/runtime/meta.hh" #include "ecsact/codegen/plugin.h" -#include "ecsact/cli/commands/codegen/codegen_util.hh" #include "ecsact/runtime/dylib.h" -#include "ecsact/cli/detail/executable_path/executable_path.hh" namespace fs = std::filesystem; using namespace std::string_literals; -static thread_local std::ofstream file_write_stream; +static std::vector file_write_streams; +static bool received_fatal_codegen_report = false; -static void file_write_fn(const char* str, int32_t str_len) { - file_write_stream << std::string_view(str, str_len); +static auto valid_filename_index(int32_t filename_index) -> bool { + if(filename_index < 0 || filename_index > file_write_streams.size() - 1) { + received_fatal_codegen_report = true; + ecsact::cli::report_error( + "Plugin used invalid filename index. Please contact plugin author." + ); + return false; + } + + return true; } -static bool received_fatal_codegen_report = false; +static void file_write_fn( + int32_t filename_index, + const char* str, + int32_t str_len +) { + if(!valid_filename_index(filename_index)) { + return; + } + file_write_streams.at(filename_index) << std::string_view(str, str_len); +} static auto codegen_report_fn( + int32_t filename_index, ecsact_codegen_report_message_type type, const char* str, int32_t str_len ) -> void { + if(!valid_filename_index(filename_index)) { + return; + } auto msg = std::string{str, static_cast(str_len)}; switch(type) { default: @@ -127,13 +149,13 @@ auto ecsact::cli::codegen(codegen_options options) -> int { FOR_EACH_ECSACT_META_API_FN(CALL_SET_META_FN_PTR); #undef CALL_SET_META_FN_PTR - if(!fs::exists(options.outdir)) { + if(options.outdir && !fs::exists(*options.outdir)) { auto ec = std::error_code{}; - fs::create_directories(options.outdir, ec); + fs::create_directories(*options.outdir, ec); if(ec) { ecsact::cli::report_error( "Failed to create out directory {}: {}", - options.outdir.string(), + options.outdir->string(), ec.message() ); unload_plugins(); @@ -142,8 +164,10 @@ auto ecsact::cli::codegen(codegen_options options) -> int { } for(auto package_id : package_ids) { - fs::path output_file_path = ecsact_meta_package_file_path(package_id); - if(output_file_path.empty()) { + auto package_file_path = + fs::path{ecsact_meta_package_file_path(package_id)}; + + if(package_file_path.empty()) { has_plugin_error = true; ecsact::cli::report_error( // "Could not find package source file path from " @@ -152,41 +176,112 @@ auto ecsact::cli::codegen(codegen_options options) -> int { continue; } - output_file_path.replace_extension( - output_file_path.extension().string() + "." + plugin_name - ); + auto plugin_output_paths = std::vector{}; + if(plugin.has("ecsact_codegen_output_filenames")) { + auto plugin_outputs_fn = + plugin.get( + "ecsact_codegen_output_filenames" + ); - if(output_paths.contains(output_file_path.string())) { - has_plugin_error = true; - auto conflicting_plugin_name = output_paths[output_file_path.string()]; + auto filenames_count = int32_t{}; + plugin_outputs_fn(package_id, nullptr, 0, 0, &filenames_count); + if(filenames_count <= 0) { + has_plugin_error = true; + ecsact::cli::report_error( + "Plugin '{}' ({}) ecsact_codegen_output_filenames returned {} " + "filenames. Expected 1 or more.", + plugin_name, + plugin.location().filename().string(), + filenames_count + ); + continue; + } - ecsact::cli::report_error( - "Plugin '{}' ({}) has conflicts with plugin '{}' output file " - "{}", - plugin_name, - plugin.location().filename().string(), - conflicting_plugin_name, - output_file_path.string() + auto filenames = std::array{}; + auto filenames_ = + std::array, filenames.size()>{}; + for(auto i = 0; filenames_.size() > i; ++i) { + filenames[i] = filenames_[i].data(); + } + + plugin_outputs_fn(package_id, filenames.data(), 16, 1024, nullptr); + + for(auto i = 0; filenames_count > i; ++i) { +#if defined(__STDC_WANT_SECURE_LIB__) && __STDC_WANT_SECURE_LIB__ + auto filename = + std::string_view{filenames[i], strnlen_s(filenames[i], 1023)}; +#else + auto filename = std::string_view{filenames[i], strlen(filenames[i])}; +#endif + plugin_output_paths.emplace_back( + fs::path{package_file_path}.parent_path() / filename + ); + } + } else { + plugin_output_paths.emplace_back( + fs::path{package_file_path}.replace_extension( + package_file_path.extension().string() + "." + plugin_name + ) ); + } - continue; + if(options.outdir) { + for(auto& output_file_path : plugin_output_paths) { + output_file_path = *options.outdir / output_file_path.filename(); + } } - output_paths.emplace(output_file_path.string(), plugin_name); - if(fs::exists(output_file_path)) { - fs::permissions(output_file_path, fs::perms::all); + + auto has_plugin_output_conflict_error = false; + for(auto filename_index = 0; plugin_output_paths.size() > filename_index; + ++filename_index) { + auto output_file_path = plugin_output_paths.at(filename_index); + if(output_paths.contains(output_file_path.string())) { + has_plugin_error = true; + has_plugin_output_conflict_error = true; + auto conflicting_plugin_name = + output_paths[output_file_path.string()]; + + ecsact::cli::report_error( + "Plugin '{}' ({}) has conflicts with plugin '{}' output file " + "{}", + plugin_name, + plugin.location().filename().string(), + conflicting_plugin_name, + output_file_path.string() + ); + } } - output_file_path = options.outdir / output_file_path.filename(); + if(!has_plugin_output_conflict_error) { + // We're filling this in the for loop. We shouldn't have any in here. + assert(file_write_streams.empty()); - file_write_stream.open(output_file_path); - plugin_fn(package_id, &file_write_fn, &codegen_report_fn); - if(received_fatal_codegen_report) { - received_fatal_codegen_report = false; - has_plugin_error = true; - report_error("Codegen plugin '{}' reported fatal error", plugin_name); + for(auto filename_index = 0; + plugin_output_paths.size() > filename_index; + ++filename_index) { + auto output_file_path = plugin_output_paths.at(filename_index); + output_paths.emplace(output_file_path.string(), plugin_name); + if(fs::exists(output_file_path)) { + fs::permissions(output_file_path, fs::perms::all); + } + + auto& file_write_stream = file_write_streams.emplace_back(); + file_write_stream.open(output_file_path); + } + + plugin_fn(package_id, &file_write_fn, &codegen_report_fn); + if(received_fatal_codegen_report) { + received_fatal_codegen_report = false; + has_plugin_error = true; + report_error("Codegen plugin '{}' reported fatal error", plugin_name); + } + + for(auto& file_write_stream : file_write_streams) { + file_write_stream.flush(); + file_write_stream.close(); + } + file_write_streams.clear(); } - file_write_stream.flush(); - file_write_stream.close(); } plugin.unload(); } diff --git a/ecsact/cli/commands/codegen/codegen.hh b/ecsact/cli/commands/codegen/codegen.hh index f4f2ada..66510a3 100644 --- a/ecsact/cli/commands/codegen/codegen.hh +++ b/ecsact/cli/commands/codegen/codegen.hh @@ -1,17 +1,16 @@ #pragma once #include -#include #include #include +#include "ecsact/codegen/plugin.h" namespace ecsact::cli { -using codegen_output_write_fn_t = void (*)(const char* str, int32_t str_len); - struct codegen_options { - std::vector plugin_paths; - std::filesystem::path outdir; + std::vector plugin_paths; + std::optional outdir; + std::optional write_fn; }; auto codegen(codegen_options options) -> int; diff --git a/test/BUILD.bazel b/test/BUILD.bazel index 568f2c9..f864310 100644 --- a/test/BUILD.bazel +++ b/test/BUILD.bazel @@ -7,13 +7,18 @@ exports_files([ "test.ecsact", ]) -cc_binary( - name = "test_codegen_plugin.so", +_TEST_PLUGINS = [ + "test_codegen_plugin", + "test_codegen_plugin_multi_output", +] + +[cc_binary( + name = "{}.so".format(plugin), linkshared = True, copts = copts, tags = ["manual"], srcs = [ - "test_codegen_plugin.cc", + "{}.cc".format(plugin), "@ecsact_runtime//dylib:dylib.cc", ], deps = [ @@ -23,15 +28,15 @@ cc_binary( "@ecsact_runtime//dylib:util", ], defines = ["ECSACT_META_API_LOAD_AT_RUNTIME"], -) +) for plugin in _TEST_PLUGINS] -cc_binary( - name = "test_codegen_plugin.dll", +[cc_binary( + name = "{}.dll".format(plugin), linkshared = True, copts = copts, tags = ["manual"], srcs = [ - "test_codegen_plugin.cc", + "{}.cc".format(plugin), "@ecsact_runtime//dylib:dylib.cc", ], deps = [ @@ -41,15 +46,15 @@ cc_binary( "@ecsact_runtime//dylib:util", ], defines = ["ECSACT_META_API_LOAD_AT_RUNTIME"], -) +) for plugin in _TEST_PLUGINS] -alias( - name = "test_codegen_plugin", +[alias( + name = plugin, actual = select({ - "@platforms//os:windows": "test_codegen_plugin.dll", - "@platforms//os:linux": "test_codegen_plugin.so", + "@platforms//os:windows": "{}.dll".format(plugin), + "@platforms//os:linux": "{}.so".format(plugin), }), -) +) for plugin in _TEST_PLUGINS] cc_test( name = "test_codegen", @@ -72,3 +77,25 @@ cc_test( "@googletest//:gtest_main", ], ) + +cc_test( + name = "test_codegen_multi_output", + copts = copts, + srcs = ["test_codegen_multi_output.cc"], + data = [ + "@ecsact_cli", + "test.ecsact", + ":test_codegen_plugin_multi_output", + ], + env = { + "TEST_ECSACT_CLI": "$(rootpath @ecsact_cli)", + "TEST_ECSACT_FILE_PATH": "$(rootpath test.ecsact)", + "TEST_CODEGEN_PLUGIN_PATH": "$(rootpath :test_codegen_plugin_multi_output)", + }, + deps = [ + "@bazel_tools//tools/cpp/runfiles", + "@ecsact_cli//ecsact/cli/commands:codegen", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) diff --git a/test/MODULE.bazel b/test/MODULE.bazel index eba8c1c..8b3c5c7 100644 --- a/test/MODULE.bazel +++ b/test/MODULE.bazel @@ -1,6 +1,6 @@ bazel_dep(name = "rules_cc", version = "0.0.9") bazel_dep(name = "rules_ecsact", version = "0.5.0") -bazel_dep(name = "ecsact_codegen", version = "0.3.0") +bazel_dep(name = "ecsact_codegen", version = "0.4.1") bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2") bazel_dep(name = "boost.process", version = "1.83.0.bzl.2") bazel_dep(name = "ecsact_runtime", version = "0.6.5") diff --git a/test/build_recipe/ecsact_build_test_merge.cc b/test/build_recipe/ecsact_build_test_merge.cc index da7470f..4eaa074 100644 --- a/test/build_recipe/ecsact_build_test_merge.cc +++ b/test/build_recipe/ecsact_build_test_merge.cc @@ -5,7 +5,12 @@ # error "This test should only have been built through 'ecsact build'" #endif -void ecsact_system_execution_context_get(struct ecsact_system_execution_context*, ecsact_component_like_id, void*) { +void ecsact_system_execution_context_get( + struct ecsact_system_execution_context*, + ecsact_component_like_id, + void*, + ... +) { } void ecsact_system_execution_context_action(struct ecsact_system_execution_context*, void*) { diff --git a/test/codegen_plugin_errors/BUILD.bazel b/test/codegen_plugin_errors/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/test/test_codegen.cc b/test/test_codegen.cc index c9bd7f5..4adadcb 100644 --- a/test/test_codegen.cc +++ b/test/test_codegen.cc @@ -63,5 +63,7 @@ TEST(Codegen, Success) { std::istreambuf_iterator(), }; - ASSERT_EQ(generated_file_contents, "this is just a test, breathe!"); + ASSERT_EQ(generated_file_contents, "this is just a test, breathe!") + << "Unexpected content at " + << fs::absolute(generated_file_path).generic_string(); } diff --git a/test/test_codegen_multi_output.cc b/test/test_codegen_multi_output.cc new file mode 100644 index 0000000..acb89af --- /dev/null +++ b/test/test_codegen_multi_output.cc @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include "ecsact/cli/commands/codegen.hh" +#include "tools/cpp/runfiles/runfiles.h" + +using bazel::tools::cpp::runfiles::Runfiles; +using ecsact::cli::detail::codegen_command; + +using namespace std::string_literals; +namespace fs = std::filesystem; + +TEST(Codegen, Success) { + auto runfiles_err = std::string{}; + auto runfiles = Runfiles::CreateForTest(&runfiles_err); + auto test_ecsact_cli = std::getenv("TEST_ECSACT_CLI"); + auto test_codegen_plugin_path = std::getenv("TEST_CODEGEN_PLUGIN_PATH"); + auto test_ecsact_file_path = std::getenv("TEST_ECSACT_FILE_PATH"); + + ASSERT_NE(test_ecsact_cli, nullptr); + ASSERT_NE(test_codegen_plugin_path, nullptr); + ASSERT_NE(test_ecsact_file_path, nullptr); + ASSERT_NE(runfiles, nullptr) << runfiles_err; + + auto generated_txt_file_path = fs::path{"_test_codegen_outdir/test.txt"}; + auto generated_zomsky_file_path = + fs::path{"_test_codegen_outdir/test.zomsky"}; + + if(fs::exists(generated_txt_file_path)) { + fs::remove(generated_txt_file_path); + } + + if(fs::exists(generated_zomsky_file_path)) { + fs::remove(generated_zomsky_file_path); + } + + ASSERT_TRUE(fs::exists(test_codegen_plugin_path)) + << "Cannot find test plugin: " + << fs::absolute(test_codegen_plugin_path).string(); + ASSERT_TRUE(fs::exists(test_ecsact_file_path)) + << "Cannot find test ecsact file: " + << fs::absolute(test_ecsact_file_path).string(); + +#if _WIN32 + // TODO: this doesn't work on linux + auto exit_code = codegen_command(std::vector{ + "ecsact"s, + "codegen"s, + std::string{test_ecsact_file_path}, + std::format("--plugin={}", test_codegen_plugin_path), + "--outdir=_test_codegen_outdir"s, + }); +#else + auto cmd = std::format( + "{} codegen {} --plugin={} --outdir=_test_codegen_outdir", + test_ecsact_cli, + std::string{test_ecsact_file_path}, + test_codegen_plugin_path, + "_test_codegen_outdir" + ); + auto exit_code = std::system(cmd.c_str()); +#endif + + ASSERT_EQ(exit_code, 0); + + ASSERT_TRUE(fs::exists(generated_txt_file_path)); + auto generated_txt_file = std::ifstream{generated_txt_file_path}; + auto generated_txt_file_contents = std::string{ + std::istreambuf_iterator(generated_txt_file), + std::istreambuf_iterator(), + }; + + ASSERT_EQ(generated_txt_file_contents, "throw this in the text file") + << "Unexpected content at " + << fs::absolute(generated_txt_file_path).generic_string(); + + ASSERT_TRUE(fs::exists(generated_zomsky_file_path)); + auto generated_zomsky_file = std::ifstream{generated_zomsky_file_path}; + auto generated_zomsky_file_contents = std::string{ + std::istreambuf_iterator(generated_zomsky_file), + std::istreambuf_iterator(), + }; + + ASSERT_EQ(generated_zomsky_file_contents, "throw this in the zomsky file") + << "Unexpected content at " + << fs::absolute(generated_zomsky_file_path).generic_string(); +} diff --git a/test/test_codegen_plugin.cc b/test/test_codegen_plugin.cc index ebf87df..fa06e47 100644 --- a/test/test_codegen_plugin.cc +++ b/test/test_codegen_plugin.cc @@ -1,6 +1,5 @@ #include #include "ecsact/codegen/plugin.h" -#include "ecsact/runtime/dylib.h" using namespace std::string_view_literals; @@ -14,10 +13,11 @@ auto ecsact_codegen_plugin( // ecsact_codegen_report_fn_t report_fn ) -> void { auto test_message = "this is just a test, breathe!"sv; - write_fn(test_message.data(), test_message.size()); + write_fn(0, test_message.data(), test_message.size()); auto example_report_msg = "example warning, don't worry"sv; report_fn( + 0, ECSACT_CODEGEN_REPORT_WARNING, example_report_msg.data(), example_report_msg.size() diff --git a/test/test_codegen_plugin_multi_output.cc b/test/test_codegen_plugin_multi_output.cc new file mode 100644 index 0000000..1781473 --- /dev/null +++ b/test/test_codegen_plugin_multi_output.cc @@ -0,0 +1,46 @@ +#include +#include +#include "ecsact/codegen/plugin.hh" +#include "ecsact/runtime/meta.hh" + +using namespace std::string_view_literals; + +auto ecsact_codegen_output_filenames( // + ecsact_package_id package_id, + char* const* out_filenames, + int32_t max_filenames, + int32_t max_filename_length, + int32_t* out_filenames_length +) -> void { + auto pkg_basename = // + ecsact::meta::package_file_path(package_id) + .filename() + .replace_extension("") + .string(); + ecsact::set_codegen_plugin_output_filenames( + std::array{ + pkg_basename + ".txt", + pkg_basename + ".zomsky", + }, + out_filenames, + max_filenames, + max_filename_length, + out_filenames_length + ); +} + +auto ecsact_codegen_plugin_name() -> const char* { + return "Example Codegen"; +} + +auto ecsact_codegen_plugin( // + ecsact_package_id package_id, + ecsact_codegen_write_fn_t write_fn, + ecsact_codegen_report_fn_t report_fn +) -> void { + auto test_message = "throw this in the text file"sv; + write_fn(0, test_message.data(), test_message.size()); + + test_message = "throw this in the zomsky file"sv; + write_fn(1, test_message.data(), test_message.size()); +}