summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Maennich <maennich@google.com>2021-11-08 22:26:27 +0000
committerMatthias Maennich <maennich@google.com>2021-11-09 18:48:32 +0000
commitabd3c5f79420405903661c8c86656aca5b6a2b96 (patch)
tree3fe565f22097b2c83669b5101db5f6000fc721ec
parentc55b76cbf334d18096d4224ca0193e0d66de00d0 (diff)
downloadbuild-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/interceptor7
-rw-r--r--interceptor/interceptor.cc48
-rw-r--r--interceptor/interceptor.h3
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_;