From 0b9bda10b7add48f2b02bc2524e980c31a214895 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 5 Oct 2022 17:34:04 -0700 Subject: [PATCH] Refactor common main logic (#2260) 1) toolchain and explorer use the same working dir logic, share it 2) explorer's carbon.cpp and main_bin.cpp use the same relative path logic, share it 3) You can append a longer path in one call with the right kind of iterator 4) Fix what's maybe a bug in passing `relative_prelude_path.str()` to `cl::init` 5) Collapse Main and ExplorerMain to avoid passing more parameters between --- common/BUILD | 8 +++++++ common/bazel_working_dir.h | 31 +++++++++++++++++++++++++++ explorer/BUILD | 3 ++- explorer/main.cpp | 36 +++++++++++++++++++------------- explorer/main.h | 7 ++++--- explorer/main_bin.cpp | 31 +++++++-------------------- installers/local/carbon.cpp | 16 ++++---------- toolchain/driver/BUILD | 1 + toolchain/driver/driver_main.cpp | 11 ++-------- 9 files changed, 82 insertions(+), 62 deletions(-) create mode 100644 common/bazel_working_dir.h diff --git a/common/BUILD b/common/BUILD index f02050bf5c14..21bcdea218a0 100644 --- a/common/BUILD +++ b/common/BUILD @@ -4,6 +4,14 @@ package(default_visibility = ["//visibility:public"]) +cc_library( + name = "bazel_working_dir", + hdrs = ["bazel_working_dir.h"], + deps = [ + "@llvm-project//llvm:Support", + ], +) + cc_library( name = "check", srcs = ["check_internal.h"], diff --git a/common/bazel_working_dir.h b/common/bazel_working_dir.h new file mode 100644 index 000000000000..eaa6d50eeaac --- /dev/null +++ b/common/bazel_working_dir.h @@ -0,0 +1,31 @@ +// 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 + +#ifndef CARBON_COMMON_BAZEL_WORKING_DIR_H_ +#define CARBON_COMMON_BAZEL_WORKING_DIR_H_ + +#include "llvm/Support/FileSystem.h" + +namespace Carbon { + +// Behave as if the working directory is where `bazel run` was invoked. +// This should only be used in development binaries, not release. +inline auto SetWorkingDirForBazel() -> bool { + char* build_working_dir = getenv("BUILD_WORKING_DIRECTORY"); + if (build_working_dir == nullptr) { + return true; + } + + if (std::error_code err = + llvm::sys::fs::set_current_path(build_working_dir)) { + llvm::errs() << "Failed to set working directory: " << err.message(); + return false; + } + + return true; +} + +} // namespace Carbon + +#endif // CARBON_COMMON_BAZEL_WORKING_DIR_H_ diff --git a/explorer/BUILD b/explorer/BUILD index 5c7b00b3912c..3b1071acdafe 100644 --- a/explorer/BUILD +++ b/explorer/BUILD @@ -33,11 +33,12 @@ cc_library( cc_binary( name = "explorer", srcs = ["main_bin.cpp"], + env = macos_malloc_env(), deps = [ ":main", + "//common:bazel_working_dir", "@llvm-project//llvm:Support", ], - env = macos_malloc_env(), ) py_binary( diff --git a/explorer/main.cpp b/explorer/main.cpp index 263487223867..b1dddd3fb97c 100644 --- a/explorer/main.cpp +++ b/explorer/main.cpp @@ -19,16 +19,20 @@ #include "explorer/interpreter/exec_program.h" #include "explorer/syntax/parse.h" #include "explorer/syntax/prelude.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" namespace Carbon { namespace cl = llvm::cl; +namespace path = llvm::sys::path; -static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[]) - -> bool { +auto ExplorerMain(int argc, char** argv, void* static_for_main_addr, + llvm::StringRef relative_prelude_path) -> int { llvm::setBugReportMsg( "Please report issues to " "https://github.com/carbon-language/carbon-lang/issues and include the " @@ -47,9 +51,18 @@ static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[]) "trace_file", cl::desc("Output file for tracing; set to `-` to output to stdout.")); - // Find the path of the executable if possible and use that as a relative root + // Use the executable path as a base for the relative prelude path. + std::string exe = + llvm::sys::fs::getMainExecutable(argv[0], static_for_main_addr); + llvm::StringRef install_path = path::parent_path(exe); + llvm::SmallString<256> default_prelude_file(install_path); + path::append(default_prelude_file, + path::begin(relative_prelude_path, path::Style::posix), + path::end(relative_prelude_path)); + std::string default_prelude_file_str(default_prelude_file); cl::opt prelude_file_name("prelude", cl::desc(""), - cl::init(default_prelude_file.str())); + cl::init(default_prelude_file_str)); + cl::ParseCommandLineOptions(argc, argv); // Set up a stream for trace output. @@ -64,7 +77,7 @@ static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[]) std::make_unique(trace_file_name, err); if (err) { llvm::errs() << err.message() << "\n"; - return false; + return EXIT_FAILURE; } trace_stream = scoped_trace_stream.get(); } @@ -77,7 +90,7 @@ static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[]) ast = *std::move(parse_result); } else { llvm::errs() << "SYNTAX ERROR: " << parse_result.error() << "\n"; - return false; + return EXIT_FAILURE; } AddPrelude(prelude_file_name, &arena, &ast.declarations); @@ -88,7 +101,7 @@ static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[]) ast = *std::move(analyze_result); } else { llvm::errs() << "COMPILATION ERROR: " << analyze_result.error() << "\n"; - return false; + return EXIT_FAILURE; } // Run the program. @@ -103,15 +116,10 @@ static auto Main(llvm::StringRef default_prelude_file, int argc, char* argv[]) } } else { llvm::errs() << "RUNTIME ERROR: " << exec_result.error() << "\n"; - return false; + return EXIT_FAILURE; } - return true; -} - -auto ExplorerMain(llvm::StringRef default_prelude_file, int argc, char** argv) - -> int { - return Main(default_prelude_file, argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE; + return EXIT_SUCCESS; } } // namespace Carbon diff --git a/explorer/main.h b/explorer/main.h index f06bba4329cb..73916609416f 100644 --- a/explorer/main.h +++ b/explorer/main.h @@ -9,9 +9,10 @@ namespace Carbon { -// Runs explorer. -auto ExplorerMain(llvm::StringRef default_prelude_file, int argc, char** argv) - -> int; +// Runs explorer. relative_prelude_path must be POSIX-style, not native, and +// will be translated to native. +auto ExplorerMain(int argc, char** argv, void* static_for_main_addr, + llvm::StringRef relative_prelude_path) -> int; } // namespace Carbon diff --git a/explorer/main_bin.cpp b/explorer/main_bin.cpp index 8b1aece01f83..722eca8e70b2 100644 --- a/explorer/main_bin.cpp +++ b/explorer/main_bin.cpp @@ -2,31 +2,16 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include "common/bazel_working_dir.h" #include "explorer/main.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" auto main(int argc, char** argv) -> int { - // This assumes execution from `bazel-bin/explorer`, either directly or with - // `bazel run`. + Carbon::SetWorkingDirForBazel(); + static int static_for_main_addr; - std::string exe = llvm::sys::fs::getMainExecutable( - argv[0], static_cast(&static_for_main_addr)); - llvm::SmallString<256> prelude_path = llvm::sys::path::parent_path(exe); - llvm::sys::path::append(prelude_path, "explorer.runfiles", "carbon", - "explorer", "data"); - llvm::sys::path::append(prelude_path, "prelude.carbon"); - - // Behave as if the working directory is where `bazel run` was invoked. - char* build_working_dir = getenv("BUILD_WORKING_DIRECTORY"); - if (build_working_dir != nullptr) { - if (std::error_code err = - llvm::sys::fs::set_current_path(build_working_dir)) { - llvm::errs() << "Failed to set working directory: " << err.message(); - return 1; - } - } - - return Carbon::ExplorerMain(prelude_path, argc, argv); + return Carbon::ExplorerMain( + argc, argv, static_cast(&static_for_main_addr), + // This assumes execution from `bazel-bin/explorer`, either directly or + // with `bazel run`. + "explorer.runfiles/carbon/explorer/data/prelude.carbon"); } diff --git a/installers/local/carbon.cpp b/installers/local/carbon.cpp index 5549d9ce4391..6722c4a3c027 100644 --- a/installers/local/carbon.cpp +++ b/installers/local/carbon.cpp @@ -3,23 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "explorer/main.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -namespace fs = llvm::sys::fs; -namespace path = llvm::sys::path; - auto main(int argc, char** argv) -> int { - llvm::StringRef bin = path::filename(argv[0]); + llvm::StringRef bin = llvm::sys::path::filename(argv[0]); if (bin == "carbon-explorer") { static int static_for_main_addr; - std::string exe = fs::getMainExecutable( - argv[0], static_cast(&static_for_main_addr)); - llvm::StringRef install_path = path::parent_path(exe); - llvm::SmallString<256> prelude_file(install_path); - path::append(prelude_file, "data", "prelude.carbon"); - return Carbon::ExplorerMain(prelude_file, argc, argv); + return Carbon::ExplorerMain(argc, argv, + static_cast(&static_for_main_addr), + "data/prelude.carbon"); } else { fprintf(stderr, "Unrecognized Carbon binary requested: %s", argv[0]); return 1; diff --git a/toolchain/driver/BUILD b/toolchain/driver/BUILD index 1dbb648ee59f..11b951179c25 100644 --- a/toolchain/driver/BUILD +++ b/toolchain/driver/BUILD @@ -55,6 +55,7 @@ cc_binary( srcs = ["driver_main.cpp"], deps = [ ":driver", + "//common:bazel_working_dir", "@llvm-project//llvm:Support", ], ) diff --git a/toolchain/driver/driver_main.cpp b/toolchain/driver/driver_main.cpp index 5f6167cad0c5..7334d407ce1b 100644 --- a/toolchain/driver/driver_main.cpp +++ b/toolchain/driver/driver_main.cpp @@ -4,6 +4,7 @@ #include +#include "common/bazel_working_dir.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" @@ -14,15 +15,7 @@ auto main(int argc, char** argv) -> int { return EXIT_FAILURE; } - // Behave as if the working directory is where `bazel run` was invoked. - char* build_working_dir = getenv("BUILD_WORKING_DIRECTORY"); - if (build_working_dir != nullptr) { - if (std::error_code err = - llvm::sys::fs::set_current_path(build_working_dir)) { - llvm::errs() << "Failed to set working directory: " << err.message(); - return EXIT_FAILURE; - } - } + Carbon::SetWorkingDirForBazel(); llvm::SmallVector args(argv + 1, argv + argc); Carbon::Driver driver;