Skip to content

Conversation

@cachemeifyoucan
Copy link
Collaborator

@cachemeifyoucan cachemeifyoucan commented Oct 22, 2024

Add OutputBackend and OutputFile to the llvm::vfs namespace for
virtualizing compiler outputs. This is intended for use in Clang,

The headers are:

  • llvm/Support/VirtualOutputConfig.h
  • llvm/Support/VirtualOutputError.h
  • llvm/Support/VirtualOutputFile.h
  • llvm/Support/VirtualOutputBackend.h

OutputFile is moveable and owns an OutputFileImpl, which is provided by
the derived OutputBackend.

  • OutputFileImpl::keep() and OutputFileImpl::discard() should keep or
    discard the output. OutputFile guarantees that exactly one of these
    will be called before destruction.
  • OutputFile::keep() and OutputFile::discard() wrap OutputFileImpl
    and catch usage errors such as double-close.
  • OutputFile::discardOnDestroy() installs an error handler for the
    destructor to use if the file is still open. The handler will be
    called if discard() fails.
  • OutputFile::~OutputFile() calls report_fatal_error() if none of
    keep(), discard(), or discardOnDestroy() has been called. It still
    calls OutputFileImpl::discard().
  • getOS() returns the wrapped raw_pwrite_stream. For convenience,
    OutputFile has an implicit conversion to raw_ostream and
    raw_ostream &operator<<(OutputFile&, T&&).

OutputBackend can be stored in IntrusiveRefCntPtr.

  • Most operations are thread-safe.
  • clone() returns a backend that targets the same destination.
    All operations are thread-safe when done on different clones.
  • createFile() takes a path and an OutputConfig (see below) and returns
    an OutputFile. Backends implement createFileImpl().

OutputConfig has flags to configure the output. Backends may ignore or
override flags that aren't relevant or implementable.

  • The initial flags are:
    • AtomicWrite: whether the output should appear atomically (e.g., by
      using a temporary file and renaming it).
    • CrashCleanup: whether the output should be cleaned up if there's a
      crash (e.g., with RemoveFileOnSignal).
    • ImplyCreateDirectories: whether to implicitly create missing
      directories in the path to the file.
    • Text: matches sys::fs::OF_Text.
    • CRLF: matches sys::fs::OF_CRLF.
    • Append: matches sys::fs::OF_Append and can use with AtomicWrite
      for atomic append.
    • OnlyIfDifferent: skip writting the output file if the existing file
      at the output path is identical to the content to be written.
  • Each "Flag" has setFlag(bool) and bool getFlag() and shortcuts
    setFlag() and setNoFlag(). The setters are constexpr and return
    OutputConfig& to make it easy to declare a default value for a filed
    in a class or struct.
  • Setters and getters for Binary and TextWithCRLF are derived from Text
    and CRLF. For convenience, sys::fs::OpenFlags can be passed
    directly to setOpenFlags().

This patch intentionally lacks a number of important features that have
been left for follow-ups:

  • Set a (virtual) current working directory.
  • Create a directory.
  • Create a file or directory with a unique name (avoiding collisions
    with existing filenames).

Patch originally by dexonsmith

@llvmbot
Copy link
Member

llvmbot commented Oct 22, 2024

@llvm/pr-subscribers-llvm-support

Author: Steven Wu (cachemeifyoucan)

Changes

Add OutputBackend and OutputFile to the llvm::vfs namespace for
virtualizing compiler outputs. This is intended for use in Clang,

The headers are:

  • llvm/Support/VirtualOutputConfig.h
  • llvm/Support/VirtualOutputError.h
  • llvm/Support/VirtualOutputFile.h
  • llvm/Support/VirtualOutputBackend.h

OutputFile is moveable and owns an OutputFileImpl, which is provided by
the derived OutputBackend.

  • OutputFileImpl::keep() and OutputFileImpl::discard() should keep or
    discard the output. OutputFile guarantees that exactly one of these
    will be called before destruction.
  • OutputFile::keep() and OutputFile::discard() wrap OutputFileImpl
    and catch usage errors such as double-close.
  • OutputFile::discardOnDestroy() installs an error handler for the
    destructor to use if the file is still open. The handler will be
    called if discard() fails.
  • OutputFile::~OutputFile() calls report_fatal_error() if none of
    keep(), discard(), or discardOnDestroy() has been called. It still
    calls OutputFileImpl::discard().
  • getOS() returns the wrapped raw_pwrite_stream. For convenience,
    OutputFile has an implicit conversion to raw_ostream and
    raw_ostream &amp;operator&lt;&lt;(OutputFile&amp;, T&amp;&amp;).

OutputBackend can be stored in IntrusiveRefCntPtr.

  • Most operations are thread-safe.
  • clone() returns a backend that targets the same destination.
    All operations are thread-safe when done on different clones.
  • createFile() takes a path and an OutputConfig (see below) and returns
    an OutputFile. Backends implement createFileImpl().

OutputConfig has flags to configure the output. Backends may ignore or
override flags that aren't relevant or implementable.

  • The initial flags are:
    • AtomicWrite: whether the output should appear atomically (e.g., by
      using a temporary file and renaming it).
    • CrashCleanup: whether the output should be cleaned up if there's a
      crash (e.g., with RemoveFileOnSignal).
    • ImplyCreateDirectories: whether to implicitly create missing
      directories in the path to the file.
    • Text: matches sys::fs::OF_Text.
    • CRLF: matches sys::fs::OF_CRLF.
    • Append: matches sys::fs::OF_Append and can use with AtomicWrite
      for atomic append.
  • Each "Flag" has setFlag(bool) and bool getFlag() and shortcuts
    setFlag() and setNoFlag(). The setters are constexpr and return
    OutputConfig&amp; to make it easy to declare a default value for a filed
    in a class or struct.
  • Setters and getters for Binary and TextWithCRLF are derived from Text
    and CRLF. For convenience, sys::fs::OpenFlags can be passed
    directly to setOpenFlags().

This patch intentionally lacks a number of important features that have
been left for follow-ups:

  • Set a (virtual) current working directory.
  • Create a directory.
  • Create a file or directory with a unique name (avoiding collisions
    with existing filenames).

Patch originally by dexonsmith


Patch is 108.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113363.diff

18 Files Affected:

  • (added) llvm/include/llvm/Support/HashingOutputBackend.h (+112)
  • (added) llvm/include/llvm/Support/VirtualOutputBackend.h (+62)
  • (added) llvm/include/llvm/Support/VirtualOutputBackends.h (+110)
  • (added) llvm/include/llvm/Support/VirtualOutputConfig.def (+26)
  • (added) llvm/include/llvm/Support/VirtualOutputConfig.h (+91)
  • (added) llvm/include/llvm/Support/VirtualOutputError.h (+134)
  • (added) llvm/include/llvm/Support/VirtualOutputFile.h (+162)
  • (modified) llvm/lib/Support/CMakeLists.txt (+5)
  • (added) llvm/lib/Support/VirtualOutputBackend.cpp (+38)
  • (added) llvm/lib/Support/VirtualOutputBackends.cpp (+594)
  • (added) llvm/lib/Support/VirtualOutputConfig.cpp (+50)
  • (added) llvm/lib/Support/VirtualOutputError.cpp (+53)
  • (added) llvm/lib/Support/VirtualOutputFile.cpp (+106)
  • (modified) llvm/unittests/Support/CMakeLists.txt (+4)
  • (added) llvm/unittests/Support/VirtualOutputBackendTest.cpp (+147)
  • (added) llvm/unittests/Support/VirtualOutputBackendsTest.cpp (+886)
  • (added) llvm/unittests/Support/VirtualOutputConfigTest.cpp (+152)
  • (added) llvm/unittests/Support/VirtualOutputFileTest.cpp (+342)
diff --git a/llvm/include/llvm/Support/HashingOutputBackend.h b/llvm/include/llvm/Support/HashingOutputBackend.h
new file mode 100644
index 00000000000000..d2e79663f55266
--- /dev/null
+++ b/llvm/include/llvm/Support/HashingOutputBackend.h
@@ -0,0 +1,112 @@
+//===- HashingOutputBackends.h - Hashing output backends --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H
+#define LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/HashBuilder.h"
+#include "llvm/Support/VirtualOutputBackend.h"
+#include "llvm/Support/VirtualOutputConfig.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm::vfs {
+
+/// raw_pwrite_stream that writes to a hasher.
+template <typename HasherT>
+class HashingStream : public llvm::raw_pwrite_stream {
+private:
+  SmallVector<char> Buffer;
+  raw_svector_ostream OS;
+
+  using HashBuilderT = HashBuilder<HasherT, support::endianness::native>;
+  HashBuilderT Builder;
+
+  void write_impl(const char *Ptr, size_t Size) override {
+    OS.write(Ptr, Size);
+  }
+
+  void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override {
+    OS.pwrite(Ptr, Size, Offset);
+  }
+
+  uint64_t current_pos() const override { return OS.str().size(); }
+
+public:
+  HashingStream() : OS(Buffer) { SetUnbuffered(); }
+
+  auto final() {
+    Builder.update(OS.str());
+    return Builder.final();
+  }
+};
+
+template <typename HasherT> class HashingOutputFile;
+
+/// An output backend that only generates the hash for outputs.
+template <typename HasherT> class HashingOutputBackend : public OutputBackend {
+private:
+  friend class HashingOutputFile<HasherT>;
+  void addOutputFile(StringRef Path, StringRef Hash) {
+    OutputHashes[Path] = std::string(Hash);
+  }
+
+protected:
+  IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
+    return const_cast<HashingOutputBackend<HasherT> *>(this);
+  }
+
+  Expected<std::unique_ptr<OutputFileImpl>>
+  createFileImpl(StringRef Path, std::optional<OutputConfig> Config) override {
+    return std::make_unique<HashingOutputFile<HasherT>>(Path, *this);
+  }
+
+public:
+  /// Iterator for all the output file names.
+  auto outputFiles() const { return OutputHashes.keys(); }
+
+  /// Get hash value for the output files in hex representation.
+  /// Return None if the requested path is not generated.
+  std::optional<std::string> getHashValueForFile(StringRef Path) {
+    auto F = OutputHashes.find(Path);
+    if (F == OutputHashes.end())
+      return std::nullopt;
+    return toHex(F->second);
+  }
+
+private:
+  StringMap<std::string> OutputHashes;
+};
+
+/// HashingOutputFile.
+template <typename HasherT>
+class HashingOutputFile final : public OutputFileImpl {
+public:
+  Error keep() override {
+    auto Result = OS.final();
+    Backend.addOutputFile(OutputPath, toStringRef(Result));
+    return Error::success();
+  }
+  Error discard() override { return Error::success(); }
+  raw_pwrite_stream &getOS() override { return OS; }
+
+  HashingOutputFile(StringRef OutputPath,
+                    HashingOutputBackend<HasherT> &Backend)
+      : OutputPath(OutputPath.str()), Backend(Backend) {}
+
+private:
+  const std::string OutputPath;
+  HashingStream<HasherT> OS;
+  HashingOutputBackend<HasherT> &Backend;
+};
+
+} // namespace llvm::vfs
+
+#endif // LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H
diff --git a/llvm/include/llvm/Support/VirtualOutputBackend.h b/llvm/include/llvm/Support/VirtualOutputBackend.h
new file mode 100644
index 00000000000000..2328252c7054fc
--- /dev/null
+++ b/llvm/include/llvm/Support/VirtualOutputBackend.h
@@ -0,0 +1,62 @@
+//===- VirtualOutputBackend.h - Output virtualization -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_VIRTUALOUTPUTBACKEND_H
+#define LLVM_SUPPORT_VIRTUALOUTPUTBACKEND_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/VirtualOutputConfig.h"
+#include "llvm/Support/VirtualOutputFile.h"
+
+namespace llvm::vfs {
+
+/// Interface for virtualized outputs.
+///
+/// If virtual functions are added here, also add them to \a
+/// ProxyOutputBackend.
+class OutputBackend : public RefCountedBase<OutputBackend> {
+  virtual void anchor();
+
+public:
+  /// Get a backend that points to the same destination as this one but that
+  /// has independent settings.
+  ///
+  /// Not thread-safe, but all operations are thread-safe when performed on
+  /// separate clones of the same backend.
+  IntrusiveRefCntPtr<OutputBackend> clone() const { return cloneImpl(); }
+
+  /// Create a file. If \p Config is \c std::nullopt, uses the backend's default
+  /// OutputConfig (may match \a OutputConfig::OutputConfig(), or may
+  /// have been customized).
+  ///
+  /// Thread-safe.
+  Expected<OutputFile>
+  createFile(const Twine &Path,
+             std::optional<OutputConfig> Config = std::nullopt);
+
+protected:
+  /// Must be thread-safe. Virtual function has a different name than \a
+  /// clone() so that implementations can override the return value.
+  virtual IntrusiveRefCntPtr<OutputBackend> cloneImpl() const = 0;
+
+  /// Create a file for \p Path. Must be thread-safe.
+  ///
+  /// \pre \p Config is valid or std::nullopt.
+  virtual Expected<std::unique_ptr<OutputFileImpl>>
+  createFileImpl(StringRef Path, std::optional<OutputConfig> Config) = 0;
+
+  OutputBackend() = default;
+
+public:
+  virtual ~OutputBackend() = default;
+};
+
+} // namespace llvm::vfs
+
+#endif // LLVM_SUPPORT_VIRTUALOUTPUTBACKEND_H
diff --git a/llvm/include/llvm/Support/VirtualOutputBackends.h b/llvm/include/llvm/Support/VirtualOutputBackends.h
new file mode 100644
index 00000000000000..6f702000d77b3e
--- /dev/null
+++ b/llvm/include/llvm/Support/VirtualOutputBackends.h
@@ -0,0 +1,110 @@
+//===- VirtualOutputBackends.h - Virtual output backends --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_VIRTUALOUTPUTBACKENDS_H
+#define LLVM_SUPPORT_VIRTUALOUTPUTBACKENDS_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/VirtualOutputBackend.h"
+#include "llvm/Support/VirtualOutputConfig.h"
+
+namespace llvm::vfs {
+
+/// Create a backend that ignores all output.
+IntrusiveRefCntPtr<OutputBackend> makeNullOutputBackend();
+
+/// Make a backend where \a OutputBackend::createFile() forwards to
+/// \p UnderlyingBackend when \p Filter is true, and otherwise returns a
+/// \a NullOutput.
+IntrusiveRefCntPtr<OutputBackend> makeFilteringOutputBackend(
+    IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend,
+    std::function<bool(StringRef, std::optional<OutputConfig>)> Filter);
+
+/// Create a backend that forwards \a OutputBackend::createFile() to both \p
+/// Backend1 and \p Backend2 and sends content to both places.
+IntrusiveRefCntPtr<OutputBackend>
+makeMirroringOutputBackend(IntrusiveRefCntPtr<OutputBackend> Backend1,
+                           IntrusiveRefCntPtr<OutputBackend> Backend2);
+
+/// A helper class for proxying another backend, with the default
+/// implementation to forward to the underlying backend.
+class ProxyOutputBackend : public OutputBackend {
+  void anchor() override;
+
+protected:
+  // Require subclass to implement cloneImpl().
+  //
+  // IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override;
+
+  Expected<std::unique_ptr<OutputFileImpl>>
+  createFileImpl(StringRef Path, std::optional<OutputConfig> Config) override {
+    OutputFile File;
+    if (Error E = UnderlyingBackend->createFile(Path, Config).moveInto(File))
+      return std::move(E);
+    return File.takeImpl();
+  }
+
+  OutputBackend &getUnderlyingBackend() const { return *UnderlyingBackend; }
+
+public:
+  ProxyOutputBackend(IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend)
+      : UnderlyingBackend(std::move(UnderlyingBackend)) {
+    assert(this->UnderlyingBackend && "Expected non-null backend");
+  }
+
+private:
+  IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend;
+};
+
+/// An output backend that creates files on disk, wrapping APIs in sys::fs.
+class OnDiskOutputBackend : public OutputBackend {
+  void anchor() override;
+
+protected:
+  IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
+    return clone();
+  }
+
+  Expected<std::unique_ptr<OutputFileImpl>>
+  createFileImpl(StringRef Path, std::optional<OutputConfig> Config) override;
+
+public:
+  /// Resolve an absolute path.
+  Error makeAbsolute(SmallVectorImpl<char> &Path) const;
+
+  /// On disk output settings.
+  struct OutputSettings {
+    /// Register output files to be deleted if a signal is received. Also
+    /// disabled for outputs with \a OutputConfig::getNoDiscardOnSignal().
+    bool DisableRemoveOnSignal = false;
+
+    /// Disable temporary files. Also disabled for outputs with \a
+    /// OutputConfig::getNoAtomicWrite().
+    bool DisableTemporaries = false;
+
+    // Default configuration for this backend.
+    OutputConfig DefaultConfig;
+  };
+
+  IntrusiveRefCntPtr<OnDiskOutputBackend> clone() const {
+    auto Clone = makeIntrusiveRefCnt<OnDiskOutputBackend>();
+    Clone->Settings = Settings;
+    return Clone;
+  }
+
+  OnDiskOutputBackend() = default;
+
+  /// Settings for this backend.
+  ///
+  /// Access is not thread-safe.
+  OutputSettings Settings;
+};
+
+} // namespace llvm::vfs
+
+#endif // LLVM_SUPPORT_VIRTUALOUTPUTBACKENDS_H
diff --git a/llvm/include/llvm/Support/VirtualOutputConfig.def b/llvm/include/llvm/Support/VirtualOutputConfig.def
new file mode 100644
index 00000000000000..0b6a765cbd4c00
--- /dev/null
+++ b/llvm/include/llvm/Support/VirtualOutputConfig.def
@@ -0,0 +1,26 @@
+//===- VirtualOutputConfig.def - Virtual output config defs -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HANDLE_OUTPUT_CONFIG_FLAG
+#error "Missing macro definition of HANDLE_OUTPUT_CONFIG_FLAG"
+#endif
+
+// Define HANDLE_OUTPUT_CONFIG_FLAG before including.
+//
+// #define HANDLE_OUTPUT_CONFIG_FLAG(NAME, DEFAULT)
+
+HANDLE_OUTPUT_CONFIG_FLAG(Text, false) // OF_Text.
+HANDLE_OUTPUT_CONFIG_FLAG(CRLF, false) // OF_CRLF.
+HANDLE_OUTPUT_CONFIG_FLAG(Append, false) // OF_Append.
+HANDLE_OUTPUT_CONFIG_FLAG(DiscardOnSignal, true) // E.g., RemoveFileOnSignal.
+HANDLE_OUTPUT_CONFIG_FLAG(AtomicWrite, true) // E.g., use temporaries.
+HANDLE_OUTPUT_CONFIG_FLAG(ImplyCreateDirectories, true)
+// Skip atomic write if existing file content is the same
+HANDLE_OUTPUT_CONFIG_FLAG(OnlyIfDifferent, false)
+
+#undef HANDLE_OUTPUT_CONFIG_FLAG
diff --git a/llvm/include/llvm/Support/VirtualOutputConfig.h b/llvm/include/llvm/Support/VirtualOutputConfig.h
new file mode 100644
index 00000000000000..d93bbf5ca63a03
--- /dev/null
+++ b/llvm/include/llvm/Support/VirtualOutputConfig.h
@@ -0,0 +1,91 @@
+//===- VirtualOutputConfig.h - Virtual output configuration -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_VIRTUALOUTPUTCONFIG_H
+#define LLVM_SUPPORT_VIRTUALOUTPUTCONFIG_H
+
+#include "llvm/Support/Compiler.h"
+#include <initializer_list>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace sys {
+namespace fs {
+enum OpenFlags : unsigned;
+} // end namespace fs
+} // end namespace sys
+
+namespace vfs {
+
+namespace detail {
+/// Unused and empty base class to allow OutputConfig constructor to be
+/// constexpr, with commas before every field's initializer.
+struct EmptyBaseClass {};
+} // namespace detail
+
+/// Full configuration for an output for use by the \a OutputBackend. Each
+/// configuration flag is either \c true or \c false.
+struct OutputConfig : detail::EmptyBaseClass {
+public:
+  void print(raw_ostream &OS) const;
+  void dump() const;
+
+#define HANDLE_OUTPUT_CONFIG_FLAG(NAME, DEFAULT)                               \
+  constexpr bool get##NAME() const { return NAME; }                            \
+  constexpr bool getNo##NAME() const { return !NAME; }                         \
+  constexpr OutputConfig &set##NAME(bool Value) {                              \
+    NAME = Value;                                                              \
+    return *this;                                                              \
+  }                                                                            \
+  constexpr OutputConfig &set##NAME() { return set##NAME(true); }              \
+  constexpr OutputConfig &setNo##NAME() { return set##NAME(false); }
+#include "llvm/Support/VirtualOutputConfig.def"
+
+  constexpr OutputConfig &setBinary() { return setNoText().setNoCRLF(); }
+  constexpr OutputConfig &setTextWithCRLF() { return setText().setCRLF(); }
+  constexpr OutputConfig &setTextWithCRLF(bool Value) {
+    return Value ? setText().setCRLF() : setBinary();
+  }
+  constexpr bool getTextWithCRLF() const { return getText() && getCRLF(); }
+  constexpr bool getBinary() const { return !getText(); }
+
+  /// Updates Text and CRLF flags based on \a sys::fs::OF_Text and \a
+  /// sys::fs::OF_CRLF in \p Flags. Rejects CRLF without Text (calling
+  /// \a setBinary()).
+  OutputConfig &setOpenFlags(const sys::fs::OpenFlags &Flags);
+
+  constexpr OutputConfig()
+      : EmptyBaseClass()
+#define HANDLE_OUTPUT_CONFIG_FLAG(NAME, DEFAULT) , NAME(DEFAULT)
+#include "llvm/Support/VirtualOutputConfig.def"
+  {
+  }
+
+  constexpr bool operator==(OutputConfig RHS) const {
+#define HANDLE_OUTPUT_CONFIG_FLAG(NAME, DEFAULT)                               \
+  if (NAME != RHS.NAME)                                                        \
+    return false;
+#include "llvm/Support/VirtualOutputConfig.def"
+    return true;
+  }
+  constexpr bool operator!=(OutputConfig RHS) const { return !operator==(RHS); }
+
+private:
+#define HANDLE_OUTPUT_CONFIG_FLAG(NAME, DEFAULT) bool NAME : 1;
+#include "llvm/Support/VirtualOutputConfig.def"
+};
+
+} // namespace vfs
+
+raw_ostream &operator<<(raw_ostream &OS, vfs::OutputConfig Config);
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_VIRTUALOUTPUTCONFIG_H
diff --git a/llvm/include/llvm/Support/VirtualOutputError.h b/llvm/include/llvm/Support/VirtualOutputError.h
new file mode 100644
index 00000000000000..5459fae4552d51
--- /dev/null
+++ b/llvm/include/llvm/Support/VirtualOutputError.h
@@ -0,0 +1,134 @@
+//===- VirtualOutputError.h - Errors for output virtualization --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_VIRTUALOUTPUTERROR_H
+#define LLVM_SUPPORT_VIRTUALOUTPUTERROR_H
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/VirtualOutputConfig.h"
+
+namespace llvm::vfs {
+
+const std::error_category &output_category();
+
+enum class OutputErrorCode {
+  // Error code 0 is absent. Use std::error_code() instead.
+  not_closed = 1,
+  invalid_config,
+  already_closed,
+  has_open_proxy,
+};
+
+inline std::error_code make_error_code(OutputErrorCode EV) {
+  return std::error_code(static_cast<int>(EV), output_category());
+}
+
+/// Error related to an \a OutputFile. Derives from \a ECError and adds \a
+/// getOutputPath().
+class OutputError : public ErrorInfo<OutputError, ECError> {
+  void anchor() override;
+
+public:
+  StringRef getOutputPath() const { return OutputPath; }
+  void log(raw_ostream &OS) const override {
+    OS << getOutputPath() << ": ";
+    ECError::log(OS);
+  }
+
+  // Used by ErrorInfo::classID.
+  static char ID;
+
+  OutputError(const Twine &OutputPath, std::error_code EC)
+      : ErrorInfo<OutputError, ECError>(EC), OutputPath(OutputPath.str()) {
+    assert(EC && "Cannot create OutputError from success EC");
+  }
+
+  OutputError(const Twine &OutputPath, OutputErrorCode EV)
+      : ErrorInfo<OutputError, ECError>(make_error_code(EV)),
+        OutputPath(OutputPath.str()) {
+    assert(EC && "Cannot create OutputError from success EC");
+  }
+
+private:
+  std::string OutputPath;
+};
+
+/// Return \a Error::success() or use \p OutputPath to create an \a
+/// OutputError, depending on \p EC.
+inline Error convertToOutputError(const Twine &OutputPath, std::error_code EC) {
+  if (EC)
+    return make_error<OutputError>(OutputPath, EC);
+  return Error::success();
+}
+
+/// Error related to an OutputConfig for an \a OutputFile. Derives from \a
+/// OutputError and adds \a getConfig().
+class OutputConfigError : public ErrorInfo<OutputConfigError, OutputError> {
+  void anchor() override;
+
+public:
+  OutputConfig getConfig() const { return Config; }
+  void log(raw_ostream &OS) const override {
+    OutputError::log(OS);
+    OS << ": " << Config;
+  }
+
+  // Used by ErrorInfo::classID.
+  static char ID;
+
+  OutputConfigError(OutputConfig Config, const Twine &OutputPath)
+      : ErrorInfo<OutputConfigError, OutputError>(
+            OutputPath, OutputErrorCode::invalid_config),
+        Config(Config) {}
+
+private:
+  OutputConfig Config;
+};
+
+/// Error related to a temporary file for an \a OutputFile. Derives from \a
+/// OutputError and adds \a getTempPath().
+class TempFileOutputError : public ErrorInfo<TempFileOutputError, OutputError> {
+  void anchor() override;
+
+public:
+  StringRef getTempPath() const { return TempPath; }
+  void log(raw_ostream &OS) const override {
+    OS << getTempPath() << " => ";
+    OutputError::log(OS);
+  }
+
+  // Used by ErrorInfo::classID.
+  static char ID;
+
+  TempFileOutputError(const Twine &TempPath, const Twine &OutputPath,
+                      std::error_code EC)
+      : ErrorInfo<TempFileOutputError, OutputError>(OutputPath, EC),
+        TempPath(TempPath.str()) {}
+
+  TempFileOutputError(const Twine &TempPath, const Twine &OutputPath,
+                      OutputErrorCode EV)
+      : ErrorInfo<TempFileOutputError, OutputError>(OutputPath, EV),
+        TempPath(TempPath.str()) {}
+
+private:
+  std::string TempPath;
+};
+
+/// Return \a Error::success() or use \p TempPath and \p OutputPath to create a
+/// \a TempFileOutputError, depending on \p EC.
+inline Error convertToTempFileOutputError(const Twine &TempPath,
+                                          const Twine &OutputPath,
+                                          std::error_code EC) {
+  if (EC)
+    return make_error<TempFileOutputError>(TempPath, OutputPath, EC);
+  return Error::success();
+}
+
+} // namespace llvm::vfs
+
+#endif // LLVM_SUPPORT_VIRTUALOUTPUTERROR_H
diff --git a/llvm/include/llvm/Support/VirtualOutputFile.h b/llvm/include/llvm/Support/VirtualOutputFile.h
new file mode 100644
index 00000000000000..0bf6c58f30484d
--- /dev/null
+++ b/llvm/include/llvm/Support/VirtualOutputFile.h
@@ -0,0 +1,162 @@
+//===- VirtualOutputFile.h - Output file virtualization ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===------------------------------------------------------------...
[truncated]

Created using spr 1.3.6

[skip ci]
Created using spr 1.3.6
@cachemeifyoucan cachemeifyoucan changed the base branch from users/cachemeifyoucan/spr/main.support-add-vfsoutputbackend-and-outputfile-to-virtualize-compiler-outputs to main August 26, 2025 23:32
Created using spr 1.3.6
@cachemeifyoucan
Copy link
Collaborator Author

ping

//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declarations of the VirtualOutputBackend class.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather have a short paragraph here about what the purpose of this file is, not what classes it declares? Same for the other files. The goal would be to create a quick mental model before actually browsing through the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added more explanations. Please review and let me know if needs more improvements.

struct ProxyOutputBackend2 : public ProxyOutputBackend {
using ProxyOutputBackend::ProxyOutputBackend;
};
struct MirroringOutput final : public OutputFileImpl, raw_pwrite_stream {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please comment this class or bikeshed the naming a bit? It is seems it's more about demultiplexing, or writing concurently (from the API perspective) to several files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really demultiplexing, but duplicating. I clarify a bit in the header file, not sure if there is a better name but open to suggestions.

});
}

Error OnDiskOutputFile::initializeFD(std::optional<int> &FD) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: FD is a Unix nomenclature, the Windows equivalent is a Handle. If ever you have better ideas for a more broad/inclusive API naming.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to initializeFile but keep the variable name since we still convert fileHandle to FD in LLVM sys::fs APIs.

});
}

Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, it wasn't clear for me at first that a lot of code here is a copy/rework of CompilerInstance::createOutputFileImpl()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, correct. This re-implements the clang output file logics. The follow up is to adopt clang to use it. Other tools can use a unified output file logics in LLVM as well.

Created using spr 1.3.6
template <typename HasherT> class HashingOutputBackend : public OutputBackend {
private:
friend class HashingOutputFile<HasherT>;
void addOutputFile(StringRef Path, StringRef Hash) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move this implementation into the cpp file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a template class on HasherType.

Created using spr 1.3.6
cachemeifyoucan added a commit to cachemeifyoucan/llvm-project that referenced this pull request Sep 3, 2025
… outputs

Add OutputBackend and OutputFile to the `llvm::vfs` namespace for
virtualizing compiler outputs. This is intended for use in Clang,

The headers are:

- llvm/Support/VirtualOutputConfig.h
- llvm/Support/VirtualOutputError.h
- llvm/Support/VirtualOutputFile.h
- llvm/Support/VirtualOutputBackend.h

OutputFile is moveable and owns an OutputFileImpl, which is provided by
the derived OutputBackend.

- OutputFileImpl::keep() and OutputFileImpl::discard() should keep or
  discard the output.  OutputFile guarantees that exactly one of these
  will be called before destruction.
- OutputFile::keep() and OutputFile::discard() wrap OutputFileImpl
  and catch usage errors such as double-close.
- OutputFile::discardOnDestroy() installs an error handler for the
  destructor to use if the file is still open. The handler will be
  called if discard() fails.
- OutputFile::~OutputFile() calls report_fatal_error() if none of
  keep(), discard(), or discardOnDestroy() has been called. It still
  calls OutputFileImpl::discard().
- getOS() returns the wrapped raw_pwrite_stream. For convenience,
  OutputFile has an implicit conversion to `raw_ostream` and
  `raw_ostream &operator<<(OutputFile&, T&&)`.

OutputBackend can be stored in IntrusiveRefCntPtr.

- Most operations are thread-safe.
- clone() returns a backend that targets the same destination.
  All operations are thread-safe when done on different clones.
- createFile() takes a path and an OutputConfig (see below) and returns
  an OutputFile. Backends implement createFileImpl().

OutputConfig has flags to configure the output. Backends may ignore or
override flags that aren't relevant or implementable.

- The initial flags are:
    - AtomicWrite: whether the output should appear atomically (e.g., by
      using a temporary file and renaming it).
    - CrashCleanup: whether the output should be cleaned up if there's a
      crash (e.g., with RemoveFileOnSignal).
    - ImplyCreateDirectories: whether to implicitly create missing
      directories in the path to the file.
    - Text: matches sys::fs::OF_Text.
    - CRLF: matches sys::fs::OF_CRLF.
    - Append: matches sys::fs::OF_Append and can use with AtomicWrite
      for atomic append.
    - OnlyIfDifferent: skip writting the output file if the existing file
      at the output path is identical to the content to be written.
- Each "Flag" has `setFlag(bool)` and `bool getFlag()` and shortcuts
  `setFlag()` and `setNoFlag()`. The setters are `constexpr` and return
  `OutputConfig&` to make it easy to declare a default value for a filed
  in a class or struct.
- Setters and getters for Binary and TextWithCRLF are derived from Text
  and CRLF. For convenience, sys::fs::OpenFlags can be passed
  directly to setOpenFlags().

This patch intentionally lacks a number of important features that have
been left for follow-ups:

- Set a (virtual) current working directory.
- Create a directory.
- Create a file or directory with a unique name (avoiding collisions
  with existing filenames).

Patch originally by dexonsmith

Reviewers: 

Pull Request: llvm#113363
Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cachemeifyoucan cachemeifyoucan merged commit 07d0225 into main Sep 5, 2025
9 checks passed
@cachemeifyoucan cachemeifyoucan deleted the users/cachemeifyoucan/spr/support-add-vfsoutputbackend-and-outputfile-to-virtualize-compiler-outputs branch September 5, 2025 17:31
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 5, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-sles-build-only running on rocm-worker-hw-04-sles while building llvm at step 9 "Add check check-llvm".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/140/builds/30194

Here is the relevant piece of the build log for the reference
Step 9 (Add check check-llvm) failure: test (failure)
...
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/tools/llvm-exegesis/lib/ProgressMeter.h: In instantiation of ‘void llvm::exegesis::ProgressMeter<ClockTypeTy, <template-parameter-1-2> >::step(llvm::exegesis::ProgressMeter<ClockTypeTy, <template-parameter-1-2> >::DurationType) [with ClockTypeTy = llvm::exegesis::{anonymous}::PreprogrammedClock; <template-parameter-1-2> = void; llvm::exegesis::ProgressMeter<ClockTypeTy, <template-parameter-1-2> >::DurationType = std::chrono::duration<long int>; typename ClockTypeTy::period = std::ratio<1>; typename ClockTypeTy::rep = long int]’:
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/tools/llvm-exegesis/lib/ProgressMeter.h:86:10:   required from ‘llvm::exegesis::ProgressMeter<ClockTypeTy, <template-parameter-1-2> >::ProgressMeterStep::~ProgressMeterStep() [with ClockTypeTy = llvm::exegesis::{anonymous}::PreprogrammedClock; <template-parameter-1-2> = void]’
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/tools/llvm-exegesis/ProgressMeterTest.cpp:49:40:   required from here
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/tools/llvm-exegesis/lib/ProgressMeter.h:110:30: warning: unused variable ‘OldEta’ [-Wunused-variable]
     auto [OldProgress, OldEta] = eta();
                              ^
[678/730] Building CXX object unittests/tools/llvm-exegesis/CMakeFiles/LLVMExegesisTests.dir/RegisterValueTest.cpp.o
[679/730] Building CXX object unittests/tools/llvm-exegesis/CMakeFiles/LLVMExegesisTests.dir/ResultAggregatorTest.cpp.o
[680/730] Linking CXX executable unittests/Frontend/LLVMFrontendTests
[681/730] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o
FAILED: unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o 
ccache /usr/bin/c++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Iunittests/Support -I/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/Support -Iinclude -I/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/include -I/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include -I/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googlemock/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -Wno-misleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG  -Wno-dangling-else -Wno-variadic-macros -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -std=c++1z -MD -MT unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -MF unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o.d -o unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -c /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/Support/VirtualOutputConfigTest.cpp
In file included from /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/gtest-printers.h:122:0,
                 from /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/gtest-matchers.h:49,
                 from /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h:47,
                 from /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/gtest-death-test.h:43,
                 from /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/gtest.h:65,
                 from /home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/Support/VirtualOutputConfigTest.cpp:11:
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/Support/VirtualOutputConfigTest.cpp: In member function ‘virtual void {anonymous}::VirtualOutputConfigTest_equals_Test::TestBody()’:
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3:   in constexpr expansion of ‘llvm::vfs::OutputConfig().llvm::vfs::OutputConfig::operator==(llvm::vfs::OutputConfig())’
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/internal/gtest-internal.h:1493:48: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2578
           ::testing::AssertionResult(expression))                     \
                                                ^
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/gtest.h:1792:3: note: in expansion of macro ‘GTEST_TEST_BOOLEAN_’
   GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
   ^~~~~~~~~~~~~~~~~~~
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/third-party/unittest/googletest/include/gtest/gtest.h:1807:32: note: in expansion of macro ‘GTEST_EXPECT_TRUE’
 #define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
                                ^~~~~~~~~~~~~~~~~
/home/botworker/bbot/builds/openmp-offload-sles-build/llvm.src/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3: note: in expansion of macro ‘EXPECT_TRUE’
   EXPECT_TRUE(OutputConfig() == OutputConfig());
   ^~~~~~~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://bugs.opensuse.org/> for instructions.
[682/730] Building CXX object unittests/tools/llvm-exegesis/CMakeFiles/LLVMExegesisTests.dir/X86/BenchmarkResultTest.cpp.o
[683/730] Building CXX object unittests/tools/llvm-exegesis/CMakeFiles/LLVMExegesisTests.dir/X86/RegisterAliasingTest.cpp.o
[684/730] Linking CXX executable unittests/XRay/XRayTests
[685/730] Linking CXX executable unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerTests
[686/730] Linking CXX executable unittests/Transforms/Vectorize/VectorizeTests
[687/730] Linking CXX executable unittests/Transforms/IPO/IPOTests
[688/730] Linking CXX executable unittests/tools/llvm-cfi-verify/CFIVerifyTests
[689/730] Linking CXX executable unittests/Analysis/AnalysisTests
[690/730] Linking CXX executable unittests/Transforms/Instrumentation/InstrumentationTests
[691/730] Linking CXX executable unittests/ExecutionEngine/Orc/OrcJITTests
[692/730] Linking CXX executable unittests/Transforms/Coroutines/CoroTests
[693/730] Linking CXX executable unittests/Passes/PassBuilderBindings/PassesBindingsTests
[694/730] Linking CXX executable unittests/CodeGen/GlobalISel/GlobalISelTests
[695/730] Linking CXX executable unittests/CodeGen/CodeGenTests

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 5, 2025

LLVM Buildbot has detected a new failure on builder ppc64le-lld-multistage-test running on ppc64le-lld-multistage-test while building llvm at step 6 "build-stage1-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/168/builds/15920

Here is the relevant piece of the build log for the reference
Step 6 (build-stage1-unified-tree) failure: build (failure)
...
143.123 [957/42/5686] Linking CXX executable unittests/Transforms/Vectorize/VectorizeTests
143.125 [957/41/5687] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputBackendTest.cpp.o
143.470 [957/40/5688] Linking CXX executable tools/clang/unittests/Format/FormatTests
143.471 [957/39/5689] Linking CXX executable bin/llvm-cat
143.607 [957/38/5690] Linking CXX executable bin/llvm-offload-wrapper
144.385 [957/37/5691] Linking CXX executable bin/llvm-cgdata
144.417 [957/36/5692] Linking CXX executable bin/llvm-as
144.572 [957/35/5693] Linking CXX executable unittests/ExecutionEngine/ExecutionEngineTests
144.752 [957/34/5694] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputFileTest.cpp.o
145.175 [957/33/5695] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o
FAILED: unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o 
ccache /usr/lib64/ccache/c++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/unittests/Support -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/Support -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googlemock/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -Wno-misleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -std=c++17  -Wno-dangling-else -Wno-variadic-macros -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -MF unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o.d -o unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -c /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp
In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/gtest-printers.h:122,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/gtest-matchers.h:49,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h:47,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/gtest-death-test.h:43,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:65,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp:11:
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp: In member function ‘virtual void {anonymous}::VirtualOutputConfigTest_equals_Test::TestBody()’:
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3:   in ‘constexpr’ expansion of ‘llvm::vfs::OutputConfig().llvm::vfs::OutputConfig::operator==(llvm::vfs::OutputConfig())’
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/internal/gtest-internal.h:1493:48: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2683
           ::testing::AssertionResult(expression))                     \
                                                ^
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:1792:3: note: in expansion of macro ‘GTEST_TEST_BOOLEAN_’
   GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
   ^~~~~~~~~~~~~~~~~~~
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:1807:32: note: in expansion of macro ‘GTEST_EXPECT_TRUE’
 #define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
                                ^~~~~~~~~~~~~~~~~
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3: note: in expansion of macro ‘EXPECT_TRUE’
   EXPECT_TRUE(OutputConfig() == OutputConfig());
   ^~~~~~~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
Preprocessed source stored into /tmp/ccWXuv27.out file, please attach this to your bugreport.
145.188 [957/32/5696] Linking CXX executable unittests/FuzzMutate/FuzzMutateTests
145.381 [957/31/5697] Building AMDGPUGenAsmWriter.inc...
145.897 [957/30/5698] Linking CXX executable bin/llvm-link
147.480 [957/29/5699] Linking CXX executable unittests/Transforms/IPO/IPOTests
148.502 [957/28/5700] Building CXX object lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetMachine.cpp.o
153.575 [957/27/5701] Building AMDGPUGenInstrInfo.inc...
153.941 [957/26/5702] Building CXX object lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetTransformInfo.cpp.o
153.964 [957/25/5703] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputBackendsTest.cpp.o
155.293 [957/24/5704] Building AMDGPUGenGlobalISel.inc...
156.712 [957/23/5705] Building CXX object lib/CodeGen/AsmPrinter/CMakeFiles/LLVMAsmPrinter.dir/AsmPrinter.cpp.o
159.206 [957/22/5706] Building CXX object lib/LTO/CMakeFiles/LLVMLTO.dir/LTO.cpp.o
In file included from /usr/include/c++/8/cassert:44,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/include/llvm/ProfileData/InstrProf.h:40,

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 5, 2025

LLVM Buildbot has detected a new failure on builder clang-ppc64le-linux-test-suite running on ppc64le-clang-test-suite while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/95/builds/17944

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
...
20.203 [5/4/77] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-calls-Noinst-Test
20.543 [5/3/78] Generating ASAN_NOINST_TEST_OBJECTS.gtest-all.cc.powerpc64le-inline.o
20.740 [4/3/79] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-inline-Noinst-Test
23.028 [4/2/80] Generating ASAN_INST_TEST_OBJECTS.gtest-all.cc.powerpc64le-calls.o
23.275 [2/3/81] Generating POWERPC64LELinuxDynamicConfig/Asan-powerpc64le-calls-Dynamic-Test
23.464 [2/2/82] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-calls-Test
26.517 [2/1/83] Generating ASAN_INST_TEST_OBJECTS.gtest-all.cc.powerpc64le-inline.o
26.763 [0/2/84] Generating POWERPC64LELinuxDynamicConfig/Asan-powerpc64le-inline-Dynamic-Test
26.952 [0/1/85] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-inline-Test
8.890 [4/54/1190] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o
FAILED: unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o 
ccache /usr/lib64/ccache/c++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/unittests/Support -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/unittests/Support -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googlemock/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -Wno-misleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -std=c++17  -Wno-dangling-else -Wno-variadic-macros -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -MF unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o.d -o unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -c /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp
In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/gtest-printers.h:122,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/gtest-matchers.h:49,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h:47,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/gtest-death-test.h:43,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:65,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp:11:
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp: In member function ‘virtual void {anonymous}::VirtualOutputConfigTest_equals_Test::TestBody()’:
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3:   in ‘constexpr’ expansion of ‘llvm::vfs::OutputConfig().llvm::vfs::OutputConfig::operator==(llvm::vfs::OutputConfig())’
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/internal/gtest-internal.h:1493:48: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2683
           ::testing::AssertionResult(expression))                     \
                                                ^
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:1792:3: note: in expansion of macro ‘GTEST_TEST_BOOLEAN_’
   GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
   ^~~~~~~~~~~~~~~~~~~
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:1807:32: note: in expansion of macro ‘GTEST_EXPECT_TRUE’
 #define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
                                ^~~~~~~~~~~~~~~~~
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3: note: in expansion of macro ‘EXPECT_TRUE’
   EXPECT_TRUE(OutputConfig() == OutputConfig());
   ^~~~~~~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
Preprocessed source stored into /tmp/ccjDyzCu.out file, please attach this to your bugreport.
30.353 [4/6/1238] Linking CXX executable unittests/DebugInfo/LogicalView/DebugInfoLogicalViewTests
34.843 [4/4/1240] Linking CXX executable tools/clang/unittests/Interpreter/ExceptionTests/ClangReplInterpreterExceptionTests
36.455 [4/3/1241] Linking CXX executable tools/clang/unittests/Interpreter/ClangReplInterpreterTests
48.260 [4/2/1242] Linking CXX executable tools/clang/tools/extra/clangd/unittests/ClangdTests
48.822 [4/1/1243] Linking CXX executable tools/clang/unittests/AllClangUnitTests
ninja: build stopped: subcommand failed.

cachemeifyoucan added a commit that referenced this pull request Sep 5, 2025
Drop few `constexpr` from the change that causes internal compiler error
in some GCC versions used in some buildbot.
@cachemeifyoucan
Copy link
Collaborator Author

Looks like GCC ICE on some constexpr. Attempted a quick fix here: fb60def

If that doesn't work, I will revert.

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 5, 2025

LLVM Buildbot has detected a new failure on builder clang-ppc64le-linux-multistage running on ppc64le-clang-multistage-test while building llvm at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/76/builds/12686

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
...
[77/85] Generating ASAN_NOINST_TEST_OBJECTS.gtest-all.cc.powerpc64le-inline.o
[78/85] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-calls-Noinst-Test
[79/85] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-inline-Noinst-Test
[80/85] Generating ASAN_INST_TEST_OBJECTS.gtest-all.cc.powerpc64le-calls.o
[81/85] Generating POWERPC64LELinuxDynamicConfig/Asan-powerpc64le-calls-Dynamic-Test
[82/85] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-calls-Test
[83/85] Generating ASAN_INST_TEST_OBJECTS.gtest-all.cc.powerpc64le-inline.o
[84/85] Generating POWERPC64LELinuxDynamicConfig/Asan-powerpc64le-inline-Dynamic-Test
[85/85] Generating POWERPC64LELinuxConfig/Asan-powerpc64le-inline-Test
[1241/1251] Building CXX object unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o
FAILED: unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o 
ccache /usr/lib64/ccache/c++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/stage1/unittests/Support -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/unittests/Support -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/stage1/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googlemock/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -Wno-misleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -std=c++17  -Wno-dangling-else -Wno-variadic-macros -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -MF unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o.d -o unittests/Support/CMakeFiles/SupportTests.dir/VirtualOutputConfigTest.cpp.o -c /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/unittests/Support/VirtualOutputConfigTest.cpp
In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/gtest-printers.h:122,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/gtest-matchers.h:49,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h:47,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/gtest-death-test.h:43,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/gtest.h:65,
                 from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/unittests/Support/VirtualOutputConfigTest.cpp:11:
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/unittests/Support/VirtualOutputConfigTest.cpp: In member function ‘virtual void {anonymous}::VirtualOutputConfigTest_equals_Test::TestBody()’:
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3:   in ‘constexpr’ expansion of ‘llvm::vfs::OutputConfig().llvm::vfs::OutputConfig::operator==(llvm::vfs::OutputConfig())’
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/internal/gtest-internal.h:1493:48: internal compiler error: in cxx_eval_bit_field_ref, at cp/constexpr.c:2683
           ::testing::AssertionResult(expression))                     \
                                                ^
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/gtest.h:1792:3: note: in expansion of macro ‘GTEST_TEST_BOOLEAN_’
   GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
   ^~~~~~~~~~~~~~~~~~~
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/third-party/unittest/googletest/include/gtest/gtest.h:1807:32: note: in expansion of macro ‘GTEST_EXPECT_TRUE’
 #define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
                                ^~~~~~~~~~~~~~~~~
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/llvm/unittests/Support/VirtualOutputConfigTest.cpp:72:3: note: in expansion of macro ‘EXPECT_TRUE’
   EXPECT_TRUE(OutputConfig() == OutputConfig());
   ^~~~~~~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
Preprocessed source stored into /tmp/ccU72piE.out file, please attach this to your bugreport.
[1245/1251] Linking CXX executable tools/clang/unittests/AllClangUnitTests
ninja: build stopped: subcommand failed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants