install_paths.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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 "common/error.h"
  7. #include "llvm/ADT/SmallString.h"
  8. #include "llvm/ADT/StringRef.h"
  9. #include "llvm/ADT/Twine.h"
  10. namespace Carbon {
  11. // Locates the toolchain installation and provides paths to various components.
  12. //
  13. // The Carbon toolchain expects to be installed into some install prefix. For
  14. // example, this is expected to be similar to the CMake install prefix:
  15. //
  16. // - `C:/Program Files/Carbon` or similar on Windows.
  17. // - `/usr` or `/usr/local` on Linux and most BSDs.
  18. // - `/opt/homebrew` or similar on macOS with Homebrew.
  19. // - `bazel-bin/some/bazel/target.runfiles/_main/toolchain/install/prefix_root`
  20. // for unit tests and just-built binaries during development.
  21. //
  22. // See https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
  23. // for more details. While we don't build the toolchain with CMake, we expect
  24. // our installation to behave in a similar and compatible way.
  25. //
  26. // There are multiple ways of locating an install's prefix:
  27. // - MakeExeRelative for command line tools in an install.
  28. // - MakeForBazelRunfiles for locating through Bazel's runfile tree.
  29. // - Make for an explicit path, for example in tests.
  30. //
  31. // When locating an install, we verify it by
  32. // looking for the `carbon_install.txt` marker file at a specific location
  33. // below. When errors occur, the install prefix is made empty, and error() can
  34. // be used for diagnostics; InstallPaths remains minimally functional.
  35. //
  36. // Within this prefix, we expect a hierarchy on Unix-y platforms:
  37. //
  38. // - `prefix_root/bin/carbon` - the main CLI driver
  39. // - `prefix_root/lib/carbon/carbon_install.txt` - a marker for the install
  40. // - `prefix_root/lib/carbon/...` - private data & binaries
  41. //
  42. // This is loosely based on the FHS (Filesystem Hierarchy Standard).
  43. //
  44. // An instance of this class provides methods that query for specific paths
  45. // within the install. Note that we want to abstract away any platform
  46. // differences in the installation layout, and so while there are some broad
  47. // paths available here, like the `prefix` method, those should primarily be
  48. // used for logging or debugging. When a specific part of the install is needed,
  49. // a dedicated accessor should be added that computes the path for that
  50. // component.
  51. //
  52. // Path accessor methods on the class return `llvm::StringRef` for any paths
  53. // that are stored in the class, and a `std::string` for any that are computed
  54. // on demand.
  55. //
  56. // TODO: Need to check the installation structure of LLVM on Windows and figure
  57. // out what Carbon's should be within a Windows prefix and how much of the
  58. // structure we can share with the Unix-y layout of the prefix.
  59. //
  60. // TODO: InstallPaths is typically called from places using a VFS (both tests
  61. // and the Driver), but does not use a VFS itself. It currently only supports
  62. // using the real filesystem, but should probably support a VFS.
  63. class InstallPaths {
  64. public:
  65. // Provide the current executable's path to detect the correct installation
  66. // prefix path. This assumes the toolchain to be in its installed layout.
  67. //
  68. // If detection fails, this reverts to using the current working directory as
  69. // the install prefix, and the error detected can be checked with `errors()`.
  70. static auto MakeExeRelative(llvm::StringRef exe_path) -> InstallPaths;
  71. // Provide the current executable's path, and use that to detect a Bazel or
  72. // Bazel-compatible runfiles install prefix path. This should only be used
  73. // where it is reasonable to rely on this rather than a fixed install location
  74. // such as for internal development purposes or other Bazel users of the
  75. // Carbon library.
  76. //
  77. // This method of construction also ensures the result is valid. If detection
  78. // fails for any reason, it will `CARBON_CHECK` fail with the error message.
  79. static auto MakeForBazelRunfiles(llvm::StringRef exe_path) -> InstallPaths;
  80. // Provide an explicit install paths prefix. This is useful for testing or for
  81. // using Carbon in an environment with an unusual path to the installed files.
  82. static auto Make(llvm::StringRef install_prefix) -> InstallPaths;
  83. // Returns the contents of the prelude manifest file. This is the list of
  84. // files that define the prelude, and will always be non-empty on success.
  85. auto ReadPreludeManifest() const -> ErrorOr<llvm::SmallVector<std::string>>;
  86. // Check for an error detecting the install paths correctly.
  87. //
  88. // A nullopt return means no errors encountered and the paths should work
  89. // correctly.
  90. //
  91. // A string return means there was an error, and details of the error are
  92. // in the `StringRef` for inclusion in any user report.
  93. [[nodiscard]] auto error() const -> std::optional<llvm::StringRef> {
  94. return error_;
  95. }
  96. // The computed installation prefix. This should correspond to the
  97. // `prefix_root` directory in Bazel's output, or to some prefix the toolchain
  98. // is installed into on a system such as `/usr/local` or `/home/$USER`.
  99. //
  100. // In the event of an error, this will be the empty string.
  101. auto prefix() const -> llvm::StringRef { return prefix_; }
  102. auto driver() const -> std::string;
  103. auto core_package() const -> std::string;
  104. auto llvm_install_bin() const -> std::string;
  105. private:
  106. InstallPaths() { SetError("No prefix provided!"); }
  107. explicit InstallPaths(llvm::StringRef prefix) : prefix_(prefix) {}
  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 the expected location,
  112. // and if not calls `SetError` with the relevant error message.
  113. auto CheckMarkerFile() -> void;
  114. llvm::SmallString<256> prefix_;
  115. std::optional<std::string> error_;
  116. };
  117. } // namespace Carbon
  118. #endif // CARBON_TOOLCHAIN_INSTALL_INSTALL_PATHS_H_