diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/runfiles/runfiles.cc | 34 | ||||
-rw-r--r-- | src/tools/runfiles/runfiles.h | 19 | ||||
-rw-r--r-- | src/tools/runfiles/runfiles_test.cc | 53 |
3 files changed, 99 insertions, 7 deletions
diff --git a/src/tools/runfiles/runfiles.cc b/src/tools/runfiles/runfiles.cc index 1de2f1a1f4..60d1ec3124 100644 --- a/src/tools/runfiles/runfiles.cc +++ b/src/tools/runfiles/runfiles.cc @@ -16,12 +16,15 @@ #include <fstream> #include <map> #include <sstream> +#include <vector> namespace bazel { namespace runfiles { using std::map; +using std::pair; using std::string; +using std::vector; namespace { @@ -52,6 +55,7 @@ class ManifestBased : public RunfilesImpl { // Returns nullptr upon failure. static ManifestBased* Create(const string& manifest_path, string* error); + vector<pair<string, string> > EnvVars() const override; string RlocationChecked(const string& path) const override; private: @@ -63,6 +67,7 @@ class ManifestBased : public RunfilesImpl { ManifestBased& operator=(const ManifestBased&) = delete; ManifestBased& operator=(ManifestBased&&) = delete; + string RunfilesDir() const; static bool ParseManifest(const string& path, map<string, string>* result, string* error); @@ -75,6 +80,7 @@ class DirectoryBased : public RunfilesImpl { public: DirectoryBased(string runfiles_path) : runfiles_path_(std::move(runfiles_path)) {} + vector<pair<string, string> > EnvVars() const override; string RlocationChecked(const string& path) const override; private: @@ -119,6 +125,26 @@ string ManifestBased::RlocationChecked(const string& path) const { return std::move(value == runfiles_map_.end() ? string() : value->second); } +vector<pair<string, string> > ManifestBased::EnvVars() const { + return std::move(vector<pair<string, string> >( + {std::make_pair("RUNFILES_MANIFEST_FILE", manifest_path_), + // TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can + // pick up RUNFILES_DIR. + std::make_pair("JAVA_RUNFILES", RunfilesDir())})); +} + +string ManifestBased::RunfilesDir() const { + const auto pos1 = manifest_path_.size() - 9; // "_MANIFEST" + const auto pos2 = manifest_path_.size() - 18; // ".runfiles_manifest" + if (manifest_path_.rfind("/MANIFEST") == pos1 || + manifest_path_.rfind("\\MANIFEST") == pos1 || + manifest_path_.rfind(".runfiles_manifest") == pos2) { + return std::move(manifest_path_.substr(0, pos1)); // remove ".MANIFEST" + } else { + return std::move(string()); + } +} + bool ManifestBased::ParseManifest(const string& path, map<string, string>* result, string* error) { std::ifstream stm(path); @@ -157,6 +183,14 @@ string DirectoryBased::RlocationChecked(const string& path) const { return std::move(runfiles_path_ + "/" + path); } +vector<pair<string, string> > DirectoryBased::EnvVars() const { + return std::move(vector<pair<string, string> >( + {std::make_pair("RUNFILES_DIR", runfiles_path_), + // TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can + // pick up RUNFILES_DIR. + std::make_pair("JAVA_RUNFILES", runfiles_path_)})); +} + } // namespace namespace testing { diff --git a/src/tools/runfiles/runfiles.h b/src/tools/runfiles/runfiles.h index 821cc1aa6f..b29981e7f6 100644 --- a/src/tools/runfiles/runfiles.h +++ b/src/tools/runfiles/runfiles.h @@ -19,7 +19,9 @@ #ifndef BAZEL_SRC_TOOLS_RUNFILES_RUNFILES_H_ #define BAZEL_SRC_TOOLS_RUNFILES_RUNFILES_H_ 1 +#include <memory> #include <string> +#include <vector> namespace bazel { namespace runfiles { @@ -28,11 +30,6 @@ class Runfiles { public: virtual ~Runfiles() {} - // TODO(laszlocsomor): implement: - // Runfiles* Create(const string& argv0, string* error); - // TODO(laszlocsomor): implement: - // vector<pair<string, string>> EnvVars(); - // Returns a new manifest-based `Runfiles` instance. // Returns nullptr on error. If `error` is provided, the method prints an // error message into it. @@ -63,6 +60,13 @@ class Runfiles { // an empty string if the method doesn't know about this runfile virtual std::string Rlocation(const std::string& path) const = 0; + // Returns environment variables for subprocesses. + // + // The caller should set the returned key-value pairs in the environment of + // subprocesses in case those subprocesses are also Bazel-built binaries that + // need to use runfiles. + virtual std::vector<std::pair<std::string, std::string> > EnvVars() const = 0; + protected: Runfiles() {} @@ -74,8 +78,9 @@ class Runfiles { }; // The "testing" namespace contains functions that allow unit testing the code. -// Do not use these outside of runfiles_test.cc, because they may change without -// notice. +// Do not use these outside of runfiles_test.cc, they are only part of the +// public API for the benefit of the tests. +// These functions and their interface may change without notice. namespace testing { // For testing only. diff --git a/src/tools/runfiles/runfiles_test.cc b/src/tools/runfiles/runfiles_test.cc index 408dfde2e1..71a9d1d413 100644 --- a/src/tools/runfiles/runfiles_test.cc +++ b/src/tools/runfiles/runfiles_test.cc @@ -172,6 +172,45 @@ TEST_F(RunfilesTest, DirectoryBasedRunfilesRlocation) { EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo"); } +TEST_F(RunfilesTest, ManifestBasedRunfilesEnvVars) { + const vector<string> suffixes({"/MANIFEST", ".runfiles_manifest", + "runfiles_manifest", ".runfiles", ".manifest", + ".txt"}); + for (vector<string>::size_type i = 0; i < suffixes.size(); ++i) { + unique_ptr<MockFile> mf( + MockFile::Create(string("foo" LINE()) + suffixes[i])); + EXPECT_TRUE(mf != nullptr) << " (suffix=\"" << suffixes[i] << "\")"; + + string error; + unique_ptr<Runfiles> r(Runfiles::CreateManifestBased(mf->Path(), &error)); + ASSERT_NE(r, nullptr) << " (suffix=\"" << suffixes[i] << "\")"; + EXPECT_TRUE(error.empty()); + + // The object can compute the runfiles directory when i=0 and i=1, but not + // when i>1 because the manifest file's name doesn't end in a well-known + // way. + const string expected_runfiles_dir( + i < 2 ? mf->Path().substr(0, mf->Path().size() - 9 /* "_manifest" */) + : ""); + vector<pair<string, string> > expected( + {{"RUNFILES_MANIFEST_FILE", mf->Path()}, + {"JAVA_RUNFILES", expected_runfiles_dir}}); + EXPECT_EQ(r->EnvVars(), expected) << " (suffix=\"" << suffixes[i] << "\")"; + } +} + +TEST_F(RunfilesTest, DirectoryBasedRunfilesEnvVars) { + string error; + unique_ptr<Runfiles> r( + Runfiles::CreateDirectoryBased("runfiles/dir", &error)); + ASSERT_NE(r, nullptr); + EXPECT_TRUE(error.empty()); + + vector<pair<string, string> > expected( + {{"RUNFILES_DIR", "runfiles/dir"}, {"JAVA_RUNFILES", "runfiles/dir"}}); + EXPECT_EQ(r->EnvVars(), expected); +} + TEST_F(RunfilesTest, FailsToCreateManifestBasedBecauseManifestDoesNotExist) { string error; unique_ptr<Runfiles> r( @@ -253,6 +292,20 @@ TEST_F(RunfilesTest, MockFileTest) { } } +TEST_F(RunfilesTest, IsAbsolute) { + EXPECT_FALSE(TestOnly_IsAbsolute("foo")); + EXPECT_FALSE(TestOnly_IsAbsolute("foo/bar")); + EXPECT_FALSE(TestOnly_IsAbsolute("\\foo")); + EXPECT_TRUE(TestOnly_IsAbsolute("c:\\foo")); + EXPECT_TRUE(TestOnly_IsAbsolute("c:/foo")); + EXPECT_TRUE(TestOnly_IsAbsolute("/foo")); + EXPECT_TRUE(TestOnly_IsAbsolute("x:\\foo")); + EXPECT_FALSE(TestOnly_IsAbsolute("::\\foo")); + EXPECT_FALSE(TestOnly_IsAbsolute("x\\foo")); + EXPECT_FALSE(TestOnly_IsAbsolute("x:")); + EXPECT_TRUE(TestOnly_IsAbsolute("x:\\")); +} + } // namespace } // namespace runfiles } // namespace bazel |