tool_runner_base.cpp 2.7 KB

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