Improve install_paths handling for relative paths. (#4331)

Because install_paths is not presently validated, and it's resolved
after the `SetWorkingDirForBazel` call, if a relative path is used with
bazel then it would fail silently. This starts making the driver share
install path errors, and starts changing how `//toolchain` launches
`carbon`.

Note the implementation is still brittle and will break with symlinks.
That's something I plan to address as part of busyboxing.
This commit is contained in:
Jon Ross-Perkins
2024-09-23 22:26:53 +00:00
committed by GitHub
parent edc6ed3d10
commit c7057eff89
8 changed files with 78 additions and 10 deletions
+1 -1
View File
@@ -6,5 +6,5 @@
# available.
alias(
name = "toolchain",
actual = "//toolchain/install:prefix_root/bin/carbon",
actual = "//toolchain/install:run_carbon",
)
+6 -2
View File
@@ -19,15 +19,19 @@ auto main(int argc, char** argv) -> int {
return EXIT_FAILURE;
}
// Resolve paths before calling SetWorkingDirForBazel.
std::string exe_path = Carbon::FindExecutablePath(argv[0]);
const auto install_paths = Carbon::InstallPaths::MakeExeRelative(exe_path);
if (install_paths.error()) {
llvm::errs() << "error: " << *install_paths.error();
return EXIT_FAILURE;
}
Carbon::SetWorkingDirForBazel();
llvm::SmallVector<llvm::StringRef> args(argv + 1, argv + argc);
auto fs = llvm::vfs::getRealFileSystem();
const auto install_paths = Carbon::InstallPaths::MakeExeRelative(exe_path);
Carbon::Driver driver(*fs, &install_paths, llvm::outs(), llvm::errs());
bool success = driver.RunCommand(args).success;
return success ? EXIT_SUCCESS : EXIT_FAILURE;
+8
View File
@@ -7,6 +7,7 @@ load("@llvm-project//llvm:binary_alias.bzl", "binary_alias")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_files", "pkg_mklink", "strip_prefix")
load("pkg_helpers.bzl", "pkg_naming_variables", "pkg_tar_and_test")
load("run_tool.bzl", "run_tool")
load("symlink_filegroup.bzl", "symlink_filegroup")
package(default_visibility = ["//visibility:public"])
@@ -230,3 +231,10 @@ pkg_tar_and_test(
],
test_install_marker = ":install_marker",
)
# Support `bazel run` on specific binaries.
run_tool(
name = "run_carbon",
data = [":install_data"],
tool = "prefix_root/bin/carbon",
)
+14
View File
@@ -44,6 +44,11 @@ auto InstallPaths::MakeExeRelative(llvm::StringRef exe_path) -> InstallPaths {
llvm::sys::path::remove_filename(paths.prefix_);
llvm::sys::path::append(paths.prefix_, llvm::sys::path::Style::posix, "../");
if (auto error = llvm::sys::fs::make_absolute(paths.prefix_)) {
paths.SetError(error.message());
return paths;
}
paths.CheckMarkerFile();
return paths;
}
@@ -67,6 +72,11 @@ auto InstallPaths::MakeForBazelRunfiles(llvm::StringRef exe_path)
llvm::sys::path::append(paths.prefix_, llvm::sys::path::Style::posix,
"../../");
if (auto error = llvm::sys::fs::make_absolute(paths.prefix_)) {
paths.SetError(error.message());
return paths;
}
paths.CheckMarkerFile();
CARBON_CHECK(!paths.error(), "{0}", *paths.error());
return paths;
@@ -125,6 +135,10 @@ auto InstallPaths::SetError(llvm::Twine message) -> void {
}
auto InstallPaths::CheckMarkerFile() -> void {
if (!llvm::sys::path::is_absolute(prefix_)) {
SetError(llvm::Twine("Not an absolute path: ") + prefix_);
}
llvm::SmallString<256> path(prefix_);
llvm::sys::path::append(path, llvm::sys::path::Style::posix, MarkerPath);
if (!llvm::sys::fs::exists(path)) {
+12 -6
View File
@@ -32,10 +32,10 @@ namespace Carbon {
// - MakeForBazelRunfiles for locating through Bazel's runfile tree.
// - Make for an explicit path, for example in tests.
//
// When locating an install, we verify it by
// looking for the `carbon_install.txt` marker file at a specific location
// below. When errors occur, the install prefix is made empty, and error() can
// be used for diagnostics; InstallPaths remains minimally functional.
// When locating an install, we verify it by looking for the
// `carbon_install.txt` marker file at a specific location below. When errors
// occur, the install prefix is made empty, and error() can be used for
// diagnostics; InstallPaths remains minimally functional.
//
// Within this prefix, we expect a hierarchy on Unix-y platforms:
//
@@ -83,8 +83,9 @@ class InstallPaths {
// fails for any reason, it will `CARBON_CHECK` fail with the error message.
static auto MakeForBazelRunfiles(llvm::StringRef exe_path) -> InstallPaths;
// Provide an explicit install paths prefix. This is useful for testing or for
// using Carbon in an environment with an unusual path to the installed files.
// Provide an explicit install paths prefix, which must be absolute. This is
// useful for testing or for using Carbon in an environment with an unusual
// path to the installed files.
static auto Make(llvm::StringRef install_prefix) -> InstallPaths;
// Returns the contents of the prelude manifest file. This is the list of
@@ -106,6 +107,11 @@ class InstallPaths {
// `prefix_root` directory in Bazel's output, or to some prefix the toolchain
// is installed into on a system such as `/usr/local` or `/home/$USER`.
//
// This will be an absolute path. We keep an absolute path for when the
// command line uses a relative path (`./bin/carbon`) and the working
// directory changes after initialization (for example, to Bazel's working
// directory).
//
// In the event of an error, this will be the empty string.
auto prefix() const -> llvm::StringRef { return prefix_; }
+1 -1
View File
@@ -118,7 +118,7 @@ TEST_F(InstallPathsTest, BinaryRunfiles) {
}
TEST_F(InstallPathsTest, Errors) {
auto paths = InstallPaths::Make("foo/bar/baz");
auto paths = InstallPaths::Make("/foo/bar/baz");
EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz")));
EXPECT_THAT(paths.prefix(), Eq(""));
+17
View File
@@ -0,0 +1,17 @@
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
# Exceptions. See /LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""Supports running a tool from the install filegroup."""
load("@rules_python//python:defs.bzl", "py_binary")
def run_tool(name, tool, data):
# TODO: Fix the driver file discovery in order to allow symlinks.
py_binary(
name = name,
main = "run_tool.py",
srcs = ["run_tool.py"],
args = ["$(location {})".format(tool)],
data = [tool] + data,
)
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
"""Runs the tool specified in argv.
This script is essentially just a bounce-through to get an appropriate arg0.
See the TODO in run_tool.bzl.
"""
__copyright__ = """
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
import os
import sys
if __name__ == "__main__":
os.execv(sys.argv[1], sys.argv[1:])