Loading executor.cpp +18 −21 Changes for executor.cpp: 18 added lines, 21 removed lines. Original line number Diff line number Diff line Loading @@ -62,12 +62,14 @@ const Rule* Executor::find_rule(const std::string& target, std::string& stem) { } std::vector<std::string> Executor::expand_prereqs(const Rule* rule, const std::string& stem) { std::vector<std::string> Executor::expand_prereqs(const std::string& target, const Rule* rule, const std::string& stem) { std::vector<std::string> prereqs; // Collect prerequisites from the given rule for (const auto& p : rule->prerequisites) { auto add_prereqs = [&](const Rule* r, bool pattern) { for (const auto& p : r->prerequisites) { std::string ep = p; if (rule->is_pattern) { if (pattern) { size_t pct = ep.find('%'); while (pct != std::string::npos) { ep = ep.substr(0, pct) + stem + ep.substr(pct + 1); Loading @@ -78,27 +80,22 @@ std::vector<std::string> Executor::expand_prereqs(const Rule* rule, const std::s auto words = Parser::split_words(expanded); prereqs.insert(prereqs.end(), words.begin(), words.end()); } }; // If rule is a pattern/implicit rule, also collect prereqs from explicit rules // (GNU Make merges prerequisites from all matching rules) if (rule->is_pattern && !rule->targets.empty()) { std::string target_pattern = rule->targets[0]; // Find what target this was matched for - reconstruct from stem size_t pct = target_pattern.find('%'); if (pct != std::string::npos) { std::string actual_target = target_pattern.substr(0, pct) + stem + target_pattern.substr(pct + 1); // Collect prerequisites from the chosen rule. add_prereqs(rule, rule->is_pattern); // GNU Make merges prerequisites from all explicit rules for the same target. // CMake relies on this: a target's prerequisites are spread across several // rule lines, only one of which carries the recipe. Without merging, the // other prerequisites (e.g. the object files to link) are never built. for (const auto& r : mf_.rules) { if (r.is_pattern) continue; if (&r == rule) continue; for (const auto& t : r.targets) { if (t == actual_target) { for (const auto& p : r.prerequisites) { std::string expanded = parser_.expand(p, mf_); auto words = Parser::split_words(expanded); prereqs.insert(prereqs.end(), words.begin(), words.end()); } } } if (t == target) { add_prereqs(&r, false); break; } } } Loading Loading @@ -208,7 +205,7 @@ int Executor::build_sequential(const std::string& target) { return 2; } auto prereqs = expand_prereqs(rule, stem); auto prereqs = expand_prereqs(target, rule, stem); // Build all prerequisites for (const auto& prereq : prereqs) { Loading Loading @@ -245,7 +242,7 @@ void Executor::add_to_dag(const std::string& target, std::set<std::string>& visi node.rule = find_rule(target, node.stem); if (node.rule) { node.prereqs = expand_prereqs(node.rule, node.stem); node.prereqs = expand_prereqs(target, node.rule, node.stem); node.unresolved_deps = 0; for (const auto& p : node.prereqs) { Loading executor.h +2 −1 Changes for executor.h: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -63,7 +63,8 @@ private: // Shared helpers const Rule* find_rule(const std::string& target, std::string& stem); std::vector<std::string> expand_prereqs(const Rule* rule, const std::string& stem); std::vector<std::string> expand_prereqs(const std::string& target, const Rule* rule, const std::string& stem); bool needs_rebuild(const std::string& target, const std::vector<std::string>& prereqs); int execute_rule(const std::string& target, const Rule* rule, const std::string& stem, const std::vector<std::string>& prereqs); Loading parser.cpp +5 −0 Changes for parser.cpp: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -84,6 +84,11 @@ const Rule* Makefile::find_explicit_rule(const std::string& target) const { const Rule* Makefile::find_pattern_rule(const std::string& target, std::string& stem) const { for (const auto& rule : rules) { if (!rule.is_pattern) continue; // A pattern rule with no commands cancels a built-in rule rather than // building anything (GNU make semantics). CMake emits match-anything // rules like "% : %,v" to disable implicit RCS/SCCS rules; using them // here would cause infinite recursion (X -> X,v -> X,v,v -> ...). if (rule.recipes.empty()) continue; for (const auto& t : rule.targets) { size_t pct = t.find('%'); if (pct == std::string::npos) continue; Loading Loading
executor.cpp +18 −21 Changes for executor.cpp: 18 added lines, 21 removed lines. Original line number Diff line number Diff line Loading @@ -62,12 +62,14 @@ const Rule* Executor::find_rule(const std::string& target, std::string& stem) { } std::vector<std::string> Executor::expand_prereqs(const Rule* rule, const std::string& stem) { std::vector<std::string> Executor::expand_prereqs(const std::string& target, const Rule* rule, const std::string& stem) { std::vector<std::string> prereqs; // Collect prerequisites from the given rule for (const auto& p : rule->prerequisites) { auto add_prereqs = [&](const Rule* r, bool pattern) { for (const auto& p : r->prerequisites) { std::string ep = p; if (rule->is_pattern) { if (pattern) { size_t pct = ep.find('%'); while (pct != std::string::npos) { ep = ep.substr(0, pct) + stem + ep.substr(pct + 1); Loading @@ -78,27 +80,22 @@ std::vector<std::string> Executor::expand_prereqs(const Rule* rule, const std::s auto words = Parser::split_words(expanded); prereqs.insert(prereqs.end(), words.begin(), words.end()); } }; // If rule is a pattern/implicit rule, also collect prereqs from explicit rules // (GNU Make merges prerequisites from all matching rules) if (rule->is_pattern && !rule->targets.empty()) { std::string target_pattern = rule->targets[0]; // Find what target this was matched for - reconstruct from stem size_t pct = target_pattern.find('%'); if (pct != std::string::npos) { std::string actual_target = target_pattern.substr(0, pct) + stem + target_pattern.substr(pct + 1); // Collect prerequisites from the chosen rule. add_prereqs(rule, rule->is_pattern); // GNU Make merges prerequisites from all explicit rules for the same target. // CMake relies on this: a target's prerequisites are spread across several // rule lines, only one of which carries the recipe. Without merging, the // other prerequisites (e.g. the object files to link) are never built. for (const auto& r : mf_.rules) { if (r.is_pattern) continue; if (&r == rule) continue; for (const auto& t : r.targets) { if (t == actual_target) { for (const auto& p : r.prerequisites) { std::string expanded = parser_.expand(p, mf_); auto words = Parser::split_words(expanded); prereqs.insert(prereqs.end(), words.begin(), words.end()); } } } if (t == target) { add_prereqs(&r, false); break; } } } Loading Loading @@ -208,7 +205,7 @@ int Executor::build_sequential(const std::string& target) { return 2; } auto prereqs = expand_prereqs(rule, stem); auto prereqs = expand_prereqs(target, rule, stem); // Build all prerequisites for (const auto& prereq : prereqs) { Loading Loading @@ -245,7 +242,7 @@ void Executor::add_to_dag(const std::string& target, std::set<std::string>& visi node.rule = find_rule(target, node.stem); if (node.rule) { node.prereqs = expand_prereqs(node.rule, node.stem); node.prereqs = expand_prereqs(target, node.rule, node.stem); node.unresolved_deps = 0; for (const auto& p : node.prereqs) { Loading
executor.h +2 −1 Changes for executor.h: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -63,7 +63,8 @@ private: // Shared helpers const Rule* find_rule(const std::string& target, std::string& stem); std::vector<std::string> expand_prereqs(const Rule* rule, const std::string& stem); std::vector<std::string> expand_prereqs(const std::string& target, const Rule* rule, const std::string& stem); bool needs_rebuild(const std::string& target, const std::vector<std::string>& prereqs); int execute_rule(const std::string& target, const Rule* rule, const std::string& stem, const std::vector<std::string>& prereqs); Loading
parser.cpp +5 −0 Changes for parser.cpp: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -84,6 +84,11 @@ const Rule* Makefile::find_explicit_rule(const std::string& target) const { const Rule* Makefile::find_pattern_rule(const std::string& target, std::string& stem) const { for (const auto& rule : rules) { if (!rule.is_pattern) continue; // A pattern rule with no commands cancels a built-in rule rather than // building anything (GNU make semantics). CMake emits match-anything // rules like "% : %,v" to disable implicit RCS/SCCS rules; using them // here would cause infinite recursion (X -> X,v -> X,v,v -> ...). if (rule.recipes.empty()) continue; for (const auto& t : rule.targets) { size_t pct = t.find('%'); if (pct == std::string::npos) continue; Loading