aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/bin/init.cxx25
-rw-r--r--libbuild2/bin/utility.hxx47
-rw-r--r--libbuild2/cc/link-rule.cxx70
-rw-r--r--libbuild2/parser.cxx11
-rw-r--r--libbuild2/utility.hxx34
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