diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2019-10-09 12:08:45 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2019-10-09 12:08:45 +0200 |
commit | 66de0d06e5b6c002cbc7d18e18685e3ea44d3848 (patch) | |
tree | 34688ee9d0c4d00de0f58e2f6f017f026a23abe6 /libbuild2 | |
parent | 09e0cf71552d7f6e4f864b997db9913b9e9ae187 (diff) |
Prepend pattern search paths to PATH when running binutils
This way any dependent tools (such as mt.exe that is invoked by link.exe)
are first search for in there.
Diffstat (limited to 'libbuild2')
-rw-r--r-- | libbuild2/bin/init.cxx | 25 | ||||
-rw-r--r-- | libbuild2/bin/utility.hxx | 47 | ||||
-rw-r--r-- | libbuild2/cc/link-rule.cxx | 70 | ||||
-rw-r--r-- | libbuild2/parser.cxx | 11 | ||||
-rw-r--r-- | libbuild2/utility.hxx | 34 |
5 files changed, 139 insertions, 48 deletions
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx index 07888f6..db9db0e 100644 --- a/libbuild2/bin/init.cxx +++ b/libbuild2/bin/init.cxx @@ -20,6 +20,7 @@ #include <libbuild2/bin/rule.hxx> #include <libbuild2/bin/guess.hxx> #include <libbuild2/bin/target.hxx> +#include <libbuild2/bin/utility.hxx> using namespace std; using namespace butl; @@ -37,30 +38,6 @@ namespace build2 static const strings liba_lib {"static", "shared"}; static const strings libs_lib {"shared", "static"}; - struct pattern_paths - { - const char* pattern = nullptr; - const char* paths = nullptr; - }; - - static inline pattern_paths - lookup_pattern (scope& rs) - { - pattern_paths r; - - // Theoretically, we could have both the pattern and the search paths, - // for example, the pattern can come first followed by the paths. - // - if (const string* v = cast_null<string> (rs["bin.pattern"])) - { - (path::traits_type::is_separator (v->back ()) - ? r.paths - : r.pattern) = v->c_str (); - } - - return r; - } - bool vars_init (scope& rs, scope&, diff --git a/libbuild2/bin/utility.hxx b/libbuild2/bin/utility.hxx new file mode 100644 index 0000000..cc2b727 --- /dev/null +++ b/libbuild2/bin/utility.hxx @@ -0,0 +1,47 @@ +// file : libbuild2/bin/utility.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef LIBBUILD2_BIN_UTILITY_HXX +#define LIBBUILD2_BIN_UTILITY_HXX + +#include <libbuild2/types.hxx> +#include <libbuild2/utility.hxx> + +#include <libbuild2/scope.hxx> +#include <libbuild2/variable.hxx> + +namespace build2 +{ + namespace bin + { + // Lookup the bin.pattern value and split it into the pattern and the + // search paths. + // + struct pattern_paths + { + const char* pattern = nullptr; + const char* paths = nullptr; + }; + + inline pattern_paths + lookup_pattern (const scope& rs) + { + pattern_paths r; + + // Theoretically, we could have both the pattern and the search paths, + // for example, the pattern can come first followed by the paths. + // + if (const string* v = cast_null<string> (rs["bin.pattern"])) + { + (path::traits_type::is_separator (v->back ()) + ? r.paths + : r.pattern) = v->c_str (); + } + + return r; + } + } +} + +#endif // LIBBUILD2_BIN_UTILITY_HXX diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index cd31058..8aedcad 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -19,6 +19,7 @@ #include <libbuild2/diagnostics.hxx> #include <libbuild2/bin/target.hxx> +#include <libbuild2/bin/utility.hxx> #include <libbuild2/cc/target.hxx> // c, pc* #include <libbuild2/cc/utility.hxx> @@ -37,7 +38,7 @@ namespace build2 link_rule:: link_rule (data&& d) : common (move (d)), - rule_id (string (x) += ".link 1") + rule_id (string (x) += ".link 2") { static_assert (sizeof (match_data) <= target::data_size, "insufficient space"); @@ -1939,6 +1940,47 @@ namespace build2 // depdb dd (tp + ".d"); + // Adjust the environment. + // + using environment = small_vector<string, 1>; + environment env; + sha256 env_cs; + + // If we have the search paths in the binutils pattern, prepend them to + // the PATH environment variable so that any dependent tools (such as + // mt.exe that is invoked by link.exe) are first search for in there. + // + { + bin::pattern_paths pat (bin::lookup_pattern (rs)); + + if (pat.paths != nullptr) + { + string v ("PATH="); + v += pat.paths; + + env_cs.append (v); // Hash only what we are adding. + + if (optional<string> o = getenv ("PATH")) + { + v += path::traits_type::path_separator; + v += *o; + } + + env.push_back (move (v)); + } + } + + // Convert the environment to what's expected by the process API. + // + small_vector<const char*, environment::small_size + 1> env_ptrs; + if (!env.empty ()) + { + for (const string& v: env) + env_ptrs.push_back (v.c_str ()); + + env_ptrs.push_back (nullptr); + } + // If targeting Windows, take care of the manifest. // path manifest; // Manifest itself (msvc) or compiled object file. @@ -1989,7 +2031,13 @@ namespace build2 try { - process pr (rc, args, -1); + process pr (rc, + args, + -1 /* stdin */, + 1 /* stdout */, + 2 /* stderr */, + nullptr /* cwd */, + env_ptrs.empty () ? nullptr : env_ptrs.data ()); try { @@ -2090,6 +2138,11 @@ namespace build2 l4 ([&]{trace << "linker mismatch forcing update of " << t;}); } + // Hash and compare any changes to the environment. + // + if (dd.expect (env_cs.string ()) != nullptr) + l4 ([&]{trace << "environment mismatch forcing update of " << t;}); + // Next check the target. While it might be incorporated into the linker // checksum, it also might not (e.g., VC link.exe). // @@ -2905,7 +2958,13 @@ namespace build2 // bool filter (tsys == "win32-msvc" && !lt.static_library ()); - process pr (*ld, args.data (), 0, (filter ? -1 : 2)); + process pr (*ld, + args.data (), + 0 /* stdin */, + (filter ? -1 : 2) /* stdout */, + 2 /* stderr */, + nullptr /* cwd */, + env_ptrs.empty () ? nullptr : env_ptrs.data ()); if (filter) { @@ -2986,7 +3045,10 @@ namespace build2 print_process (args); if (!ctx.dry_run) - run (rl, args); + run (rl, + args, + dir_path () /* cwd */, + env_ptrs.empty () ? nullptr : env_ptrs.data ()); } // For Windows generate (or clean up) rpath-emulating assembly. diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index b33ba78..6e15cf3 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -1568,12 +1568,13 @@ namespace build2 [] (const string& s) {return s.c_str ();}); cargs.push_back (nullptr); - process pr (run_start (3 /* verbosity */, + process pr (run_start (3 /* verbosity */, cargs, - 0 /* stdin */, - -1 /* stdout */, - true /* error */, - empty_dir_path /* cwd */, + 0 /* stdin */, + -1 /* stdout */, + true /* error */, + dir_path () /* cwd */, + nullptr /* env */, l)); bool bad (false); try diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx index c362b34..980c31f 100644 --- a/libbuild2/utility.hxx +++ b/libbuild2/utility.hxx @@ -280,18 +280,20 @@ namespace build2 inline void run (const process_path& p, const char* args[], - const dir_path& cwd = dir_path ()) + const dir_path& cwd = dir_path (), + const char* const* env = nullptr) { - process pr (run_start (p, args, 0 /* stdin */, 1 /* stdout */, true, cwd)); + process pr (run_start (process_env (p, env), args, 0, 1, true, cwd)); run_finish (args, pr); } inline void run (const process_path& p, cstrings& args, - const dir_path& cwd = dir_path ()) + const dir_path& cwd = dir_path (), + const char* const* env = nullptr) { - run (p, args.data (), cwd); + run (p, args.data (), cwd, env); } // As above, but search for the process (including updating args[0]) and @@ -304,10 +306,14 @@ namespace build2 int out, bool error = true, const dir_path& cwd = dir_path (), + const char* const* env = nullptr, const location& l = location ()) { process_path pp (run_search (args[0], l)); - return run_start (verbosity, pp, args, in, out, error, cwd, l); + return run_start (verbosity, + process_env (pp, env), args, + in, out, error, + cwd, l); } inline process @@ -317,31 +323,29 @@ namespace build2 int out, bool error = true, const dir_path& cwd = dir_path (), + const char* const* env = nullptr, const location& l = location ()) { - return run_start (verbosity, args.data (), in, out, error, cwd, l); + return run_start (verbosity, args.data (), in, out, error, cwd, env, l); } inline void run (uint16_t verbosity, const char* args[], - const dir_path& cwd = dir_path ()) + const dir_path& cwd = dir_path (), + const char* const* env = nullptr) { - process pr (run_start (verbosity, - args, - 0 /* stdin */, - 1 /* stdout */, - true, - cwd)); + process pr (run_start (verbosity, args, 0, 1, true, cwd, env)); run_finish (args, pr); } inline void run (uint16_t verbosity, cstrings& args, - const dir_path& cwd = dir_path ()) + const dir_path& cwd = dir_path (), + const char* const* env = nullptr) { - run (verbosity, args.data (), cwd); + run (verbosity, args.data (), cwd, env); } // Start the process as above and then call the specified function on each |