diff options
author | Matthias Maennich <maennich@google.com> | 2021-11-08 22:26:27 +0000 |
---|---|---|
committer | Matthias Maennich <maennich@google.com> | 2021-11-09 18:48:32 +0000 |
commit | abd3c5f79420405903661c8c86656aca5b6a2b96 (patch) | |
tree | 3fe565f22097b2c83669b5101db5f6000fc721ec | |
parent | c55b76cbf334d18096d4224ca0193e0d66de00d0 (diff) | |
download | build-tools-abd3c5f79420405903661c8c86656aca5b6a2b96.tar.gz |
Interceptor: relativate execution based on `cwd`
`ROOT_DIR` - if set, otherwise assume `cwd` - is assumed to be the
directory all execution is done relatively to. Hence, when rewriting
commands, do it with that directory as a base.
The interceptor wrapper is determining the INTERCEPTOR_root_dir based on
either ROOT_DIR or falls back to `cwd`.
Bug: 205577427
Signed-off-by: Matthias Maennich <maennich@google.com>
Change-Id: Ifef91ce7ae446d1a6cea7a744f36d0ff27cb4b3e
-rw-r--r-- | interceptor/interceptor | 7 | ||||
-rw-r--r-- | interceptor/interceptor.cc | 48 | ||||
-rw-r--r-- | interceptor/interceptor.h | 3 |
3 files changed, 57 insertions, 1 deletions
diff --git a/interceptor/interceptor b/interceptor/interceptor index e57b3e3..54ab449 100644 --- a/interceptor/interceptor +++ b/interceptor/interceptor @@ -43,6 +43,13 @@ if [ -n "$COMMAND_LOG" ]; then echo "[" > "$INTERCEPTOR_command_log" fi +# If ROOT_DIR is not set, assume the current working directory is it +if [ -z "$ROOT_DIR" ]; then + export INTERCEPTOR_root_dir=$(pwd) +else + export INTERCEPTOR_root_dir=$ROOT_DIR +fi + # Discover the interceptor preload library export LD_PRELOAD=$(realpath $(dirname $(readlink -f $0))/../lib64/libinterceptor.so) if [ ! -x "$LD_PRELOAD" ]; then diff --git a/interceptor/interceptor.cc b/interceptor/interceptor.cc index 71f67a2..98b8e5e 100644 --- a/interceptor/interceptor.cc +++ b/interceptor/interceptor.cc @@ -35,6 +35,7 @@ namespace fs = std::filesystem; // Options passed via environment variables from the interceptor starter constexpr static auto ENV_command_log = "INTERCEPTOR_command_log"; +constexpr static auto ENV_root_dir = "INTERCEPTOR_root_dir"; // UTILITY function declarations @@ -121,6 +122,45 @@ std::string Command::repr() const { os << "}"; return os.str(); } + +void Command::make_relative() { + // determine the ROOT_DIR + std::string root_dir; + if (auto it = env().find(ENV_root_dir); it != env().cend()) { + root_dir = it->second; + if (root_dir[root_dir.size() - 1] != '/') root_dir += '/'; + } else { + return; + } + + // determine the relative path to ROOT_DIR from the current working dir + std::string rel_root = fs::relative(root_dir); + if (rel_root[rel_root.size() - 1] != '/') rel_root += '/'; + if (rel_root == "./") rel_root = ""; + + // TODO: This is generally bad as this means we can't make anything relative. + // This happens if the out dir is outside of the root. + if (rel_root.find(root_dir) != std::string::npos) { + return; + } + + cwd_ = fs::relative(cwd_, root_dir); + + // replacement functor + const auto replace_all = [&](auto& str) { + auto pos = std::string::npos; + while ((pos = str.find(root_dir)) != std::string::npos) { + str.replace(pos, root_dir.length(), rel_root); + } + }; + + if (!args_.has_value()) args(); + + // now go and replace everything + replace_all(program_); + std::for_each(args_->begin(), args_->end(), replace_all); +} + } // namespace interceptor /// UTILITY FUNCTIONS @@ -133,9 +173,15 @@ static void process_command(const char* filename, char* const argv[], char* cons return; } - // Ok, we can handle that one, let's log it. + // Ok, we can handle that one, let's transform it. interceptor::Command command(filename, argv, envp); + + // rewrite all command line arguments (including the program itself) to use + // paths relative to ROOT_DIR. This is essential for reproducible builds and + // furthermore necessary to produce cache hits in RBE. + command.make_relative(); + log(command, ""); // pass down the transformed command to execve diff --git a/interceptor/interceptor.h b/interceptor/interceptor.h index 3944bde..77b137a 100644 --- a/interceptor/interceptor.h +++ b/interceptor/interceptor.h @@ -41,6 +41,9 @@ class Command { std::string repr() const; + // make command line calls relative to ROOT_DIR + void make_relative(); + private: std::string program_; std::string cwd_; |