install_paths.h 7.3 KB

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