spdlog::info("Compile file: {}", fs::relative(src_path, params.root).string()); | spdlog::info("Compile file: {}", fs::relative(src_path, params.root).string()); | ||||
compile_file_spec spec{src_path, obj_path}; | compile_file_spec spec{src_path, obj_path}; | ||||
spec.enable_warnings = params.enable_warnings; | |||||
spec.include_dirs.push_back(params.root / "src"); | spec.include_dirs.push_back(params.root / "src"); | ||||
spec.include_dirs.push_back(params.root / "include"); | spec.include_dirs.push_back(params.root / "include"); | ||||
throw compile_failure("Compilation failed."); | throw compile_failure("Compilation failed."); | ||||
} | } | ||||
if (!compile_res.output.empty()) { | |||||
spdlog::warn("While compiling file {}:\n{}", spec.source_path.string(), compile_res.output); | |||||
} | |||||
return obj_path; | return obj_path; | ||||
} | } | ||||
std::string export_name; | std::string export_name; | ||||
bool do_export = false; | bool do_export = false; | ||||
bool build_tests = false; | bool build_tests = false; | ||||
bool enable_warnings = false; | |||||
}; | }; | ||||
void build(const build_params&, const library_manifest& man); | void build(const build_params&, const library_manifest& man); |
args::Flag build_tests{cmd, "build_tests", "Build the tests", {"tests"}}; | args::Flag build_tests{cmd, "build_tests", "Build the tests", {"tests"}}; | ||||
args::Flag export_{cmd, "export_dir", "Generate a library export", {"export", 'E'}}; | args::Flag export_{cmd, "export_dir", "Generate a library export", {"export", 'E'}}; | ||||
args::Flag enable_warnings{cmd, | |||||
"enable_warnings", | |||||
"Enable compiler warnings", | |||||
{"--warnings", 'W'}}; | |||||
int run() { | int run() { | ||||
dds::build_params params; | dds::build_params params; | ||||
params.root = lib_dir.Get(); | params.root = lib_dir.Get(); | ||||
params.export_name = export_name.Get(); | params.export_name = export_name.Get(); | ||||
params.do_export = export_.Get(); | params.do_export = export_.Get(); | ||||
params.build_tests = build_tests.Get(); | params.build_tests = build_tests.Get(); | ||||
params.enable_warnings = enable_warnings.Get(); | |||||
dds::library_manifest man; | dds::library_manifest man; | ||||
const auto man_filepath = params.root / "manifest.dds"; | const auto man_filepath = params.root / "manifest.dds"; | ||||
if (exists(man_filepath)) { | if (exists(man_filepath)) { |
opt_string c_compile_template; | opt_string c_compile_template; | ||||
opt_string cxx_compile_template; | opt_string cxx_compile_template; | ||||
opt_string create_archive_template; | opt_string create_archive_template; | ||||
opt_string warning_flags; | |||||
opt_string archive_suffix; | opt_string archive_suffix; | ||||
|| try_single("Compile-C++-Template", cxx_compile_template) | || try_single("Compile-C++-Template", cxx_compile_template) | ||||
|| try_single("Create-Archive-Template", create_archive_template) | || try_single("Create-Archive-Template", create_archive_template) | ||||
|| try_single("Archive-Suffix", archive_suffix) | || try_single("Archive-Suffix", archive_suffix) | ||||
|| try_single("Warning-Flags", warning_flags) | |||||
|| false; | || false; | ||||
// clang-format on | // clang-format on | ||||
def_template.value(), | def_template.value(), | ||||
create_archive_template.value(), | create_archive_template.value(), | ||||
archive_suffix.value(), | archive_suffix.value(), | ||||
warning_flags.value_or(""), | |||||
}; | }; | ||||
} | } | ||||
for (auto&& inc_dir : spec.include_dirs) { | for (auto&& inc_dir : spec.include_dirs) { | ||||
auto inc_args = include_args(inc_dir); | auto inc_args = include_args(inc_dir); | ||||
flags.insert(flags.end(), inc_args.begin(), inc_args.end()); | |||||
extend(flags, inc_args); | |||||
} | } | ||||
for (auto&& def : spec.definitions) { | for (auto&& def : spec.definitions) { | ||||
auto def_args = definition_args(def); | auto def_args = definition_args(def); | ||||
flags.insert(flags.end(), def_args.begin(), def_args.end()); | |||||
extend(flags, def_args); | |||||
} | |||||
if (spec.enable_warnings) { | |||||
extend(flags, _warning_flags); | |||||
} | } | ||||
vector<string> command; | vector<string> command; | ||||
for (auto arg : _cxx_compile) { | for (auto arg : _cxx_compile) { | ||||
if (arg == "<FLAGS>") { | if (arg == "<FLAGS>") { | ||||
command.insert(command.end(), flags.begin(), flags.end()); | |||||
extend(command, flags); | |||||
} else { | } else { | ||||
arg = replace(arg, "<FILE>", spec.source_path.string()); | arg = replace(arg, "<FILE>", spec.source_path.string()); | ||||
arg = replace(arg, "<OUT>", spec.out_path.string()); | arg = replace(arg, "<OUT>", spec.out_path.string()); | ||||
vector<string> cmd; | vector<string> cmd; | ||||
for (auto& arg : _archive_template) { | for (auto& arg : _archive_template) { | ||||
if (arg == "<OBJECTS>") { | if (arg == "<OBJECTS>") { | ||||
cmd.insert(cmd.end(), spec.input_files.begin(), spec.input_files.end()); | |||||
extend(cmd, spec.input_files); | |||||
} else { | } else { | ||||
cmd.push_back(replace(arg, "<ARCHIVE>", spec.out_path.string())); | cmd.push_back(replace(arg, "<ARCHIVE>", spec.out_path.string())); | ||||
} | } |
std::vector<std::string> definitions = {}; | std::vector<std::string> definitions = {}; | ||||
std::vector<fs::path> include_dirs = {}; | std::vector<fs::path> include_dirs = {}; | ||||
language lang = language::automatic; | language lang = language::automatic; | ||||
bool enable_warnings = false; | |||||
}; | }; | ||||
struct archive_spec { | struct archive_spec { | ||||
class toolchain { | class toolchain { | ||||
using string_seq = std::vector<std::string>; | using string_seq = std::vector<std::string>; | ||||
string_seq _c_compile; | |||||
string_seq _cxx_compile; | |||||
string_seq _inc_template; | |||||
string_seq _def_template; | |||||
string_seq _archive_template; | |||||
string_seq _c_compile; | |||||
string_seq _cxx_compile; | |||||
string_seq _inc_template; | |||||
string_seq _def_template; | |||||
string_seq _archive_template; | |||||
std::string _archive_suffix; | std::string _archive_suffix; | ||||
string_seq _warning_flags; | |||||
public: | public: | ||||
toolchain(const std::string& c_compile, | toolchain(const std::string& c_compile, | ||||
const std::string& inc_template, | const std::string& inc_template, | ||||
const std::string& def_template, | const std::string& def_template, | ||||
const std::string& archive_template, | const std::string& archive_template, | ||||
const std::string& archive_suffix) | |||||
const std::string& archive_suffix, | |||||
const std::string& warning_flags) | |||||
: _c_compile(split_shell_string(c_compile)) | : _c_compile(split_shell_string(c_compile)) | ||||
, _cxx_compile(split_shell_string(cxx_compile)) | , _cxx_compile(split_shell_string(cxx_compile)) | ||||
, _inc_template(split_shell_string(inc_template)) | , _inc_template(split_shell_string(inc_template)) | ||||
, _def_template(split_shell_string(def_template)) | , _def_template(split_shell_string(def_template)) | ||||
, _archive_template(split_shell_string(archive_template)) | , _archive_template(split_shell_string(archive_template)) | ||||
, _archive_suffix(archive_suffix) {} | |||||
, _archive_suffix(archive_suffix) | |||||
, _warning_flags(split_shell_string(warning_flags)) {} | |||||
static toolchain load_from_file(fs::path); | static toolchain load_from_file(fs::path); | ||||
c.erase(erase_point, c.end()); | c.erase(erase_point, c.end()); | ||||
} | } | ||||
template <typename Container, typename Other> | |||||
void extend(Container& c, const Other& o) { | |||||
c.insert(c.end(), o.begin(), o.end()); | |||||
} | |||||
} // namespace dds | } // namespace dds | ||||
#endif // DDS_UTIL_HPP_INCLUDED | #endif // DDS_UTIL_HPP_INCLUDED |