aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/runfiles/runfiles.cc
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2018-04-30 03:29:21 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-04-30 03:30:49 -0700
commit819bf38d97e6eef3c823bdae3ffcdb013d6d83e3 (patch)
treef18d8d0cc5e34061c5c46514b18b9e5608f3d566 /src/tools/runfiles/runfiles.cc
parenteb35e41242e1f9fb0ae1061623272c891237c8a8 (diff)
c++,runfiles: move runfiles library
Move the half-done C++ runfiles library to `//tools/cpp/runfiles`. (The Python and Bash runfiles libraries are already under `//tools/<language>/runfiles`.) See https://github.com/bazelbuild/bazel/issues/4460 Change-Id: I1006f7f81462ea0e4b1de1adcdba89e386d4f9e7 Closes #5107. Change-Id: I1006f7f81462ea0e4b1de1adcdba89e386d4f9e7 PiperOrigin-RevId: 194763392
Diffstat (limited to 'src/tools/runfiles/runfiles.cc')
-rw-r--r--src/tools/runfiles/runfiles.cc350
1 files changed, 0 insertions, 350 deletions
diff --git a/src/tools/runfiles/runfiles.cc b/src/tools/runfiles/runfiles.cc
deleted file mode 100644
index 801e44e374..0000000000
--- a/src/tools/runfiles/runfiles.cc
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2018 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include "tools/runfiles/runfiles.h"
-
-#ifdef COMPILER_MSVC
-#include <windows.h>
-#else // not COMPILER_MSVC
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif // COMPILER_MSVC
-
-#include <fstream>
-#include <map>
-#include <sstream>
-#include <vector>
-
-#ifdef COMPILER_MSVC
-#include <memory>
-#endif // COMPILER_MSVC
-
-namespace bazel {
-namespace runfiles {
-
-using std::function;
-using std::map;
-using std::pair;
-using std::string;
-using std::vector;
-
-namespace {
-
-bool starts_with(const string& s, const string& prefix) {
- if (prefix.empty()) {
- return true;
- }
- if (s.empty()) {
- return false;
- }
- return s.find(prefix) == 0;
-}
-
-bool contains(const string& s, const string& substr) {
- if (substr.empty()) {
- return true;
- }
- if (s.empty()) {
- return false;
- }
- return s.find(substr) != string::npos;
-}
-
-bool ends_with(const string& s, const string& suffix) {
- if (suffix.empty()) {
- return true;
- }
- if (s.empty()) {
- return false;
- }
- return s.rfind(suffix) == s.size() - suffix.size();
-}
-
-class RunfilesImpl : public Runfiles {
- public:
- static Runfiles* Create(const string& argv0,
- function<string(const string&)> env_lookup,
- string* error);
-
- string Rlocation(const string& path) const override;
-
- // Returns the runtime-location of a given runfile.
- //
- // This method assumes that the caller already validated the `path`. See
- // Runfiles::Rlocation for requirements.
- virtual string RlocationChecked(const string& path) const = 0;
-
- protected:
- RunfilesImpl() {}
- virtual ~RunfilesImpl() {}
-};
-
-// Runfiles implementation that parses a runfiles-manifest to look up runfiles.
-class ManifestBased : public RunfilesImpl {
- public:
- // Returns a new `ManifestBased` instance.
- // Reads the file at `manifest_path` to build a map of the runfiles.
- // 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:
- ManifestBased(const string& manifest_path, map<string, string>&& runfiles_map)
- : manifest_path_(manifest_path), runfiles_map_(runfiles_map) {}
-
- ManifestBased(const ManifestBased&) = delete;
- ManifestBased(ManifestBased&&) = delete;
- ManifestBased& operator=(const ManifestBased&) = delete;
- ManifestBased& operator=(ManifestBased&&) = delete;
-
- string RunfilesDir() const;
- static bool ParseManifest(const string& path, map<string, string>* result,
- string* error);
-
- const string manifest_path_;
- const map<string, string> runfiles_map_;
-};
-
-// Runfiles implementation that appends runfiles paths to the runfiles root.
-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:
- DirectoryBased(const DirectoryBased&) = delete;
- DirectoryBased(DirectoryBased&&) = delete;
- DirectoryBased& operator=(const DirectoryBased&) = delete;
- DirectoryBased& operator=(DirectoryBased&&) = delete;
-
- const string runfiles_path_;
-};
-
-bool IsReadableFile(const string& path) {
- return std::ifstream(path).is_open();
-}
-
-bool IsDirectory(const string& path) {
-#ifdef COMPILER_MSVC
- DWORD attrs = GetFileAttributesA(path.c_str());
- return (attrs != INVALID_FILE_ATTRIBUTES) &&
- (attrs & FILE_ATTRIBUTE_DIRECTORY);
-#else
- struct stat buf;
- return stat(path.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode);
-#endif
-}
-
-Runfiles* RunfilesImpl::Create(const string& argv0,
- function<string(const string&)> env_lookup,
- string* error) {
- string manifest(std::move(env_lookup("RUNFILES_MANIFEST_FILE")));
- if (!manifest.empty()) {
- return ManifestBased::Create(manifest, error);
- }
-
- string directory(std::move(env_lookup("RUNFILES_DIR")));
- if (!directory.empty()) {
- return new DirectoryBased(directory);
- }
-
- manifest = argv0 + ".runfiles_manifest";
- if (IsReadableFile(manifest)) {
- return CreateManifestBased(manifest, error);
- }
-
- manifest = argv0 + ".runfiles/MANIFEST";
- if (IsReadableFile(manifest)) {
- return CreateManifestBased(manifest, error);
- }
-
- directory = argv0 + ".runfiles";
- if (IsDirectory(directory)) {
- return CreateDirectoryBased(std::move(directory), error);
- }
-
- if (error) {
- std::ostringstream err;
- err << "ERROR: " << __FILE__ << "(" << __LINE__
- << "): cannot find runfiles (argv0=\"" << argv0 << "\")";
- *error = err.str();
- }
- return nullptr;
-}
-
-bool IsAbsolute(const string& path) {
- if (path.empty()) {
- return false;
- }
- char c = path.front();
- return (c == '/' && (path.size() < 2 || path[1] != '/')) ||
- (path.size() >= 3 &&
- ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) &&
- path[1] == ':' && (path[2] == '\\' || path[2] == '/'));
-}
-
-string GetEnv(const string& key) {
-#ifdef COMPILER_MSVC
- DWORD size = ::GetEnvironmentVariableA(key.c_str(), NULL, 0);
- if (size == 0) {
- return std::move(string()); // unset or empty envvar
- }
- std::unique_ptr<char[]> value(new char[size]);
- ::GetEnvironmentVariableA(key.c_str(), value.get(), size);
- return move(string(value.get()));
-#else
- char* result = getenv(key.c_str());
- return std::move((result == NULL) ? string() : string(result));
-#endif
-}
-
-string RunfilesImpl::Rlocation(const string& path) const {
- if (path.empty() || starts_with(path, "../") || contains(path, "/..") ||
- starts_with(path, "./") || contains(path, "/./") ||
- ends_with(path, "/.") || contains(path, "//")) {
- return std::move(string());
- }
- if (IsAbsolute(path)) {
- return path;
- }
- return RlocationChecked(path);
-}
-
-ManifestBased* ManifestBased::Create(const string& manifest_path,
- string* error) {
- map<string, string> runfiles;
- return ParseManifest(manifest_path, &runfiles, error)
- ? new ManifestBased(manifest_path, std::move(runfiles))
- : nullptr;
-}
-
-string ManifestBased::RlocationChecked(const string& path) const {
- const auto value = runfiles_map_.find(path);
- 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);
- if (!stm.is_open()) {
- if (error) {
- std::ostringstream err;
- err << "ERROR: " << __FILE__ << "(" << __LINE__
- << "): cannot open runfiles manifest \"" << path << "\"";
- *error = err.str();
- }
- return false;
- }
- string line;
- std::getline(stm, line);
- size_t line_count = 1;
- while (!line.empty()) {
- string::size_type idx = line.find_first_of(' ');
- if (idx == string::npos) {
- if (error) {
- std::ostringstream err;
- err << "ERROR: " << __FILE__ << "(" << __LINE__
- << "): bad runfiles manifest entry in \"" << path << "\" line #"
- << line_count << ": \"" << line << "\"";
- *error = err.str();
- }
- return false;
- }
- (*result)[line.substr(0, idx)] = line.substr(idx + 1);
- std::getline(stm, line);
- ++line_count;
- }
- return true;
-}
-
-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 {
-
-Runfiles* TestOnly_CreateRunfiles(const std::string& argv0,
- function<string(const string&)> env_lookup,
- string* error) {
- return RunfilesImpl::Create(argv0, env_lookup, error);
-}
-
-bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); }
-
-} // namespace testing
-
-Runfiles* Runfiles::Create(const string& argv0, string* error) {
- return RunfilesImpl::Create(
- argv0,
- [](const string& key) {
- if (key == "RUNFILES_MANIFEST_FILE" || key == "RUNFILES_DIR") {
- string val(GetEnv(key));
- return std::move(val);
- } else {
- return std::move(string());
- }
- },
- error);
-}
-
-Runfiles* Runfiles::CreateManifestBased(const string& manifest_path,
- string* error) {
- return ManifestBased::Create(manifest_path, error);
-}
-
-Runfiles* Runfiles::CreateDirectoryBased(const string& directory_path,
- string* error) {
- // Note: `error` is intentionally unused because we don't expect any errors
- // here. We expect an `error` pointer so that we may use it in the future if
- // need be, without having to change the API.
- return new DirectoryBased(directory_path);
-}
-
-} // namespace runfiles
-} // namespace bazel