Loading executor.cpp +24 −1 Changes for executor.cpp: 24 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -36,7 +36,30 @@ const Rule* Executor::find_rule(const std::string& target, std::string& stem) { // Explicit rule has no recipe - try pattern/implicit rules for recipe const Rule* pattern = mf_.find_pattern_rule(target, stem); if (pattern) return pattern; if (pattern) { // GNU make only applies an implicit rule when its prerequisites exist // or can themselves be made. Without this check a self-similar pattern // such as "x/%: x/%_shipped" would chain forever (x/ -> x/_shipped -> // x/_shipped_shipped -> ...), growing the target name until the process // runs out of memory. A prerequisite counts as satisfiable if the file // exists, an explicit rule produces it, or it is phony. bool viable = true; for (const auto& p : pattern->prerequisites) { std::string prereq = p; size_t ppct = prereq.find('%'); if (ppct != std::string::npos) { prereq = prereq.substr(0, ppct) + stem + prereq.substr(ppct + 1); } prereq = parser_.expand(prereq, mf_); if (prereq.empty()) continue; if (file_exists(prereq)) continue; if (mf_.find_explicit_rule(prereq)) continue; if (mf_.phony_targets.count(prereq)) continue; viable = false; break; } if (viable) return pattern; } // Built-in implicit rules static std::vector<Rule> builtins; Loading Loading
executor.cpp +24 −1 Changes for executor.cpp: 24 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -36,7 +36,30 @@ const Rule* Executor::find_rule(const std::string& target, std::string& stem) { // Explicit rule has no recipe - try pattern/implicit rules for recipe const Rule* pattern = mf_.find_pattern_rule(target, stem); if (pattern) return pattern; if (pattern) { // GNU make only applies an implicit rule when its prerequisites exist // or can themselves be made. Without this check a self-similar pattern // such as "x/%: x/%_shipped" would chain forever (x/ -> x/_shipped -> // x/_shipped_shipped -> ...), growing the target name until the process // runs out of memory. A prerequisite counts as satisfiable if the file // exists, an explicit rule produces it, or it is phony. bool viable = true; for (const auto& p : pattern->prerequisites) { std::string prereq = p; size_t ppct = prereq.find('%'); if (ppct != std::string::npos) { prereq = prereq.substr(0, ppct) + stem + prereq.substr(ppct + 1); } prereq = parser_.expand(prereq, mf_); if (prereq.empty()) continue; if (file_exists(prereq)) continue; if (mf_.find_explicit_rule(prereq)) continue; if (mf_.phony_targets.count(prereq)) continue; viable = false; break; } if (viable) return pattern; } // Built-in implicit rules static std::vector<Rule> builtins; Loading