[llvm] [CMAKE][llvm-libraries] Add Precompiled Headers option to improve build times (PR #91755)

Ameer J via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 7 10:25:34 PDT 2024


https://github.com/ameerj updated https://github.com/llvm/llvm-project/pull/91755

>From 7fb7a91424887fb68810a2a992bed72deef7c22b Mon Sep 17 00:00:00 2001
From: ameerj <ameerj99 at outlook.com>
Date: Sun, 26 May 2024 23:13:46 -0400
Subject: [PATCH 1/3] [CMAKE][llvm-libraries] Add Precompiled Headers option to
 improve build times

---
 llvm/CMakeLists.txt                           |  3 +
 llvm/cmake/modules/HandleLLVMOptions.cmake    | 11 ++-
 .../modules/LLVMPrecompiledHeaders.cmake      | 65 ++++++++++++
 llvm/include/llvm/ADT/ConcurrentHashtable.h   |  1 -
 llvm/include/llvm/PrecompiledHeaders.h        | 99 +++++++++++++++++++
 .../DWARF/DWARFAbbreviationDeclaration.cpp    |  2 +-
 llvm/lib/Object/Minidump.cpp                  |  2 +-
 llvm/lib/Support/CMakeLists.txt               | 15 +++
 8 files changed, 194 insertions(+), 4 deletions(-)
 create mode 100644 llvm/cmake/modules/LLVMPrecompiledHeaders.cmake
 create mode 100644 llvm/include/llvm/PrecompiledHeaders.h

diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index c06e661573ed4..e36abfaf475f0 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -1410,3 +1410,6 @@ endif()
 if (LLVM_INCLUDE_UTILS AND LLVM_INCLUDE_TOOLS)
   add_subdirectory(utils/llvm-locstats)
 endif()
+
+include(LLVMPrecompiledHeaders)
+llvm_lib_precompiled_headers()
diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 185266c0861e8..15b9e21b53935 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -538,6 +538,11 @@ endif()
 
 option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON)
 
+option(LLVM_ENABLE_LIB_PRECOMPILED_HEADERS "Enable precompiled headers for LLVM Lib projects to improve build times." ON)
+
+set(LLVM_LIB_DIRETORIES_FOR_PRECOMPILED_HEADERS ""
+    CACHE STRING "Semicolon-separated list of lib subdirectories to use precompiled headers")
+
 if( MSVC )
 
   # Add definitions that make MSVC much less annoying.
@@ -593,7 +598,11 @@ if( MSVC )
   # PDBs without changing codegen.
   option(LLVM_ENABLE_PDB OFF)
   if (LLVM_ENABLE_PDB AND uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
-    append("/Zi" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+    if (LLVM_ENABLE_LIB_PRECOMPILED_HEADERS)
+        append("/Z7" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+    else()
+        append("/Zi" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+    endif()
     # /DEBUG disables linker GC and ICF, but we want those in Release mode.
     append("/DEBUG /OPT:REF /OPT:ICF"
           CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS
diff --git a/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake b/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake
new file mode 100644
index 0000000000000..dabcf9f2b2581
--- /dev/null
+++ b/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake
@@ -0,0 +1,65 @@
+macro(get_all_targets_recursive targets dir)
+    get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
+    foreach(subdir ${subdirectories})
+        get_all_targets_recursive(${targets} ${subdir})
+    endforeach()
+
+    get_property(current_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
+    list(APPEND ${targets} ${current_targets})
+endmacro()
+
+function(get_all_targets dir outvar)
+    set(targets)
+    get_all_targets_recursive(targets ${dir})
+    set(${outvar} ${targets} PARENT_SCOPE)
+endfunction()
+
+function(add_llvm_lib_precompiled_headers target)
+    get_target_property(target_type ${target} TYPE)
+    if (target_type STREQUAL "STATIC_LIBRARY")
+        target_precompile_headers(${target} REUSE_FROM LLVMPchTarget)
+    endif()
+endfunction()
+
+function(add_llvm_subdir_pch subdir)
+    get_all_targets("${LLVM_MAIN_SRC_DIR}/lib/${subdir}" lib_targets)
+    foreach(target ${lib_targets})
+        add_llvm_lib_precompiled_headers(${target})
+    endforeach()
+endfunction()
+
+function(llvm_lib_precompiled_headers)
+    if (LLVM_ENABLE_LIB_PRECOMPILED_HEADERS)
+        # Create a dummy source file to compile the PCH target.
+        set(pch_dummy_cpp ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp)
+        if (NOT EXISTS ${pch_dummy_cpp})
+            FILE(TOUCH ${pch_dummy_cpp})
+        endif()
+
+        set(precompiled_header_path ${LLVM_MAIN_INCLUDE_DIR}/llvm/PrecompiledHeaders.h)
+        add_llvm_component_library(LLVMPchTarget ${pch_dummy_cpp} ${precompiled_header_path})
+        target_precompile_headers(LLVMPchTarget PUBLIC "$<$<COMPILE_LANGUAGE:CXX>:${LLVM_MAIN_INCLUDE_DIR}/llvm/PrecompiledHeaders.h>")
+
+        if (NOT ${LLVM_LIB_DIRETORIES_FOR_PRECOMPILED_HEADERS})
+            set(default_lib_dirs_for_pch
+                "Analysis"
+                "Codegen"
+                "DebugInfo"
+                "ExecutionEngine"
+                "IR"
+                "MC"
+                "MCA"
+                "ObjCopy"
+                "Object"
+                "Passes"
+                "Support"
+                "Target"
+                "Transforms"
+            )
+            set(LLVM_LIB_DIRETORIES_FOR_PRECOMPILED_HEADERS ${default_lib_dirs_for_pch})
+        endif()
+        foreach(subdir ${LLVM_LIB_DIRETORIES_FOR_PRECOMPILED_HEADERS})
+	        add_llvm_subdir_pch(${subdir})
+        endforeach()
+    endif()
+endfunction()
diff --git a/llvm/include/llvm/ADT/ConcurrentHashtable.h b/llvm/include/llvm/ADT/ConcurrentHashtable.h
index ffbeece1a8934..3d8876e138161 100644
--- a/llvm/include/llvm/ADT/ConcurrentHashtable.h
+++ b/llvm/include/llvm/ADT/ConcurrentHashtable.h
@@ -16,7 +16,6 @@
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Parallel.h"
-#include "llvm/Support/WithColor.h"
 #include "llvm/Support/xxhash.h"
 #include <atomic>
 #include <cstddef>
diff --git a/llvm/include/llvm/PrecompiledHeaders.h b/llvm/include/llvm/PrecompiledHeaders.h
new file mode 100644
index 0000000000000..4ffee4bc65ff0
--- /dev/null
+++ b/llvm/include/llvm/PrecompiledHeaders.h
@@ -0,0 +1,99 @@
+//===-- llvm/PrecompiledHeaders.h - Precompiled Headers ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains common headers used within the LLVM library.
+/// It is intended to be used as a precompiled header.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PRECOMPILEDHEADERS_H
+#define LLVM_PRECOMPILEDHEADERS_H
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+
+#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/ADL.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/bit.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/EpochTracker.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMapEntry.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ilist_node_base.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/ilist_node_options.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+#include <algorithm>
+#include <utility>
+#include <optional>
+#include <vector>
+#include <string>
+#include <memory>
+#include <iterator>
+#include <map>
+#include <tuple>
+#include <limits>
+#include <set>
+#include <system_error>
+#include <functional>
+#include <numeric>
+#include <deque>
+#include <sstream>
+#include <queue>
+#include <type_traits>
+#include <mutex>
+#include <array>
+#include <list>
+#include <atomic>
+#include <unordered_map>
+#include <bitset>
+#include <new>
+#include <unordered_set>
+#include <iomanip>
+#include <thread>
+#include <variant>
+#include <future>
+#include <stack>
+#include <chrono>
+#include <initializer_list>
+#include <random>
+
+#include <cctype>
+#include <cerrno>
+#include <cfloat>
+#include <cinttypes>
+#include <climits>
+#include <clocale>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <cwchar>
+
+#endif // LLVM_PRECOMPILEDHEADERS_H
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
index ecdbd004efadb..1ade83cf275e0 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -68,7 +68,7 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint64_t *OffsetPtr) {
 
   // Read all of the abbreviation attributes and forms.
   while (Data.isValidOffset(*OffsetPtr)) {
-    auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr, &Err));
+    auto A = static_cast<dwarf::Attribute>(Data.getULEB128(OffsetPtr, &Err));
     if (Err)
       return std::move(Err);
 
diff --git a/llvm/lib/Object/Minidump.cpp b/llvm/lib/Object/Minidump.cpp
index 6febff89ac519..11c52182d20fd 100644
--- a/llvm/lib/Object/Minidump.cpp
+++ b/llvm/lib/Object/Minidump.cpp
@@ -92,7 +92,7 @@ Expected<ArrayRef<T>> MinidumpFile::getListStream(StreamType Type) const {
 
   return getDataSliceAs<T>(*Stream, ListOffset, ListSize);
 }
-template Expected<ArrayRef<Module>>
+template Expected<ArrayRef<minidump::Module>>
     MinidumpFile::getListStream(StreamType) const;
 template Expected<ArrayRef<Thread>>
     MinidumpFile::getListStream(StreamType) const;
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 03e888958a071..2f4787400d7f3 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -297,6 +297,21 @@ add_llvm_component_library(LLVMSupport
 
 set(llvm_system_libs ${system_libs})
 
+if (LLVM_ENABLE_LIB_PRECOMPILED_HEADERS)
+  # CMake cannot use a C++ PCH in source targets that are non-C++
+  # Ideally this would be handled by LLVMPrecompiledHeaders.cmake
+  set(non_cpp_sources 
+    regcomp.c
+    regerror.c
+    regexec.c
+    regfree.c
+    regstrlcpy.c
+  )
+  foreach(source ${non_cpp_sources})
+    set_source_files_properties(${source} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
+  endforeach()
+endif()
+
 # This block is only needed for llvm-config. When we deprecate llvm-config and
 # move to using CMake export, this block can be removed.
 if(LLVM_ENABLE_ZLIB)

>From 87bf5c2bde47e5f5fc1f9e3be3ffb88cb9fe895d Mon Sep 17 00:00:00 2001
From: ameerj <ameerj99 at outlook.com>
Date: Tue, 28 May 2024 18:24:54 -0400
Subject: [PATCH 2/3] fix formatting

---
 llvm/include/llvm/PrecompiledHeaders.h | 89 +++++++++++++-------------
 1 file changed, 44 insertions(+), 45 deletions(-)

diff --git a/llvm/include/llvm/PrecompiledHeaders.h b/llvm/include/llvm/PrecompiledHeaders.h
index 4ffee4bc65ff0..870e380682fa2 100644
--- a/llvm/include/llvm/PrecompiledHeaders.h
+++ b/llvm/include/llvm/PrecompiledHeaders.h
@@ -15,71 +15,70 @@
 #ifndef LLVM_PRECOMPILEDHEADERS_H
 #define LLVM_PRECOMPILEDHEADERS_H
 
-#include "llvm/IR/PassManager.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/PassManager.h"
 
-#include "llvm/ADT/STLForwardCompat.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/ADL.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/bit.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/iterator.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/EpochTracker.h"
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMapEntry.h"
+#include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/EpochTracker.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ilist_node_base.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringMapEntry.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/bit.h"
 #include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/ilist_node_base.h"
 #include "llvm/ADT/ilist_node_options.h"
-#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
 
 #include <algorithm>
-#include <utility>
-#include <optional>
-#include <vector>
-#include <string>
-#include <memory>
+#include <array>
+#include <atomic>
+#include <bitset>
+#include <chrono>
+#include <deque>
+#include <functional>
+#include <future>
+#include <initializer_list>
+#include <iomanip>
 #include <iterator>
-#include <map>
-#include <tuple>
 #include <limits>
-#include <set>
-#include <system_error>
-#include <functional>
+#include <list>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <new>
 #include <numeric>
-#include <deque>
-#include <sstream>
+#include <optional>
 #include <queue>
+#include <random>
+#include <set>
+#include <sstream>
+#include <stack>
+#include <string>
+#include <system_error>
+#include <thread>
+#include <tuple>
 #include <type_traits>
-#include <mutex>
-#include <array>
-#include <list>
-#include <atomic>
 #include <unordered_map>
-#include <bitset>
-#include <new>
 #include <unordered_set>
-#include <iomanip>
-#include <thread>
+#include <utility>
 #include <variant>
-#include <future>
-#include <stack>
-#include <chrono>
-#include <initializer_list>
-#include <random>
+#include <vector>
 
 #include <cctype>
 #include <cerrno>

>From 6597ffd46d2fcf2fd56cf7f8113a75df39cac194 Mon Sep 17 00:00:00 2001
From: ameerj <ameerj99 at outlook.com>
Date: Fri, 7 Jun 2024 13:13:39 -0400
Subject: [PATCH 3/3] Add cmake version check for PCH

---
 llvm/cmake/modules/LLVMPrecompiledHeaders.cmake | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake b/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake
index dabcf9f2b2581..9e17d956c1247 100644
--- a/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake
+++ b/llvm/cmake/modules/LLVMPrecompiledHeaders.cmake
@@ -29,7 +29,14 @@ function(add_llvm_subdir_pch subdir)
 endfunction()
 
 function(llvm_lib_precompiled_headers)
+    # target_precompile_headers was introduced in 3.16
+    if(${CMAKE_VERSION} VERSION_LESS "3.16")
+        message(STATUS "LLVM Lib Precompiled Headers requires CMake version 3.16")
+        set(LLVM_ENABLE_LIB_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE)
+    endif()
+
     if (LLVM_ENABLE_LIB_PRECOMPILED_HEADERS)
+        message(STATUS "LLVM Lib Precompiled Headers are enabled")
         # Create a dummy source file to compile the PCH target.
         set(pch_dummy_cpp ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp)
         if (NOT EXISTS ${pch_dummy_cpp})



More information about the llvm-commits mailing list