diff options
author | Laszlo Csomor <laszlocsomor@google.com> | 2018-04-30 03:29:21 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-04-30 03:30:49 -0700 |
commit | 819bf38d97e6eef3c823bdae3ffcdb013d6d83e3 (patch) | |
tree | f18d8d0cc5e34061c5c46514b18b9e5608f3d566 /src/tools/runfiles/runfiles.cc | |
parent | eb35e41242e1f9fb0ae1061623272c891237c8a8 (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.cc | 350 |
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 |