Commit 7c05f4bd authored by jan.koester's avatar jan.koester
Browse files

bugs fixed

parent 180997b1
Loading
Loading
Loading
Loading
+18 −21
Changes for executor.cpp: 18 added lines, 21 removed lines.
Original line number Diff line number Diff line
@@ -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);
@@ -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;
            }
        }
    }
@@ -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) {
@@ -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) {
+2 −1
Changes for executor.h: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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);
+5 −0
Changes for parser.cpp: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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;