Skip to content

Commit f14dff8

Browse files
authored
feat: support new codegen api for multi output (#120)
* when new codegen api is detected it is used and allows multiple output files and custom file paths for code generated files * this is needed due to unreal not liking output paths with `.` characters
1 parent ce7953a commit f14dff8

File tree

12 files changed

+358
-215
lines changed

12 files changed

+358
-215
lines changed

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ bazel_dep(name = "rules_pkg", version = "0.10.1")
1111
bazel_dep(name = "bazel_skylib", version = "1.6.1")
1212
bazel_dep(name = "ecsact_runtime", version = "0.6.6")
1313
bazel_dep(name = "ecsact_interpret", version = "0.6.4")
14-
bazel_dep(name = "ecsact_codegen", version = "0.3.0")
14+
bazel_dep(name = "ecsact_codegen", version = "0.4.1")
1515
bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2")
1616
bazel_dep(name = "magic_enum", version = "0.9.3")
1717
bazel_dep(name = "curl", version = "8.7.1.bcr.1")

ecsact/cli/commands/codegen.cc

Lines changed: 31 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <boost/dll/library_info.hpp>
1111
#include "docopt.h"
1212
#include "ecsact/interpret/eval.hh"
13+
#include "ecsact/cli/commands/codegen/codegen.hh"
1314
#include "ecsact/cli/commands/common.hh"
1415
#include "ecsact/cli/report.hh"
1516
#include "ecsact/runtime/dynamic.h"
@@ -37,36 +38,12 @@ constexpr auto USAGE = R"(Ecsact Codegen Command
3738
--report_filter=<filter> Filtering out report logs [default: none]
3839
)";
3940

40-
static void stdout_write_fn(const char* str, int32_t str_len) {
41-
std::cout << std::string_view(str, str_len);
42-
}
43-
44-
static bool received_fatal_codegen_report = false;
45-
46-
static auto codegen_report_fn(
47-
ecsact_codegen_report_message_type type,
48-
const char* str,
49-
int32_t str_len
41+
static auto stdout_write_fn(
42+
int32_t filename_index,
43+
const char* str,
44+
int32_t str_len
5045
) -> void {
51-
auto msg = std::string{str, static_cast<size_t>(str_len)};
52-
switch(type) {
53-
default:
54-
case ECSACT_CODEGEN_REPORT_INFO:
55-
return report(ecsact::cli::info_message{msg});
56-
case ECSACT_CODEGEN_REPORT_WARNING:
57-
return report(ecsact::cli::warning_message{msg});
58-
case ECSACT_CODEGEN_REPORT_ERROR:
59-
return report(ecsact::cli::error_message{msg});
60-
case ECSACT_CODEGEN_REPORT_FATAL:
61-
received_fatal_codegen_report = true;
62-
return report(ecsact::cli::error_message{msg});
63-
}
64-
}
65-
66-
static thread_local std::ofstream file_write_stream;
67-
68-
static void file_write_fn(const char* str, int32_t str_len) {
69-
file_write_stream << std::string_view(str, str_len);
46+
std::cout << std::string_view(str, str_len);
7047
}
7148

7249
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[]) {
161138
return 1;
162139
}
163140

164-
std::vector<ecsact_package_id> package_ids;
165-
package_ids.resize(static_cast<int32_t>(ecsact_meta_count_packages()));
166-
ecsact_meta_get_package_ids(
167-
static_cast<int32_t>(package_ids.size()),
168-
package_ids.data(),
169-
nullptr
170-
);
171-
172-
std::unordered_set<std::string> output_paths;
173-
bool has_plugin_error = false;
174-
175-
for(auto& plugin : plugins) {
176-
// precondition: these methods should've been checked in validation
177-
assert(plugin.has("ecsact_codegen_plugin"));
178-
assert(plugin.has("ecsact_codegen_plugin_name"));
179-
assert(plugin.has("ecsact_dylib_set_fn_addr"));
180-
181-
auto plugin_fn =
182-
plugin.get<decltype(ecsact_codegen_plugin)>("ecsact_codegen_plugin");
183-
auto plugin_name_fn = plugin.get<decltype(ecsact_codegen_plugin_name)>(
184-
"ecsact_codegen_plugin_name"
185-
);
186-
std::string plugin_name = plugin_name_fn();
187-
188-
decltype(&ecsact_dylib_has_fn) dylib_has_fn = nullptr;
189-
190-
if(plugin.has("ecsact_dylib_has_fn")) {
191-
dylib_has_fn =
192-
plugin.get<decltype(ecsact_dylib_has_fn)>("ecsact_dylib_has_fn");
193-
}
194-
195-
auto dylib_set_fn_addr =
196-
plugin.get<decltype(ecsact_dylib_set_fn_addr)>("ecsact_dylib_set_fn_addr"
197-
);
198-
199-
auto set_meta_fn_ptr = [&](const char* fn_name, auto fn_ptr) {
200-
if(dylib_has_fn && !dylib_has_fn(fn_name)) {
201-
return;
202-
}
203-
dylib_set_fn_addr(fn_name, reinterpret_cast<void (*)()>(fn_ptr));
204-
};
205-
206-
#define CALL_SET_META_FN_PTR(fn_name, unused) \
207-
set_meta_fn_ptr(#fn_name, &::fn_name)
208-
FOR_EACH_ECSACT_META_API_FN(CALL_SET_META_FN_PTR);
209-
#undef CALL_SET_META_FN_PTR
210-
211-
std::optional<fs::path> outdir;
212-
if(args.at("--outdir").isString()) {
213-
outdir = fs::path(args.at("--outdir").asString());
214-
if(!fs::exists(*outdir)) {
215-
std::error_code ec;
216-
fs::create_directories(*outdir, ec);
217-
if(ec) {
218-
report_error(
219-
"Failed to create out directory {}: {}",
220-
outdir->string(),
221-
ec.message()
222-
);
223-
return 3;
224-
}
225-
}
226-
}
227-
228-
if(args.at("--stdout").asBool()) {
229-
plugin_fn(*package_ids.begin(), &stdout_write_fn, &codegen_report_fn);
230-
std::cout.flush();
231-
if(received_fatal_codegen_report) {
232-
received_fatal_codegen_report = false;
233-
has_plugin_error = true;
234-
report_error("Codegen plugin '{}' reported fatal error", plugin_name);
235-
}
236-
} else {
237-
for(auto package_id : package_ids) {
238-
fs::path output_file_path = ecsact_meta_package_file_path(package_id);
239-
if(output_file_path.empty()) {
240-
report_error(
241-
"Could not find package source file path from "
242-
"'ecsact_meta_package_file_path'"
243-
);
244-
continue;
245-
}
246-
247-
output_file_path.replace_extension(
248-
output_file_path.extension().string() + "." + plugin_name
141+
std::optional<fs::path> outdir;
142+
if(args.at("--outdir").isString()) {
143+
outdir = fs::path(args.at("--outdir").asString());
144+
if(!fs::exists(*outdir)) {
145+
std::error_code ec;
146+
fs::create_directories(*outdir, ec);
147+
if(ec) {
148+
report_error(
149+
"Failed to create out directory {}: {}",
150+
outdir->string(),
151+
ec.message()
249152
);
250-
251-
if(outdir) {
252-
output_file_path = *outdir / output_file_path.filename();
253-
}
254-
255-
if(output_paths.contains(output_file_path.string())) {
256-
has_plugin_error = true;
257-
report_error(
258-
"Plugin '{}' has conflicts with another plugin output file '{}'",
259-
plugin.location().filename().string(),
260-
output_file_path.string()
261-
);
262-
continue;
263-
}
264-
265-
output_paths.emplace(output_file_path.string());
266-
if(fs::exists(output_file_path)) {
267-
fs::permissions(output_file_path, fs::perms::all);
268-
}
269-
file_write_stream.open(output_file_path);
270-
plugin_fn(package_id, &file_write_fn, &codegen_report_fn);
271-
file_write_stream.flush();
272-
file_write_stream.close();
273-
fs::permissions(output_file_path, file_readonly_perms);
274-
if(received_fatal_codegen_report) {
275-
received_fatal_codegen_report = false;
276-
report_error(
277-
"Codegen plugin '{}' reported fatal error while processing package "
278-
"'{}'",
279-
plugin_name,
280-
ecsact::meta::package_name(package_id)
281-
);
282-
has_plugin_error = true;
283-
}
153+
return 3;
284154
}
285155
}
156+
}
286157

287-
plugin.unload();
158+
auto codegen_options = ecsact::cli::codegen_options{
159+
.plugin_paths = plugin_paths,
160+
.outdir = outdir,
161+
};
162+
163+
if(args.at("--stdout").asBool()) {
164+
codegen_options.write_fn = &stdout_write_fn;
288165
}
289166

290-
if(has_plugin_error) {
291-
return 2;
167+
auto exit_code = ecsact::cli::codegen(codegen_options);
168+
169+
if(args.at("--stdout").asBool()) {
170+
std::cout.flush();
292171
}
293172

294-
return 0;
173+
return exit_code;
295174
}

0 commit comments

Comments
 (0)