summaryrefslogtreecommitdiffhomepage
path: root/Builder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Builder.cpp')
-rw-r--r--Builder.cpp147
1 files changed, 92 insertions, 55 deletions
diff --git a/Builder.cpp b/Builder.cpp
index 51ac90f..86f6920 100644
--- a/Builder.cpp
+++ b/Builder.cpp
@@ -60,6 +60,16 @@ namespace {
return sources;
}
+ // get link libs of single target, ptree is <build> subtree
+ std::vector<std::string> get_link_libs_of_build(const pt::ptree& ptree) {
+ std::vector<std::string> linklibs;
+ for (const pt::ptree::value_type &v: ptree) {
+ if (v.first == "linklib")
+ linklibs.push_back(v.second.data());
+ }
+ return linklibs;
+ }
+
// ptree is main tree
std::vector<fs::path> get_all_sources(const pt::ptree& ptree) {
std::vector<fs::path> result;
@@ -105,20 +115,6 @@ namespace {
return t_p < t_other;
}
- // outdated according to dependency file list, non-recursively
- bool is_outdated(const fs::path& p, const std::vector<fs::path> &dependencies) {
- if (!fs::exists(p))
- return true;
-
- for (const auto& dep: dependencies) {
- if (!fs::exists(dep) || is_older(p, dep)) {
- return true;
- }
- }
-
- return false;
- }
-
std::vector<fs::path> deps_from_depfile(const fs::path& path) {
std::string depfile_content{Reichwein::File::getFile(path)};
std::vector<std::string> parts {Reichwein::Stringhelper::split(depfile_content, ":\r\n")};
@@ -138,43 +134,19 @@ namespace {
return depfile;
}
- // return contained dependencies
- // input: cpp
- std::vector<fs::path> make_depfile_from(const fs::path& p) {
- fs::path depfile{depfile_name_from(p)};
-
- // check if depfile exists and if it contains up to date info
- if (!fs::exists(depfile) || is_outdated(depfile, deps_from_depfile(depfile))) {
- // actually create depfile
- int result{system(fmt::format("g++ -MM -MF {} -c {}", depfile.string(), p.string()).c_str())};
- if (result != 0) {
- throw std::runtime_error(fmt::format("Depfile {} can't be created", depfile.string()));
- }
- }
-
- return deps_from_depfile(depfile);
- }
-
- std::unordered_map<fs::path, std::vector<fs::path>> get_dependencies(const pt::ptree& ptree) {
- std::unordered_map<fs::path, std::vector<fs::path>> dependencies;
+ std::unordered_map<fs::path, std::vector<std::string>> get_link_libs(const pt::ptree& ptree) {
+ std::unordered_map<fs::path, std::vector<std::string>> link_libs_map;
for (const auto& build: ptree.get_child("ymake")) {
if (build.first == "build") {
- dependencies.emplace(get_target(build.second), get_objects(build.second));
-
- std::vector<fs::path> sources{get_sources(build.second)};
- for (const auto& p: sources) {
- fs::path p_obj{p};
- p_obj.replace_extension("o");
- std::vector<fs::path> deps {make_depfile_from(p)};
- // keep .d files for now to speed dependencies detection on following runs
- //fs::remove(depfile_name_from(p));
- dependencies.emplace(p_obj, deps);
+ std::vector<std::string> link_libs{get_link_libs_of_build(build.second)};
+ if (!link_libs.empty()) {
+ link_libs_map.emplace(get_target(build.second), link_libs);
}
}
}
- return dependencies;
+ return link_libs_map;
}
}
@@ -182,7 +154,8 @@ namespace {
Builder::Builder(const pt::ptree& ptree):
_ptree(ptree),
_all_targets{get_all_targets(ptree)},
- _all_objects{get_all_objects(ptree)}
+ _all_objects{get_all_objects(ptree)},
+ _link_libs{get_link_libs(ptree)}
{
// intentionally defer creation of _dependencies to build()
// to prevent creation of .d files in clean()
@@ -197,6 +170,15 @@ std::vector<fs::path> Builder::dependencies_of(const fs::path& p) const
}
}
+std::vector<std::string> Builder::link_libs_of(const fs::path& p) const
+{
+ try {
+ return _link_libs.at(p);
+ } catch (const std::out_of_range& ex) {
+ return {}; // empty by default
+ }
+}
+
// outdated according to dependency tree, recursively
bool Builder::is_outdated(const fs::path& p) const
{
@@ -217,24 +199,79 @@ bool Builder::is_outdated(const fs::path& p) const
return false;
}
+// outdated according to dependency file list, non-recursively
+bool Builder::is_outdated(const fs::path& p, const std::vector<fs::path> &dependencies) const
+{
+ if (!fs::exists(p))
+ return true;
+
+ for (const auto& dep: dependencies) {
+ if (!fs::exists(dep) || is_older(p, dep)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// return contained dependencies
+// input: cpp
+std::vector<fs::path> Builder::make_depfile_from(const fs::path& p) const
+{
+ fs::path depfile{depfile_name_from(p)};
+
+ // check if depfile exists and if it contains up to date info
+ if (!fs::exists(depfile) || is_outdated(depfile, deps_from_depfile(depfile))) {
+ // actually create depfile
+ int result{system(_lang.getDepCommand(depfile.string(), p.string()).c_str())};
+ if (result != 0) {
+ throw std::runtime_error(fmt::format("Depfile {} can't be created", depfile.string()));
+ }
+ }
+
+ return deps_from_depfile(depfile);
+}
+
+std::unordered_map<fs::path, std::vector<fs::path>> Builder::get_dependencies(const pt::ptree& ptree) const
+{
+ std::unordered_map<fs::path, std::vector<fs::path>> dependencies;
+
+ for (const auto& build: ptree.get_child("ymake")) {
+ if (build.first == "build") {
+ dependencies.emplace(get_target(build.second), get_objects(build.second));
+
+ std::vector<fs::path> sources{get_sources(build.second)};
+ for (const auto& p: sources) {
+ fs::path p_obj{p};
+ p_obj.replace_extension("o");
+ std::vector<fs::path> deps {make_depfile_from(p)};
+ // keep .d files for now to speed dependencies detection on following runs
+ //fs::remove(depfile_name_from(p));
+ dependencies.emplace(p_obj, deps);
+ }
+ }
+ }
+
+ return dependencies;
+}
+
// build 1 file
void Builder::build_file(const fs::path& p) {
std::string command;
if (p.extension() == ".o") {
- // compile
- fs::path cppfile{p};
- cppfile.replace_extension("cpp");
- command = fmt::format("g++ -std=c++17 -c {} -o {}", cppfile.string(), p.string());
+ // compile
+ std::vector<fs::path> source_files{dependencies_of(p)};
+ auto it{std::find_if(source_files.begin(), source_files.end(), is_compile_unit_source_by_extension)};
+ if (it == source_files.end()) {
+ throw std::runtime_error(fmt::format("No source file found for {}", p.string()));
+ }
+ command = _lang.getCompileCommand(p, *it);
} else {
// link
- command = "g++";
std::vector<fs::path> objects{dependencies_of(p)};
- for (auto &i: objects) {
- command += fmt::format(" {}", i.string());
- }
- command += " -lreichwein -lfmt";
- command += fmt::format(" -o {}", p.string());
+ std::vector<std::string> link_libs{link_libs_of(p)};
+ command = _lang.getLinkCommand(p, objects, link_libs);
}
std::cout << command << std::endl;