Loading main.cpp +66 −3 Changes for main.cpp: 66 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -240,9 +240,50 @@ int main(int argc, char* argv[]) { // Setup default variables setup_defaults(mf, argv[0]); // Apply command-line variables (highest priority) // GNU make propagates command-line variable overrides to every sub-make via // MAKEFLAGS: the portion after "--" holds NAME=value assignments (spaces in // a value are backslash-escaped). A child make re-reads them and gives them // command-line (highest) priority. Replicate that so a recipe like // $(MAKE) $(build)=objtool CFLAGS="$(OBJTOOL_CFLAGS)" // reaches the nested $(MAKE) descend that actually performs the compile // (the kernel tools/ build relies on this for its include flags). if (const char* mflags = getenv("MAKEFLAGS")) { std::string env_flags(mflags); size_t sep = env_flags.find("--"); if (sep != std::string::npos) { std::string overrides = env_flags.substr(sep + 2); std::vector<std::pair<std::string, std::string>> inherited; std::string word; auto flush = [&]() { if (word.empty()) return; size_t e = word.find('='); if (e != std::string::npos && e > 0) inherited.emplace_back(word.substr(0, e), word.substr(e + 1)); word.clear(); }; for (size_t i = 0; i < overrides.size(); ++i) { char c = overrides[i]; if (c == '\\' && i + 1 < overrides.size()) { word.push_back(overrides[++i]); // unescape "\<c>" -> "<c>" } else if (c == ' ' || c == '\t') { flush(); } else { word.push_back(c); } } flush(); // Inherited overrides come first so an override stated explicitly on // this invocation's command line still wins (applied last below). cmdline_vars.insert(cmdline_vars.begin(), inherited.begin(), inherited.end()); } } // Apply command-line variables (highest priority). Also export them into the // environment, like GNU make, so plain $$VAR references in recipes and any // child process observe the value. for (const auto& [name, value] : cmdline_vars) { mf.variables[name] = {value, makeplus::VarFlavor::Simple, true}; setenv(name.c_str(), value.c_str(), 1); } // MAKECMDGOALS and MAKEFLAGS must exist BEFORE parsing: build systems like Loading @@ -268,8 +309,30 @@ int main(int argc, char* argv[]) { std::string combined = flags; if (!words.empty()) combined += words; if (jobs > 1) combined += " -j" + std::to_string(jobs); mf.variables["MAKEFLAGS"] = {makeplus::Parser::trim(combined), makeplus::VarFlavor::Simple, false}; // Append command-line variable overrides after "--" so they propagate to // sub-makes (GNU make format; spaces/backslashes in a value are escaped). if (!cmdline_vars.empty()) { std::map<std::string, std::string> ov; std::vector<std::string> order; for (const auto& kv : cmdline_vars) { if (!ov.count(kv.first)) order.push_back(kv.first); ov[kv.first] = kv.second; // later (command-line) value wins } combined += " --"; for (const auto& name : order) { std::string esc; for (char c : ov[name]) { if (c == ' ' || c == '\t' || c == '\\') esc.push_back('\\'); esc.push_back(c); } combined += " " + name + "=" + esc; } } std::string mkflags = makeplus::Parser::trim(combined); mf.variables["MAKEFLAGS"] = {mkflags, makeplus::VarFlavor::Simple, false}; // MAKEFLAGS must be in the environment so a recursive $(MAKE) (a fresh // makeplus process) inherits the flags and the variable overrides above. setenv("MAKEFLAGS", mkflags.c_str(), 1); } // Parse makefile Loading Loading
main.cpp +66 −3 Changes for main.cpp: 66 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -240,9 +240,50 @@ int main(int argc, char* argv[]) { // Setup default variables setup_defaults(mf, argv[0]); // Apply command-line variables (highest priority) // GNU make propagates command-line variable overrides to every sub-make via // MAKEFLAGS: the portion after "--" holds NAME=value assignments (spaces in // a value are backslash-escaped). A child make re-reads them and gives them // command-line (highest) priority. Replicate that so a recipe like // $(MAKE) $(build)=objtool CFLAGS="$(OBJTOOL_CFLAGS)" // reaches the nested $(MAKE) descend that actually performs the compile // (the kernel tools/ build relies on this for its include flags). if (const char* mflags = getenv("MAKEFLAGS")) { std::string env_flags(mflags); size_t sep = env_flags.find("--"); if (sep != std::string::npos) { std::string overrides = env_flags.substr(sep + 2); std::vector<std::pair<std::string, std::string>> inherited; std::string word; auto flush = [&]() { if (word.empty()) return; size_t e = word.find('='); if (e != std::string::npos && e > 0) inherited.emplace_back(word.substr(0, e), word.substr(e + 1)); word.clear(); }; for (size_t i = 0; i < overrides.size(); ++i) { char c = overrides[i]; if (c == '\\' && i + 1 < overrides.size()) { word.push_back(overrides[++i]); // unescape "\<c>" -> "<c>" } else if (c == ' ' || c == '\t') { flush(); } else { word.push_back(c); } } flush(); // Inherited overrides come first so an override stated explicitly on // this invocation's command line still wins (applied last below). cmdline_vars.insert(cmdline_vars.begin(), inherited.begin(), inherited.end()); } } // Apply command-line variables (highest priority). Also export them into the // environment, like GNU make, so plain $$VAR references in recipes and any // child process observe the value. for (const auto& [name, value] : cmdline_vars) { mf.variables[name] = {value, makeplus::VarFlavor::Simple, true}; setenv(name.c_str(), value.c_str(), 1); } // MAKECMDGOALS and MAKEFLAGS must exist BEFORE parsing: build systems like Loading @@ -268,8 +309,30 @@ int main(int argc, char* argv[]) { std::string combined = flags; if (!words.empty()) combined += words; if (jobs > 1) combined += " -j" + std::to_string(jobs); mf.variables["MAKEFLAGS"] = {makeplus::Parser::trim(combined), makeplus::VarFlavor::Simple, false}; // Append command-line variable overrides after "--" so they propagate to // sub-makes (GNU make format; spaces/backslashes in a value are escaped). if (!cmdline_vars.empty()) { std::map<std::string, std::string> ov; std::vector<std::string> order; for (const auto& kv : cmdline_vars) { if (!ov.count(kv.first)) order.push_back(kv.first); ov[kv.first] = kv.second; // later (command-line) value wins } combined += " --"; for (const auto& name : order) { std::string esc; for (char c : ov[name]) { if (c == ' ' || c == '\t' || c == '\\') esc.push_back('\\'); esc.push_back(c); } combined += " " + name + "=" + esc; } } std::string mkflags = makeplus::Parser::trim(combined); mf.variables["MAKEFLAGS"] = {mkflags, makeplus::VarFlavor::Simple, false}; // MAKEFLAGS must be in the environment so a recursive $(MAKE) (a fresh // makeplus process) inherits the flags and the variable overrides above. setenv("MAKEFLAGS", mkflags.c_str(), 1); } // Parse makefile Loading