Skip to content

Commit fc9a6ff

Browse files
committed
Use _repo_mapping in C++ runfiles library
Work towards #16124 Closes #16701. PiperOrigin-RevId: 487806351 Change-Id: I3b04fef84d817b0875bfd71c65efe6db13468b13
1 parent feed6ce commit fc9a6ff

File tree

4 files changed

+127
-153
lines changed

4 files changed

+127
-153
lines changed

src/test/py/bazel/bzlmod/bazel_module_test.py

+52
Original file line numberDiff line numberDiff line change
@@ -694,5 +694,57 @@ def testRunfilesRepoMappingManifest(self):
694694
self.Path('bazel-bin/external/bar~2.0/bar.runfiles_manifest')) as f:
695695
self.assertIn('_repo_mapping ', f.read())
696696

697+
def testCppRunfilesLibraryRepoMapping(self):
698+
self.main_registry.setModuleBasePath('projects')
699+
projects_dir = self.main_registry.projects
700+
701+
self.main_registry.createLocalPathModule('data', '1.0', 'data')
702+
projects_dir.joinpath('data').mkdir(exist_ok=True)
703+
scratchFile(projects_dir.joinpath('data', 'WORKSPACE'))
704+
scratchFile(projects_dir.joinpath('data', 'foo.txt'), ['hello'])
705+
scratchFile(
706+
projects_dir.joinpath('data', 'BUILD'), ['exports_files(["foo.txt"])'])
707+
708+
self.main_registry.createLocalPathModule('test', '1.0', 'test',
709+
{'data': '1.0'})
710+
projects_dir.joinpath('test').mkdir(exist_ok=True)
711+
scratchFile(projects_dir.joinpath('test', 'WORKSPACE'))
712+
scratchFile(
713+
projects_dir.joinpath('test', 'BUILD'), [
714+
'cc_test(',
715+
' name = "test",',
716+
' srcs = ["test.cpp"],',
717+
' data = ["@data//:foo.txt"],',
718+
' args = ["$(rlocationpath @data//:foo.txt)"],',
719+
' deps = ["@bazel_tools//tools/cpp/runfiles"],',
720+
')',
721+
])
722+
scratchFile(
723+
projects_dir.joinpath('test', 'test.cpp'), [
724+
'#include <cstdlib>',
725+
'#include <fstream>',
726+
'#include "tools/cpp/runfiles/runfiles.h"',
727+
'using bazel::tools::cpp::runfiles::Runfiles;',
728+
'int main(int argc, char** argv) {',
729+
' Runfiles* runfiles = Runfiles::Create(argv[0], BAZEL_CURRENT_REPOSITORY);',
730+
' std::ifstream f1(runfiles->Rlocation(argv[1]));',
731+
' if (!f1.good()) std::exit(1);',
732+
' std::ifstream f2(runfiles->Rlocation("data/foo.txt"));',
733+
' if (!f2.good()) std::exit(2);',
734+
'}',
735+
])
736+
737+
self.ScratchFile('MODULE.bazel', ['bazel_dep(name="test",version="1.0")'])
738+
self.ScratchFile('WORKSPACE')
739+
740+
# Run sandboxed on Linux and macOS.
741+
exit_code, stderr, stdout = self.RunBazel(
742+
['test', '@test//:test', '--test_output=errors'], allow_failure=True)
743+
self.AssertExitCode(exit_code, 0, stderr, stdout)
744+
# Run unsandboxed on all platforms.
745+
exit_code, stderr, stdout = self.RunBazel(['run', '@test//:test'],
746+
allow_failure=True)
747+
self.AssertExitCode(exit_code, 0, stderr, stdout)
748+
697749
if __name__ == '__main__':
698750
unittest.main()

tools/cpp/runfiles/runfiles_src.cc

+29-63
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,13 @@ bool IsDirectory(const string& path) {
9696

9797
bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file,
9898
std::string runfiles_dir, std::string* out_manifest,
99-
std::string* out_directory, std::string* out_repo_mapping);
99+
std::string* out_directory);
100100

101101
bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file,
102102
std::string runfiles_dir,
103103
std::function<bool(const std::string&)> is_runfiles_manifest,
104104
std::function<bool(const std::string&)> is_runfiles_directory,
105-
std::function<bool(const std::string&)> is_repo_mapping,
106-
std::string* out_manifest, std::string* out_directory,
107-
std::string* out_repo_mapping);
105+
std::string* out_manifest, std::string* out_directory);
108106

109107
bool ParseManifest(const string& path, map<string, string>* result,
110108
string* error);
@@ -117,9 +115,9 @@ Runfiles* Runfiles::Create(const string& argv0,
117115
const string& runfiles_manifest_file,
118116
const string& runfiles_dir,
119117
const string& source_repository, string* error) {
120-
string manifest, directory, repo_mapping;
118+
string manifest, directory;
121119
if (!PathsFrom(argv0, runfiles_manifest_file, runfiles_dir, &manifest,
122-
&directory, &repo_mapping)) {
120+
&directory)) {
123121
if (error) {
124122
std::ostringstream err;
125123
err << "ERROR: " << __FILE__ << "(" << __LINE__
@@ -144,10 +142,10 @@ Runfiles* Runfiles::Create(const string& argv0,
144142
}
145143

146144
map<pair<string, string>, string> mapping;
147-
if (!repo_mapping.empty()) {
148-
if (!ParseRepoMapping(repo_mapping, &mapping, error)) {
149-
return nullptr;
150-
}
145+
if (!ParseRepoMapping(
146+
RlocationUnchecked("_repo_mapping", runfiles, directory), &mapping,
147+
error)) {
148+
return nullptr;
151149
}
152150

153151
return new Runfiles(std::move(runfiles), std::move(directory),
@@ -196,28 +194,28 @@ string Runfiles::Rlocation(const string& path,
196194
return path;
197195
}
198196

199-
if (repo_mapping_.empty()) {
200-
return RlocationUnchecked(path);
201-
}
202197
string::size_type first_slash = path.find_first_of('/');
203198
if (first_slash == string::npos) {
204-
return RlocationUnchecked(path);
199+
return RlocationUnchecked(path, runfiles_map_, directory_);
205200
}
206201
string target_apparent = path.substr(0, first_slash);
207202
auto target =
208203
repo_mapping_.find(std::make_pair(source_repo, target_apparent));
209204
if (target == repo_mapping_.cend()) {
210-
return RlocationUnchecked(path);
205+
return RlocationUnchecked(path, runfiles_map_, directory_);
211206
}
212-
return RlocationUnchecked(target->second + path.substr(first_slash));
207+
return RlocationUnchecked(target->second + path.substr(first_slash),
208+
runfiles_map_, directory_);
213209
}
214210

215-
string Runfiles::RlocationUnchecked(const string& path) const {
216-
const auto exact_match = runfiles_map_.find(path);
217-
if (exact_match != runfiles_map_.end()) {
211+
string Runfiles::RlocationUnchecked(const string& path,
212+
const map<string, string>& runfiles_map,
213+
const string& directory) {
214+
const auto exact_match = runfiles_map.find(path);
215+
if (exact_match != runfiles_map.end()) {
218216
return exact_match->second;
219217
}
220-
if (!runfiles_map_.empty()) {
218+
if (!runfiles_map.empty()) {
221219
// If path references a runfile that lies under a directory that itself is a
222220
// runfile, then only the directory is listed in the manifest. Look up all
223221
// prefixes of path in the manifest and append the relative path from the
@@ -226,14 +224,14 @@ string Runfiles::RlocationUnchecked(const string& path) const {
226224
while ((prefix_end = path.find_last_of('/', prefix_end - 1)) !=
227225
string::npos) {
228226
const string prefix = path.substr(0, prefix_end);
229-
const auto prefix_match = runfiles_map_.find(prefix);
230-
if (prefix_match != runfiles_map_.end()) {
227+
const auto prefix_match = runfiles_map.find(prefix);
228+
if (prefix_match != runfiles_map.end()) {
231229
return prefix_match->second + "/" + path.substr(prefix_end + 1);
232230
}
233231
}
234232
}
235-
if (!directory_.empty()) {
236-
return directory_ + "/" + path;
233+
if (!directory.empty()) {
234+
return directory + "/" + path;
237235
}
238236
return "";
239237
}
@@ -279,13 +277,7 @@ bool ParseRepoMapping(const string& path,
279277
string* error) {
280278
std::ifstream stm(path);
281279
if (!stm.is_open()) {
282-
if (error) {
283-
std::ostringstream err;
284-
err << "ERROR: " << __FILE__ << "(" << __LINE__
285-
<< "): cannot open repository mapping \"" << path << "\"";
286-
*error = err.str();
287-
}
288-
return false;
280+
return true;
289281
}
290282
string line;
291283
std::getline(stm, line);
@@ -333,12 +325,9 @@ namespace testing {
333325
bool TestOnly_PathsFrom(const string& argv0, string mf, string dir,
334326
function<bool(const string&)> is_runfiles_manifest,
335327
function<bool(const string&)> is_runfiles_directory,
336-
function<bool(const string&)> is_repo_mapping,
337-
string* out_manifest, string* out_directory,
338-
string* out_repo_mapping) {
328+
string* out_manifest, string* out_directory) {
339329
return PathsFrom(argv0, mf, dir, is_runfiles_manifest, is_runfiles_directory,
340-
is_repo_mapping, out_manifest, out_directory,
341-
out_repo_mapping);
330+
out_manifest, out_directory);
342331
}
343332

344333
bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); }
@@ -376,23 +365,19 @@ Runfiles* Runfiles::CreateForTest(std::string* error) {
376365
namespace {
377366

378367
bool PathsFrom(const string& argv0, string mf, string dir, string* out_manifest,
379-
string* out_directory, string* out_repo_mapping) {
368+
string* out_directory) {
380369
return PathsFrom(
381370
argv0, mf, dir, [](const string& path) { return IsReadableFile(path); },
382-
[](const string& path) { return IsDirectory(path); },
383-
[](const string& path) { return IsReadableFile(path); }, out_manifest,
384-
out_directory, out_repo_mapping);
371+
[](const string& path) { return IsDirectory(path); }, out_manifest,
372+
out_directory);
385373
}
386374

387375
bool PathsFrom(const string& argv0, string mf, string dir,
388376
function<bool(const string&)> is_runfiles_manifest,
389377
function<bool(const string&)> is_runfiles_directory,
390-
function<bool(const string&)> is_repo_mapping,
391-
string* out_manifest, string* out_directory,
392-
string* out_repo_mapping) {
378+
string* out_manifest, string* out_directory) {
393379
out_manifest->clear();
394380
out_directory->clear();
395-
out_repo_mapping->clear();
396381

397382
bool mfValid = is_runfiles_manifest(mf);
398383
bool dirValid = is_runfiles_directory(dir);
@@ -428,21 +413,6 @@ bool PathsFrom(const string& argv0, string mf, string dir,
428413
dirValid = is_runfiles_directory(dir);
429414
}
430415

431-
string rm;
432-
bool rmValid = false;
433-
434-
if (dirValid && ends_with(dir, ".runfiles")) {
435-
rm = dir.substr(0, dir.size() - 9) + ".repo_mapping";
436-
rmValid = is_repo_mapping(rm);
437-
}
438-
439-
if (!rmValid && mfValid &&
440-
(ends_with(mf, ".runfiles_manifest") ||
441-
ends_with(mf, ".runfiles/MANIFEST"))) {
442-
rm = mf.substr(0, mf.size() - 18) + ".repo_mapping";
443-
rmValid = is_repo_mapping(rm);
444-
}
445-
446416
if (mfValid) {
447417
*out_manifest = mf;
448418
}
@@ -451,10 +421,6 @@ bool PathsFrom(const string& argv0, string mf, string dir,
451421
*out_directory = dir;
452422
}
453423

454-
if (rmValid) {
455-
*out_repo_mapping = rm;
456-
}
457-
458424
return true;
459425
}
460426

tools/cpp/runfiles/runfiles_src.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,17 @@ class Runfiles {
206206
Runfiles& operator=(const Runfiles&) = delete;
207207
Runfiles& operator=(Runfiles&&) = delete;
208208

209+
static std::string RlocationUnchecked(
210+
const std::string& path,
211+
const std::map<std::string, std::string>& runfiles_map,
212+
const std::string& directory);
213+
209214
const std::map<std::string, std::string> runfiles_map_;
210215
const std::string directory_;
211216
const std::map<std::pair<std::string, std::string>, std::string>
212217
repo_mapping_;
213218
const std::vector<std::pair<std::string, std::string> > envvars_;
214219
const std::string source_repository_;
215-
216-
std::string RlocationUnchecked(const std::string& path) const;
217220
};
218221

219222
// The "testing" namespace contains functions that allow unit testing the code.
@@ -243,9 +246,7 @@ bool TestOnly_PathsFrom(
243246
std::string runfiles_dir,
244247
std::function<bool(const std::string&)> is_runfiles_manifest,
245248
std::function<bool(const std::string&)> is_runfiles_directory,
246-
std::function<bool(const std::string&)> is_repo_mapping,
247-
std::string* out_manifest, std::string* out_directory,
248-
std::string* out_repo_mapping);
249+
std::string* out_manifest, std::string* out_directory);
249250

250251
// For testing only.
251252
// Returns true if `path` is an absolute Unix or Windows path.

0 commit comments

Comments
 (0)