Commit cfe158db authored by jan.koester's avatar jan.koester
Browse files

append in execute

parent 42cd23d8
Loading
Loading
Loading
Loading
+16 −2
Changes for executor.cpp: 16 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -296,8 +296,22 @@ int Executor::execute_rule(const std::string& target, const Rule* rule,
        if (entry.first != target && !pattern_key_matches(entry.first, target)) continue;
        if (entry.second.empty()) continue;
        if (!have_overrides) { local_copy = mf_; have_overrides = true; }
        for (const auto& kv : entry.second)
            local_copy.variables[kv.first] = {kv.second, VarFlavor::Recursive, false};
        for (const auto& kv : entry.second) {
            std::string value = kv.value;
            if (kv.append) {
                // GNU make: a target-specific 'VAR += x' appends to the value
                // VAR has in the surrounding scope. Resolve that base value now.
                auto git = mf_.variables.find(kv.name);
                std::string base;
                if (git != mf_.variables.end()) {
                    base = (git->second.flavor == VarFlavor::Recursive)
                        ? parser_.expand(git->second.value, mf_) : git->second.value;
                }
                value = base.empty() ? kv.value
                                     : base + " " + kv.value;
            }
            local_copy.variables[kv.name] = {value, VarFlavor::Recursive, false};
        }
    }
    if (have_overrides) mfp = &local_copy;
    // Export marked variables into the environment so recipes and any
+10 −5
Changes for parser.cpp: 10 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -849,15 +849,20 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren
                auto& vec = mf.target_vars[t];
                bool found = false;
                for (auto& pr : vec) {
                    if (pr.first == tv_name) {
                        pr.second = (tv_op == "+=")
                            ? (pr.second.empty() ? val : pr.second + " " + val)
                            : val;
                    if (pr.name == tv_name) {
                        if (tv_op == "+=") {
                            pr.value = pr.value.empty() ? val : pr.value + " " + val;
                        } else {
                            pr.value = val;
                            pr.append = false;
                        }
                        found = true;
                        break;
                    }
                }
                if (!found) vec.push_back({tv_name, val});
                // A first-time '+=' must append to whatever value the variable
                // has in the surrounding (global) scope when the recipe runs.
                if (!found) vec.push_back({tv_name, val, tv_op == "+="});
            }
            current_rule = nullptr;
            return true;
+9 −2
Changes for parser.h: 9 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -37,9 +37,16 @@ struct Makefile {
    std::set<std::string> phony_targets;
    std::string default_target;
    std::string base_dir;
    // Target-specific variable assignments: target name -> list of (name, value).
    // Target-specific variable assignments: target name -> list of bindings.
    // Applied (recursive flavor) while the target's recipes are expanded.
    std::map<std::string, std::vector<std::pair<std::string, std::string>>> target_vars;
    // `append` records that the binding used '+=', so at apply time it appends
    // to the value the variable would otherwise have (GNU make semantics).
    struct TargetVar {
        std::string name;
        std::string value;
        bool append = false;
    };
    std::map<std::string, std::vector<TargetVar>> target_vars;
    // Variables marked for export into the recipe / sub-make environment.
    std::set<std::string> exported;
    bool export_all = false;