Skip to content

feat: allow specifying libs #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
41 changes: 41 additions & 0 deletions ecsact/cli/commands/build/build_recipe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,41 @@ static auto parse_sources( //
return result;
}

static auto parse_libs( //
fs::path recipe_path,
YAML::Node libs
)
-> std::variant<
std::vector<ecsact::build_recipe::lib>,
ecsact::build_recipe_parse_error> {
auto result = std::vector<ecsact::build_recipe::lib>{};

for(auto lib_doc : libs) {
if(!lib_doc.IsMap()) {
return ecsact::build_recipe_parse_error::invalid_lib;
}

auto sources = parse_sources(recipe_path, lib_doc["sources"]);
if(auto err = get_if_error(sources)) {
return *err;
}

auto system_libs = parse_system_libs(lib_doc["system_libs"]);
if(auto err = get_if_error(system_libs)) {
return *err;
}

auto lib = ecsact::build_recipe::lib{};
lib.name = lib_doc["name"].as<std::string>();
lib.sources = get_value(sources);
lib.system_libs = get_value(system_libs);

result.emplace_back(std::move(lib));
}

return result;
}

auto ecsact::build_recipe::build_recipe_from_yaml_node( //
YAML::Node doc,
fs::path p
Expand Down Expand Up @@ -293,6 +328,11 @@ auto ecsact::build_recipe::build_recipe_from_yaml_node( //
return *err;
}

auto libs = parse_libs(p, doc["libs"]);
if(auto err = get_if_error(libs)) {
return *err;
}

auto recipe = ecsact::build_recipe{};
if(doc["name"]) {
recipe._name = doc["name"].as<std::string>();
Expand All @@ -304,6 +344,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._libs = get_value(libs);

if(recipe._exports.empty()) {
return build_recipe_parse_error::missing_exports;
Expand Down
9 changes: 9 additions & 0 deletions ecsact/cli/commands/build/build_recipe.hh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum class build_recipe_parse_error {
unknown_import_method,
unknown_export_method,
conflicting_import_export_method_modules,
invalid_lib,
};

enum class build_recipe_merge_error {
Expand Down Expand Up @@ -68,6 +69,12 @@ public:

using source = std::variant<source_path, source_fetch, source_codegen>;

struct lib {
std::string name;
std::vector<source> sources;
std::vector<std::string> system_libs;
};

build_recipe(build_recipe&&);
~build_recipe();

Expand All @@ -76,6 +83,7 @@ public:
auto exports() const -> std::span<const std::string>;
auto imports() const -> std::span<const std::string>;
auto sources() const -> std::span<const source>;
auto libs() const -> std::span<const lib>;
auto system_libs() const -> std::span<const std::string>;

auto to_yaml_string() const -> std::string;
Expand All @@ -90,6 +98,7 @@ private:
std::vector<std::string> _exports;
std::vector<std::string> _imports;
std::vector<source> _sources;
std::vector<lib> _libs;
std::vector<std::string> _system_libs;

build_recipe();
Expand Down
176 changes: 117 additions & 59 deletions ecsact/cli/commands/build/recipe/cook.cc
Original file line number Diff line number Diff line change
Expand Up @@ -420,17 +420,23 @@ static auto generate_dylib_imports( //
output << "}\n\n";
}

struct compile_lib_options {
std::vector<std::string> system_libs;
std::vector<fs::path> srcs;
};

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;
bool debug;
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::vector<compile_lib_options> libs;
bool debug;
};

auto clang_gcc_compile(compile_options options) -> int {
Expand Down Expand Up @@ -583,6 +589,34 @@ auto clang_gcc_compile(compile_options options) -> int {
}

auto cl_compile(compile_options options) -> int {
struct : ecsact::cli::detail::spawn_reporter {
auto on_std_out(std::string_view line) -> std::optional<message_variant_t> {
if(line.find(": warning") != std::string::npos) {
return ecsact::cli::warning_message{
.content = std::string{line},
};
} else if(line.find(": error") != std::string::npos) {
return ecsact::cli::error_message{
.content = std::string{line},
};
} else if(line.find(": fatal error ") != std::string::npos) {
return ecsact::cli::error_message{
.content = std::string{line},
};
} else if(line.find(": Command line error ") != std::string::npos) {
return ecsact::cli::error_message{
.content = std::string{line},
};
}

return {};
}

auto on_std_err(std::string_view line) -> std::optional<message_variant_t> {
return {};
}
} reporter;

auto abs_from_wd = [&options](fs::path rel_path) {
assert(!rel_path.empty());
if(rel_path.is_absolute()) {
Expand All @@ -593,29 +627,81 @@ auto cl_compile(compile_options options) -> int {
);
};

auto cl_args = std::vector<std::string>{};

cl_args.push_back("/nologo");
cl_args.push_back("/std:c++20");
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("/wd4530"); // ignore use of exceptions warning
cl_args.push_back("/MD");
cl_args.push_back("/DNDEBUG");
cl_args.push_back("/O2");
cl_args.push_back("/GL");
cl_args.push_back("/MP");
auto prepare_default_cl_args = [&] {
auto cl_args = std::vector<std::string>{};

cl_args.push_back("/nologo");
cl_args.push_back("/std:c++20");
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("/wd4530"); // ignore use of exceptions warning
cl_args.push_back("/MD");
cl_args.push_back("/DNDEBUG");
cl_args.push_back("/O2");
cl_args.push_back("/GL");
cl_args.push_back("/MP");
return cl_args;
};

auto lib_objs = std::vector<fs::path>();

for(auto lib : options.libs) {
auto cl_args = prepare_default_cl_args();

cl_args.push_back("/LIB");

for(auto src : lib.srcs) {
if(src.extension().string().starts_with(".h")) {
continue;
}

if(src.extension().string() == ".ipp") {
continue;
}

cl_args.push_back(abs_from_wd(src).string());
}

for(auto inc_dir : options.compiler.std_inc_paths) {
cl_args.push_back(std::format("/I{}", inc_dir.string()));
}

for(auto inc_dir : options.inc_dirs) {
cl_args.push_back(std::format("/I{}", inc_dir.string()));
}

for(auto sys_lib : lib.system_libs) {
cl_args.push_back(std::format("/DEFAULTLIB:{}", sys_lib));
}

auto lib_compile_exit_code = ecsact::cli::detail::spawn_and_report(
options.compiler.compiler_path,
cl_args,
reporter
);

if(lib_compile_exit_code != 0) {
ecsact::cli::report_error(
"Failed to compile recipe lib. Compiler {} exited with code {}",
to_string(options.compiler.compiler_type),
lib_compile_exit_code
);
return 1;
}
}

auto cl_args = prepare_default_cl_args();
cl_args.push_back("/Fo:"); // typos:disable-line
cl_args.push_back(
std::format("{}\\", fs::path{options.work_dir}.lexically_normal().string())
Expand Down Expand Up @@ -671,34 +757,6 @@ auto cl_compile(compile_options options) -> int {

cl_args.push_back(std::format("/OUT:{}", options.output_path.string()));

struct : ecsact::cli::detail::spawn_reporter {
auto on_std_out(std::string_view line) -> std::optional<message_variant_t> {
if(line.find(": warning") != std::string::npos) {
return ecsact::cli::warning_message{
.content = std::string{line},
};
} else if(line.find(": error") != std::string::npos) {
return ecsact::cli::error_message{
.content = std::string{line},
};
} else if(line.find(": fatal error ") != std::string::npos) {
return ecsact::cli::error_message{
.content = std::string{line},
};
} else if(line.find(": Command line error ") != std::string::npos) {
return ecsact::cli::error_message{
.content = std::string{line},
};
}

return {};
}

auto on_std_err(std::string_view line) -> std::optional<message_variant_t> {
return {};
}
} reporter;

auto compile_exit_code = ecsact::cli::detail::spawn_and_report(
options.compiler.compiler_path,
cl_args,
Expand Down