-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
runfiles,C++: implement runfiles lib foundations
Implement the foundation of the C++ runfiles library, along with a directory-based Runfiles implementation. Subsequent commits will add more feataures: - manifest-based runfiles handling - creating list of envvars to pass to child processes - automatic Runfiles creation based on argv[0] and the envvars of this process See #4460 Change-Id: Id5a38619a1ae874499f04523863081559360410c PiperOrigin-RevId: 187031518
- Loading branch information
1 parent
726df7e
commit 9dfb1ee
Showing
4 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// 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" | ||
|
||
namespace bazel { | ||
namespace runfiles { | ||
|
||
using std::string; | ||
|
||
namespace { | ||
|
||
class RunfilesImpl : public Runfiles { | ||
public: | ||
// TODO(laszlocsomor): implement 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() {} | ||
}; | ||
|
||
// TODO(laszlocsomor): derive a ManifestBased class from RunfilesImpl. | ||
|
||
// 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)) {} | ||
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 IsAbsolute(const string& path) { | ||
if (path.empty()) { | ||
return false; | ||
} | ||
char c = path.front(); | ||
return (c == '/') || (path.size() >= 3 && | ||
((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) && | ||
path[1] == ':' && (path[2] == '\\' || path[2] == '/')); | ||
} | ||
|
||
string RunfilesImpl::Rlocation(const string& path) const { | ||
if (path.empty() || path.find("..") != string::npos) { | ||
return std::move(string()); | ||
} | ||
if (IsAbsolute(path)) { | ||
return path; | ||
} | ||
return RlocationChecked(path); | ||
} | ||
|
||
string DirectoryBased::RlocationChecked(const string& path) const { | ||
return std::move(runfiles_path_ + "/" + path); | ||
} | ||
|
||
} // namespace | ||
|
||
namespace testing { | ||
|
||
bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); } | ||
|
||
} // namespace testing | ||
|
||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// 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. | ||
|
||
// Runfiles lookup library for Bazel-built C++ binaries and tests. | ||
// | ||
// TODO(laszlocsomor): add usage information and examples. | ||
|
||
#ifndef BAZEL_SRC_TOOLS_RUNFILES_RUNFILES_H_ | ||
#define BAZEL_SRC_TOOLS_RUNFILES_RUNFILES_H_ 1 | ||
|
||
#include <string> | ||
|
||
namespace bazel { | ||
namespace runfiles { | ||
|
||
class Runfiles { | ||
public: | ||
virtual ~Runfiles() {} | ||
|
||
// TODO(laszlocsomor): implement: | ||
// Runfiles* Create(const string& argv0, string* error); | ||
// TODO(laszlocsomor): implement: | ||
// vector<pair<string, string>> EnvVars(); | ||
// TODO(laszlocsomor): implement: | ||
// Runfiles* CreateManifestBased(const string& path, string* error); | ||
|
||
// Returns a new directory-based `Runfiles` instance. | ||
// Returns nullptr on error. If `error` is provided, the method prints an | ||
// error message into it. | ||
static Runfiles* CreateDirectoryBased(const std::string& directory_path, | ||
std::string* error = nullptr); | ||
|
||
// Returns the runtime path of a runfile. | ||
// | ||
// Runfiles are data-dependencies of Bazel-built binaries and tests. | ||
// | ||
// The returned path may not be valid. The caller should check the path's | ||
// validity and that the path exists. | ||
// | ||
// The function may return an empty string. In that case the caller can be | ||
// sure that the Runfiles object does not know about this data-dependency. | ||
// | ||
// Args: | ||
// path: runfiles-root-relative path of the runfile; must not be empty and | ||
// must not contain uplevel references. | ||
// Returns: | ||
// the path to the runfile, which the caller should check for existence, or | ||
// an empty string if the method doesn't know about this runfile | ||
virtual std::string Rlocation(const std::string& path) const = 0; | ||
|
||
protected: | ||
Runfiles() {} | ||
|
||
private: | ||
Runfiles(const Runfiles&) = delete; | ||
Runfiles(Runfiles&&) = delete; | ||
Runfiles& operator=(const Runfiles&) = delete; | ||
Runfiles& operator=(Runfiles&&) = delete; | ||
}; | ||
|
||
// 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. | ||
namespace testing { | ||
|
||
// For testing only. | ||
// Returns true if `path` is an absolute Unix or Windows path. | ||
// For Windows paths, this function does not regard drive-less absolute paths | ||
// (i.e. absolute-on-current-drive, e.g. "\foo\bar") as absolute and returns | ||
// false for these. | ||
bool TestOnly_IsAbsolute(const std::string& path); | ||
|
||
} // namespace testing | ||
} // namespace runfiles | ||
} // namespace bazel | ||
|
||
#endif // BAZEL_SRC_TOOLS_RUNFILES_RUNFILES_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// 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 "src/tools/runfiles/runfiles.h" | ||
|
||
#include <memory> | ||
#include <string> | ||
|
||
#include "gtest/gtest.h" | ||
|
||
#define _T(x) #x | ||
#define T(x) _T(x) | ||
#define LINE() T(__LINE__) | ||
|
||
namespace bazel { | ||
namespace runfiles { | ||
namespace { | ||
|
||
using std::string; | ||
using std::unique_ptr; | ||
|
||
TEST(RunfilesTest, DirectoryBasedRunfilesRlocation) { | ||
string error; | ||
unique_ptr<Runfiles> r(Runfiles::CreateDirectoryBased("whatever", &error)); | ||
ASSERT_NE(r, nullptr); | ||
EXPECT_TRUE(error.empty()); | ||
|
||
EXPECT_EQ(r->Rlocation("a/b"), "whatever/a/b"); | ||
EXPECT_EQ(r->Rlocation("c/d"), "whatever/c/d"); | ||
EXPECT_EQ(r->Rlocation(""), ""); | ||
EXPECT_EQ(r->Rlocation("foo"), "whatever/foo"); | ||
EXPECT_EQ(r->Rlocation("foo/"), "whatever/foo/"); | ||
EXPECT_EQ(r->Rlocation("foo/bar"), "whatever/foo/bar"); | ||
EXPECT_EQ(r->Rlocation("foo/.."), ""); | ||
EXPECT_EQ(r->Rlocation("/Foo"), "/Foo"); | ||
EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo"); | ||
EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo"); | ||
} | ||
|
||
} // namespace | ||
} // namespace runfiles | ||
} // namespace bazel |