Loading parser.cpp +42 −1 Changes for parser.cpp: 42 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -989,7 +989,17 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren current_rule = nullptr; return true; } if (targets[0] == ".SUFFIXES" || targets[0] == ".PRECIOUS" || // ".SUFFIXES: .a .b" appends to the suffix list, a bare // ".SUFFIXES:" clears it if (targets[0] == ".SUFFIXES") { if (prereqs.empty()) mf.suffixes.clear(); for (const auto& p : prereqs) if (std::find(mf.suffixes.begin(), mf.suffixes.end(), p) == mf.suffixes.end()) mf.suffixes.push_back(p); current_rule = nullptr; return true; } if (targets[0] == ".PRECIOUS" || targets[0] == ".INTERMEDIATE" || targets[0] == ".SECONDARY" || targets[0] == ".DELETE_ON_ERROR" || targets[0] == ".NOTPARALLEL") { current_rule = nullptr; Loading @@ -1005,6 +1015,37 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren } } // Old-fashioned suffix rules: ".c.o:" (both known suffixes) is the // pattern rule "%.o: %.c", ".c:" is "%: %.c". Like GNU make, only // for a single target without prerequisites. if (!is_pattern && targets.size() == 1 && prereqs.empty() && order_only.empty() && targets[0].size() > 1 && targets[0][0] == '.' && targets[0].find('/') == std::string::npos) { const std::string& t = targets[0]; auto known = [&](const std::string& sfx) { return std::find(mf.suffixes.begin(), mf.suffixes.end(), sfx) != mf.suffixes.end(); }; std::string from, to; bool single = known(t); for (size_t i = 1; !single && i < t.size(); ++i) { if (t[i] != '.') continue; if (known(t.substr(0, i)) && known(t.substr(i))) { from = t.substr(0, i); to = t.substr(i); break; } } if (single) { targets = {"%"}; prereqs = {"%" + t}; is_pattern = true; } else if (!from.empty()) { targets = {"%" + to}; prereqs = {"%" + from}; is_pattern = true; } } mf.rules.push_back({targets, prereqs, order_only, {}, is_pattern, ""}); current_rule = &mf.rules.back(); Loading parser.h +7 −0 Changes for parser.h: 7 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -37,6 +37,13 @@ struct Makefile { std::set<std::string> phony_targets; std::string default_target; std::string base_dir; // The known suffixes for old-fashioned suffix rules (".c.o:"), in // .SUFFIXES order; starts out as GNU make's default list. std::vector<std::string> suffixes = { ".out", ".a", ".ln", ".o", ".c", ".cc", ".C", ".cpp", ".p", ".f", ".F", ".m", ".r", ".y", ".l", ".ym", ".yl", ".s", ".S", ".mod", ".sym", ".def", ".h", ".info", ".dvi", ".tex", ".texinfo", ".texi", ".txinfo", ".w", ".ch", ".web", ".sh", ".elc", ".el"}; // Target-specific variable assignments: target name -> list of bindings. // Applied (recursive flavor) while the target's recipes are expanded. // `append` records that the binding used '+=', so at apply time it appends Loading Loading
parser.cpp +42 −1 Changes for parser.cpp: 42 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -989,7 +989,17 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren current_rule = nullptr; return true; } if (targets[0] == ".SUFFIXES" || targets[0] == ".PRECIOUS" || // ".SUFFIXES: .a .b" appends to the suffix list, a bare // ".SUFFIXES:" clears it if (targets[0] == ".SUFFIXES") { if (prereqs.empty()) mf.suffixes.clear(); for (const auto& p : prereqs) if (std::find(mf.suffixes.begin(), mf.suffixes.end(), p) == mf.suffixes.end()) mf.suffixes.push_back(p); current_rule = nullptr; return true; } if (targets[0] == ".PRECIOUS" || targets[0] == ".INTERMEDIATE" || targets[0] == ".SECONDARY" || targets[0] == ".DELETE_ON_ERROR" || targets[0] == ".NOTPARALLEL") { current_rule = nullptr; Loading @@ -1005,6 +1015,37 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren } } // Old-fashioned suffix rules: ".c.o:" (both known suffixes) is the // pattern rule "%.o: %.c", ".c:" is "%: %.c". Like GNU make, only // for a single target without prerequisites. if (!is_pattern && targets.size() == 1 && prereqs.empty() && order_only.empty() && targets[0].size() > 1 && targets[0][0] == '.' && targets[0].find('/') == std::string::npos) { const std::string& t = targets[0]; auto known = [&](const std::string& sfx) { return std::find(mf.suffixes.begin(), mf.suffixes.end(), sfx) != mf.suffixes.end(); }; std::string from, to; bool single = known(t); for (size_t i = 1; !single && i < t.size(); ++i) { if (t[i] != '.') continue; if (known(t.substr(0, i)) && known(t.substr(i))) { from = t.substr(0, i); to = t.substr(i); break; } } if (single) { targets = {"%"}; prereqs = {"%" + t}; is_pattern = true; } else if (!from.empty()) { targets = {"%" + to}; prereqs = {"%" + from}; is_pattern = true; } } mf.rules.push_back({targets, prereqs, order_only, {}, is_pattern, ""}); current_rule = &mf.rules.back(); Loading
parser.h +7 −0 Changes for parser.h: 7 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -37,6 +37,13 @@ struct Makefile { std::set<std::string> phony_targets; std::string default_target; std::string base_dir; // The known suffixes for old-fashioned suffix rules (".c.o:"), in // .SUFFIXES order; starts out as GNU make's default list. std::vector<std::string> suffixes = { ".out", ".a", ".ln", ".o", ".c", ".cc", ".C", ".cpp", ".p", ".f", ".F", ".m", ".r", ".y", ".l", ".ym", ".yl", ".s", ".S", ".mod", ".sym", ".def", ".h", ".info", ".dvi", ".tex", ".texinfo", ".texi", ".txinfo", ".w", ".ch", ".web", ".sh", ".elc", ".el"}; // Target-specific variable assignments: target name -> list of bindings. // Applied (recursive flavor) while the target's recipes are expanded. // `append` records that the binding used '+=', so at apply time it appends Loading