diff --git a/toolchain/install/BUILD b/toolchain/install/BUILD index 9b8054279507..ceeb1f4aae08 100644 --- a/toolchain/install/BUILD +++ b/toolchain/install/BUILD @@ -64,6 +64,7 @@ cc_binary( "//toolchain/base:install_paths", "//toolchain/base:llvm_tools_def", "//toolchain/driver", + "@llvm-project//clang:driver", "@llvm-project//llvm:Support", ], ) diff --git a/toolchain/install/busybox_main.cpp b/toolchain/install/busybox_main.cpp index 2812e3907f95..4a3ab42b3bd5 100644 --- a/toolchain/install/busybox_main.cpp +++ b/toolchain/install/busybox_main.cpp @@ -7,12 +7,15 @@ #include #include +#include "clang/Driver/Driver.h" #include "common/bazel_working_dir.h" #include "common/error.h" #include "common/init_llvm.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" #include "llvm/Support/LLVMDriver.h" #include "toolchain/base/install_paths.h" #include "toolchain/driver/driver.h" @@ -46,9 +49,17 @@ static auto Main(int argc, char** argv) -> ErrorOr { auto fs = llvm::vfs::getRealFileSystem(); - llvm::SmallVector raw_args; + llvm::SmallVector raw_args; raw_args.append(argv + 1, argv + argc); + // Expand any response files in the arguments. + llvm::BumpPtrAllocator alloc; + if (llvm::Error error = clang::driver::expandResponseFiles( + raw_args, busybox_info.mode && *busybox_info.mode == "clang-cl", + alloc, fs.get())) { + return Error(llvm::toString(std::move(error))); + } + llvm::SmallVector args; args.reserve(argc + 1); if (busybox_info.mode) { @@ -85,23 +96,36 @@ static auto Main(int argc, char** argv) -> ErrorOr { .Default({*busybox_info.mode, "--"}); - // When we're operating as a busybox, we also support a special command line - // syntax for passing flags to the base Carbon driver as - // `-Xcarbon=--some-carbon-flag=some-value`. Extract any arguments of that - // form, remove the prefix, and prepend them to the arg list prior to the - // busybox subcommand arguments. - llvm::erase_if(raw_args, [&args](llvm::StringRef raw_arg) { - if (raw_arg.consume_front("-Xcarbon=")) { - args.push_back(raw_arg); - return true; - } - return false; - }); - // And now append the subcommand args. args.append(subcommand_args); } - args.append(raw_args); + llvm::append_range(args, raw_args); + + // We also support a special command line syntax for passing flags to the base + // Carbon driver as `-Xcarbon=--some-carbon-flag=some-value`. This is + // important when build systems only allow appending custom user flags to + // allow them to be used for driver. + // + // Extract any arguments of that form, remove the prefix, and insert them to + // the argument list just before the first positional parameter or subcommand. + // This let's them come after any other flags to the base driver and override + // them if needed. + llvm::SmallVector extra_driver_args; + llvm::erase_if(args, [&extra_driver_args](llvm::StringRef arg) { + if (arg.consume_front("-Xcarbon=")) { + extra_driver_args.push_back(arg); + return true; + } + return false; + }); + if (!extra_driver_args.empty()) { + auto* subcommand_it = llvm::find_if(args, [](llvm::StringRef arg) { + // Flags start with `-`, unless it is the string `-` or `--`. + return !arg.starts_with("-") || arg == "-" || arg == "--"; + }); + args.insert(subcommand_it, extra_driver_args.begin(), + extra_driver_args.end()); + } Driver driver(fs, &install_paths, stdin, &llvm::outs(), &llvm::errs(), /*fuzzing=*/false, /*enable_leaking=*/true);