tool_runner_base.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/driver/tool_runner_base.h"
  5. #include <array>
  6. #include <memory>
  7. #include <optional>
  8. #include "common/vlog.h"
  9. #include "llvm/ADT/ArrayRef.h"
  10. #include "llvm/ADT/StringRef.h"
  11. namespace Carbon {
  12. ToolRunnerBase::ToolRunnerBase(const InstallPaths* install_paths,
  13. llvm::raw_ostream* vlog_stream)
  14. : installation_(install_paths), vlog_stream_(vlog_stream) {}
  15. auto ToolRunnerBase::BuildCStrArgs(llvm::StringRef tool_name,
  16. llvm::StringRef tool_path,
  17. std::optional<llvm::StringRef> verbose_flag,
  18. llvm::ArrayRef<llvm::StringRef> args,
  19. llvm::OwningArrayRef<char>& cstr_arg_storage)
  20. -> llvm::SmallVector<const char*, 64> {
  21. // TODO: Maybe handle response file expansion similar to the Clang CLI?
  22. // If we have a verbose logging stream, and that stream is the same as
  23. // `llvm::errs`, then add the `-v` flag so that the driver also prints verbose
  24. // information.
  25. bool inject_v_arg = verbose_flag.has_value() && vlog_stream_ == &llvm::errs();
  26. std::array<llvm::StringRef, 1> v_arg_storage;
  27. llvm::ArrayRef<llvm::StringRef> maybe_v_arg;
  28. if (inject_v_arg) {
  29. v_arg_storage[0] = *verbose_flag;
  30. maybe_v_arg = v_arg_storage;
  31. }
  32. CARBON_VLOG("Running {} driver with arguments:\n", tool_name);
  33. // Render the arguments into null-terminated C-strings. Command lines can get
  34. // quite long in build systems so this tries to minimize the memory allocation
  35. // overhead.
  36. // Provide the wrapped tool path as the synthetic `argv[0]`.
  37. std::array<llvm::StringRef, 1> exe_arg = {tool_path};
  38. auto args_range =
  39. llvm::concat<const llvm::StringRef>(exe_arg, maybe_v_arg, args);
  40. int total_size = 0;
  41. for (llvm::StringRef arg : args_range) {
  42. // Accumulate both the string size and a null terminator byte.
  43. total_size += arg.size() + 1;
  44. }
  45. // Allocate one chunk of storage for the actual C-strings and a vector of
  46. // pointers into the storage.
  47. cstr_arg_storage = llvm::OwningArrayRef<char>(total_size);
  48. llvm::SmallVector<const char*, 64> cstr_args;
  49. cstr_args.reserve(args.size() + inject_v_arg + 1);
  50. for (ssize_t i = 0; llvm::StringRef arg : args_range) {
  51. cstr_args.push_back(&cstr_arg_storage[i]);
  52. memcpy(&cstr_arg_storage[i], arg.data(), arg.size());
  53. i += arg.size();
  54. cstr_arg_storage[i] = '\0';
  55. ++i;
  56. }
  57. for (const char* cstr_arg : llvm::ArrayRef(cstr_args)) {
  58. CARBON_VLOG(" '{0}'\n", cstr_arg);
  59. }
  60. return cstr_args;
  61. }
  62. } // namespace Carbon