Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions ecsact/cli/commands/build/build_recipe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ auto ecsact::build_recipe::system_libs() const -> std::span<const std::string> {
return _system_libs;
}

auto ecsact::build_recipe::defines() const
-> std::unordered_map<std::string, std::string> {
return _defines;
}

static auto get_if_error( //
const auto& result
) -> std::optional<ecsact::build_recipe_parse_error> {
Expand Down Expand Up @@ -166,6 +171,19 @@ static auto parse_system_libs( //
return system_libs.as<std::vector<std::string>>();
}

static auto parse_defines( //
YAML::Node defines
)
-> std::variant<
std::unordered_map<std::string, std::string>,
ecsact::build_recipe_parse_error> {
if(!defines) {
return {};
}

return defines.as<std::unordered_map<std::string, std::string>>();
}

static auto parse_sources( //
fs::path recipe_path,
YAML::Node sources
Expand Down Expand Up @@ -225,13 +243,15 @@ static auto parse_sources( //
if(src["outdir"]) {
outdir = src["outdir"].as<std::string>();
}
result.emplace_back(source_fetch{
.url = fetch.as<std::string>(),
.integrity = integrity,
.strip_prefix = strip_prefix,
.outdir = outdir,
.paths = paths,
});
result.emplace_back(
source_fetch{
.url = fetch.as<std::string>(),
.integrity = integrity,
.strip_prefix = strip_prefix,
.outdir = outdir,
.paths = paths,
}
);
} else if(path) {
auto src_path = fs::path{path.as<std::string>()};
auto outdir = std::optional<std::string>{};
Expand All @@ -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<std::string>()}.lexically_normal();
result.emplace_back(source_path{
.path = path,
.outdir = ".",
});
result.emplace_back(
source_path{
.path = path,
.outdir = ".",
}
);
}
}

Expand Down Expand Up @@ -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<std::string>();
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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()
);
Expand Down
4 changes: 4 additions & 0 deletions ecsact/cli/commands/build/build_recipe.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <cstddef>
#include <optional>
#include <filesystem>
#include <unordered_map>

namespace YAML {
class Node;
Expand Down Expand Up @@ -77,6 +78,7 @@ public:
auto imports() const -> std::span<const std::string>;
auto sources() const -> std::span<const source>;
auto system_libs() const -> std::span<const std::string>;
auto defines() const -> std::unordered_map<std::string, std::string>;

auto to_yaml_string() const -> std::string;
auto to_yaml_bytes() const -> std::vector<std::byte>;
Expand All @@ -92,6 +94,8 @@ private:
std::vector<source> _sources;
std::vector<std::string> _system_libs;

std::unordered_map<std::string, std::string> _defines;

build_recipe();
build_recipe(const build_recipe&);

Expand Down
61 changes: 42 additions & 19 deletions ecsact/cli/commands/build/recipe/cook.cc
Original file line number Diff line number Diff line change
Expand Up @@ -452,15 +452,16 @@ static auto generate_dylib_imports( //
struct compile_options {
fs::path work_dir;

ecsact::cli::cc_compiler compiler;
std::vector<fs::path> inc_dirs;
std::vector<std::string> system_libs;
std::vector<fs::path> srcs;
fs::path output_path;
std::vector<std::string> imports;
std::vector<std::string> exports;
std::optional<fs::path> tracy_dir;
bool debug;
ecsact::cli::cc_compiler compiler;
std::vector<fs::path> inc_dirs;
std::vector<std::string> system_libs;
std::unordered_map<std::string, std::string> defines;
std::vector<fs::path> srcs;
fs::path output_path;
std::vector<std::string> imports;
std::vector<std::string> exports;
std::optional<fs::path> tracy_dir;
bool debug;
};

struct tracy_compile_options {
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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()));
Expand All @@ -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;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()),
Expand All @@ -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()),
Expand Down
15 changes: 14 additions & 1 deletion test/build_recipe/ecsact_build_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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( //
Expand Down
4 changes: 4 additions & 0 deletions test/build_recipe/test-recipe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading