install_paths.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. #ifndef CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_H_
  5. #define CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_H_
  6. #include <filesystem>
  7. #include "common/error.h"
  8. #include "common/filesystem.h"
  9. #include "llvm/ADT/SmallString.h"
  10. #include "llvm/ADT/StringRef.h"
  11. #include "llvm/ADT/Twine.h"
  12. #include "toolchain/base/llvm_tools.h"
  13. namespace Carbon {
  14. // Locates the toolchain installation and provides paths to various components.
  15. //
  16. // The Carbon toolchain expects to be installed into a tree rooted at `root_`.
  17. // This root contains the marker file and the busy box binary.
  18. //
  19. // In a Unix-like filesystem environment, the root is typically located as
  20. // `<some prefix>/lib/carbon`, with symlinks in the other parts of the FHS-based
  21. // layout back to entries below this tree. However, this class and the toolchain
  22. // itself should only directly use things below the installation root to support
  23. // non-FHS usage.
  24. //
  25. // When locating an install, we verify it with `CheckMarkerFile`. When errors
  26. // occur, `SetError` makes `error()` available for diagnostics and clears the
  27. // install root, leaving things minimally functional but with the installation
  28. // root of the current working directory.
  29. //
  30. // The factory methods locate the install root based on their use-case:
  31. //
  32. // - `MakeExeRelative` for command line tools in an install.
  33. // - `MakeForBazelRunfiles` for locating through Bazel's runfile tree.
  34. // - `Make` for an explicit path, for example in tests.
  35. //
  36. // An instance of this class provides methods that query for specific paths
  37. // within the install. Note that we want to abstract away any platform
  38. // differences in the installation layout. When a specific part of the install
  39. // is needed, a dedicated accessor should be added that computes the path for
  40. // that component.
  41. //
  42. // TODO: Need to check the installation structure of LLVM on Windows and figure
  43. // out what Carbon's should be within a Windows prefix and how much of the
  44. // structure we can share with the Unix-y layout of the prefix.
  45. //
  46. // TODO: InstallPaths is typically called from places using a VFS (both tests
  47. // and the Driver), but does not use a VFS itself. It currently only supports
  48. // using the real filesystem, but should probably support a VFS.
  49. class InstallPaths {
  50. public:
  51. // Provide the current executable's path to detect the correct installation
  52. // root. This assumes the toolchain to be in its installed layout.
  53. static auto MakeExeRelative(llvm::StringRef exe_path) -> InstallPaths;
  54. // Provide the current executable's path, and use that to detect a Bazel or
  55. // Bazel-compatible runfiles install root. This should only be used where it
  56. // is reasonable to rely on this rather than a fixed install location such as
  57. // for internal development purposes or other Bazel users of the Carbon
  58. // library.
  59. //
  60. // This method of construction also ensures the result is valid. If detection
  61. // fails for any reason, it will `CARBON_CHECK` fail with the error message.
  62. static auto MakeForBazelRunfiles(llvm::StringRef exe_path) -> InstallPaths;
  63. // Provide an explicit install paths root. This is useful for testing or for
  64. // using Carbon in an environment with an unusual path to the installed files.
  65. static auto Make(llvm::StringRef install_root) -> InstallPaths;
  66. // Returns the contents of the prelude manifest file. This is the list of
  67. // files that define the prelude, and will always be non-empty on success.
  68. auto ReadPreludeManifest() const -> ErrorOr<llvm::SmallVector<std::string>>;
  69. // Returns the contents of the clang builtin headers manifest file. This is
  70. // the list of header files that are installed as part of the clang compiler,
  71. // and will always be non-empty on success.
  72. auto ReadClangHeadersManifest() const
  73. -> ErrorOr<llvm::SmallVector<std::string>>;
  74. // Check for an error detecting the install paths correctly.
  75. //
  76. // A nullopt return means no errors encountered and the paths should work
  77. // correctly.
  78. //
  79. // A string return means there was an error, and details of the error are
  80. // in the `StringRef` for inclusion in any user report.
  81. [[nodiscard]] auto error() const -> std::optional<llvm::StringRef> {
  82. return error_;
  83. }
  84. // The path to the root of this installation.
  85. auto root() const -> std::filesystem::path { return root_; }
  86. // The directory containing the `Core` package. Computed on demand.
  87. auto core_package() const -> std::filesystem::path;
  88. // The directory containing LLVM install binaries. Computed on demand.
  89. auto llvm_install_bin() const -> std::filesystem::path;
  90. // The path to `clang`.
  91. auto clang_path() const -> std::filesystem::path;
  92. // The path to `lld' and various aliases of `lld`.
  93. auto lld_path() const -> std::filesystem::path;
  94. auto ld_lld_path() const -> std::filesystem::path;
  95. auto ld64_lld_path() const -> std::filesystem::path;
  96. // The path to any of the LLVM tools.
  97. auto llvm_tool_path(LLVMTool tool) const -> std::filesystem::path;
  98. // The path to the Clang resources.
  99. auto clang_resource_path() const -> std::filesystem::path;
  100. // The path to the root of the runtimes.
  101. auto runtimes_root() const -> std::filesystem::path;
  102. // The path to `libunwind` runtime.
  103. auto libunwind_path() const -> std::filesystem::path;
  104. // The path to `libunwind` runtime.
  105. auto libcxx_path() const -> std::filesystem::path;
  106. // The path to `libunwind` runtime.
  107. auto libcxxabi_path() const -> std::filesystem::path;
  108. // The path to the LLVM `libc` runtime.
  109. auto libc_path() const -> std::filesystem::path;
  110. // The installation digest path.
  111. //
  112. // This file contains a digest of the installation.
  113. auto digest_path() const -> std::filesystem::path;
  114. private:
  115. friend class InstallPathsTestPeer;
  116. InstallPaths() { SetError("No root provided!"); }
  117. explicit InstallPaths(std::filesystem::path root) : root_(std::move(root)) {}
  118. static auto MakeFromFile(std::filesystem::path file) -> InstallPaths;
  119. // Set an error message on the install paths and reset the `root_` to empty,
  120. // which should use the current working directory.
  121. auto SetError(llvm::Twine message) -> void;
  122. // Check that the install paths have a marker file at
  123. // `root()/carbon_install.txt". If not, calls `SetError` with the
  124. // relevant error message.
  125. auto CheckMarkerFile() -> void;
  126. // Read a manifest file.
  127. auto ReadManifest(std::filesystem::path manifest_path,
  128. std::filesystem::path manifest_file) const
  129. -> ErrorOr<llvm::SmallVector<std::string>>;
  130. // The computed installation root. In the event of an error, this will be the
  131. // empty string.
  132. //
  133. // When run from Bazel (for example, in unit tests or development binaries)
  134. // this will look like:
  135. // `bazel-bin/some/bazel/target.runfiles/_main/toolchain/install`
  136. //
  137. // When installed, it's expected to be similar to the CMake install prefix,
  138. // followed by `lib/carbon`:
  139. //
  140. // - `/usr/lib/carbon` or `/usr/local/lib/carbon` on Linux and most BSDs.
  141. // - `/opt/homebrew/lib/carbon` or similar on macOS with Homebrew.
  142. // - TODO: Figure out if this is `C:/Program Files/Carbon` or something else
  143. // on Windows.
  144. //
  145. // See https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
  146. // for more details. While we don't build the toolchain with CMake, we expect
  147. // our installation to behave in a similar and compatible way.
  148. //
  149. // The hierarchy of files beneath the install root can be found in the
  150. // BUILD rules in `//toolchain/install`.
  151. std::filesystem::path root_;
  152. // The opened root directory.
  153. Filesystem::Dir root_dir_;
  154. std::optional<std::string> error_;
  155. };
  156. } // namespace Carbon
  157. #endif // CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_H_