Enable precompiled headers for spirv-tools(-shared) and some unit tests (#2026)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f992fc..0626e43 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,6 +212,18 @@
   add_definitions(-DSPIRV_CHECK_CONTEXT)
 endif()
 
+# Precompiled header macro. Parameters are source file list and filename for pch cpp file.
+macro(PCH SRCS PCHPREFIX)
+  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio")
+    set(PCH_NAME "$(IntDir)\\${PCHPREFIX}.pch")
+    # make source files use/depend on PCH_NAME
+    set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yu${PCHPREFIX}.h /FI${PCHPREFIX}.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
+    # make PCHPREFIX.cpp file compile and generate PCH_NAME
+    set_source_files_properties("${PCHPREFIX}.cpp" PROPERTIES COMPILE_FLAGS "/Yc${PCHPREFIX}.h /Fp${PCH_NAME} /Zm300" OBJECT_OUTPUTS "${PCH_NAME}")
+    list(APPEND ${SRCS} "${PCHPREFIX}.cpp")
+  endif()
+endmacro(PCH)
+
 add_subdirectory(external)
 
 add_subdirectory(source)
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index ea619f2..068fbbf 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -184,10 +184,10 @@
   PROPERTIES OBJECT_DEPENDS "${ENUM_STRING_MAPPING_CPP_DEPENDS}")
 
 set_source_files_properties(
-  ${CMAKE_CURRENT_SOURCE_DIR}/extension.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/extensions.h
   PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties(
-  ${CMAKE_CURRENT_SOURCE_DIR}/extension.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/extensions.h
   PROPERTIES OBJECT_DEPENDS "${EXTENSION_H_DEPENDS}")
 
 set(SPIRV_TOOLS_BUILD_VERSION_INC
@@ -209,6 +209,11 @@
    DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC})
 set_property(TARGET spirv-tools-build-version PROPERTY FOLDER "SPIRV-Tools build")
 
+list(APPEND PCH_DEPENDS ${ENUM_STRING_MAPPING_CPP_DEPENDS} ${OPCODE_CPP_DEPENDS} ${OPERAND_CPP_DEPENDS} ${EXTENSION_H_DEPENDS} ${EXTINST_CPP_DEPENDS} ${SPIRV_TOOLS_BUILD_VERSION_INC})
+set_source_files_properties(
+  ${CMAKE_CURRENT_SOURCE_DIR}/pch_source.cpp
+  PROPERTIES OBJECT_DEPENDS "${PCH_DEPENDS}")
+
 add_subdirectory(comp)
 add_subdirectory(opt)
 add_subdirectory(link)
@@ -340,6 +345,8 @@
   ${CMAKE_CURRENT_SOURCE_DIR}/software_version.cpp
   PROPERTIES OBJECT_DEPENDS "${SPIRV_TOOLS_BUILD_VERSION_INC}")
 
+PCH(SPIRV_SOURCES pch_source)
+
 add_library(${SPIRV_TOOLS} ${SPIRV_SOURCES})
 spvtools_default_compile_options(${SPIRV_TOOLS})
 target_include_directories(${SPIRV_TOOLS}
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index fd52ca6..eab78a6 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -188,18 +188,10 @@
 if(MSVC)
   # Enable parallel builds across four cores for this lib
   add_definitions(/MP4)
-
-  # Enable precompiled header
-  if (CMAKE_GENERATOR MATCHES "^Visual Studio")
-    set(PCH_NAME "$(IntDir)\\pch.pch")
-  else()
-    set(PCH_NAME "pch.pch")
-  endif()
-  set_source_files_properties(${SPIRV_TOOLS_OPT_SOURCES} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
-  set_source_files_properties(pch.cpp PROPERTIES COMPILE_FLAGS "/Ycpch.h /Fp${PCH_NAME} /Zm300" OBJECT_OUTPUTS "${PCH_NAME}")
-  list(APPEND SPIRV_TOOLS_OPT_SOURCES "pch.cpp")
 endif()
 
+PCH(SPIRV_TOOLS_OPT_SOURCES pch_source_opt)
+
 add_library(SPIRV-Tools-opt ${SPIRV_TOOLS_OPT_SOURCES})
 
 spvtools_default_compile_options(SPIRV-Tools-opt)
diff --git a/source/opt/pch.cpp b/source/opt/pch_source_opt.cpp
similarity index 95%
copy from source/opt/pch.cpp
copy to source/opt/pch_source_opt.cpp
index b8d3f6c..f45448d 100644
--- a/source/opt/pch.cpp
+++ b/source/opt/pch_source_opt.cpp
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "pch_source_opt.h"
diff --git a/source/opt/pch.h b/source/opt/pch_source_opt.h
similarity index 100%
rename from source/opt/pch.h
rename to source/opt/pch_source_opt.h
diff --git a/source/opt/pch.cpp b/source/pch_source.cpp
similarity index 95%
rename from source/opt/pch.cpp
rename to source/pch_source.cpp
index b8d3f6c..032e29e 100644
--- a/source/opt/pch.cpp
+++ b/source/pch_source.cpp
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "pch_source.h"
diff --git a/source/opt/pch.cpp b/source/pch_source.h
similarity index 92%
copy from source/opt/pch.cpp
copy to source/pch_source.h
index b8d3f6c..6695ba2 100644
--- a/source/opt/pch.cpp
+++ b/source/pch_source.h
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "source/val/validation_state.h"
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a8db33c..f2d05be 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -30,12 +30,16 @@
 
 function(add_spvtools_unittest)
   if (NOT "${SPIRV_SKIP_TESTS}" AND TARGET gmock_main)
-    set(one_value_args TARGET)
+    set(one_value_args TARGET PCH_FILE)
     set(multi_value_args SRCS LIBS ENVIRONMENT)
     cmake_parse_arguments(
       ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
     set(target test_${ARG_TARGET})
-    add_executable(${target} ${ARG_SRCS})
+    set(SRC_COPY ${ARG_SRCS})
+    if (DEFINED ARG_PCH_FILE)
+      PCH(SRC_COPY ${ARG_PCH_FILE})
+    endif()
+    add_executable(${target} ${SRC_COPY})
     spvtools_default_compile_options(${target})
     if(${COMPILER_IS_LIKE_GNU})
       target_compile_options(${target} PRIVATE -Wno-undef)
@@ -147,6 +151,8 @@
   unit_spirv.cpp
 )
 
+PCH(TEST_SOURCES pch_test)
+
 add_spvtools_unittest(
   TARGET spirv_unit_tests
   SRCS ${TEST_SOURCES}
diff --git a/test/opt/dominator_tree/CMakeLists.txt b/test/opt/dominator_tree/CMakeLists.txt
index f95a56d..813d628 100644
--- a/test/opt/dominator_tree/CMakeLists.txt
+++ b/test/opt/dominator_tree/CMakeLists.txt
@@ -27,4 +27,5 @@
        unreachable_for.cpp
        unreachable_for_post.cpp
   LIBS SPIRV-Tools-opt
+  PCH_FILE pch_test_opt_dom
 )
diff --git a/source/opt/pch.cpp b/test/opt/dominator_tree/pch_test_opt_dom.cpp
similarity index 94%
copy from source/opt/pch.cpp
copy to test/opt/dominator_tree/pch_test_opt_dom.cpp
index b8d3f6c..a28310e 100644
--- a/source/opt/pch.cpp
+++ b/test/opt/dominator_tree/pch_test_opt_dom.cpp
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "pch_test_opt_dom.h"
diff --git a/source/opt/pch.cpp b/test/opt/dominator_tree/pch_test_opt_dom.h
similarity index 60%
copy from source/opt/pch.cpp
copy to test/opt/dominator_tree/pch_test_opt_dom.h
index b8d3f6c..4e8106f 100644
--- a/source/opt/pch.cpp
+++ b/test/opt/dominator_tree/pch_test_opt_dom.h
@@ -12,4 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "gmock/gmock.h"
+#include "source/opt/iterator.h"
+#include "source/opt/loop_dependence.h"
+#include "source/opt/loop_descriptor.h"
+#include "source/opt/pass.h"
+#include "source/opt/scalar_analysis.h"
+#include "source/opt/tree_iterator.h"
+#include "test/opt/assembly_builder.h"
+#include "test/opt/function_utils.h"
+#include "test/opt/pass_fixture.h"
+#include "test/opt/pass_utils.h"
diff --git a/test/opt/loop_optimizations/CMakeLists.txt b/test/opt/loop_optimizations/CMakeLists.txt
index 8c7971b..e362078 100644
--- a/test/opt/loop_optimizations/CMakeLists.txt
+++ b/test/opt/loop_optimizations/CMakeLists.txt
@@ -37,4 +37,5 @@
        unroll_simple.cpp
        unswitch.cpp
   LIBS SPIRV-Tools-opt
+  PCH_FILE pch_test_opt_loop
 )
diff --git a/source/opt/pch.cpp b/test/opt/loop_optimizations/pch_test_opt_loop.cpp
similarity index 94%
copy from source/opt/pch.cpp
copy to test/opt/loop_optimizations/pch_test_opt_loop.cpp
index b8d3f6c..f4ac7b2 100644
--- a/source/opt/pch.cpp
+++ b/test/opt/loop_optimizations/pch_test_opt_loop.cpp
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "pch_test_opt_loop.h"
diff --git a/source/opt/pch.cpp b/test/opt/loop_optimizations/pch_test_opt_loop.h
similarity index 60%
copy from source/opt/pch.cpp
copy to test/opt/loop_optimizations/pch_test_opt_loop.h
index b8d3f6c..4e8106f 100644
--- a/source/opt/pch.cpp
+++ b/test/opt/loop_optimizations/pch_test_opt_loop.h
@@ -12,4 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "gmock/gmock.h"
+#include "source/opt/iterator.h"
+#include "source/opt/loop_dependence.h"
+#include "source/opt/loop_descriptor.h"
+#include "source/opt/pass.h"
+#include "source/opt/scalar_analysis.h"
+#include "source/opt/tree_iterator.h"
+#include "test/opt/assembly_builder.h"
+#include "test/opt/function_utils.h"
+#include "test/opt/pass_fixture.h"
+#include "test/opt/pass_utils.h"
diff --git a/source/opt/pch.cpp b/test/pch_test.cpp
similarity index 95%
copy from source/opt/pch.cpp
copy to test/pch_test.cpp
index b8d3f6c..3b06a0a 100644
--- a/source/opt/pch.cpp
+++ b/test/pch_test.cpp
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "pch_test.h"
diff --git a/source/opt/pch.cpp b/test/pch_test.h
similarity index 82%
copy from source/opt/pch.cpp
copy to test/pch_test.h
index b8d3f6c..7dac06a 100644
--- a/source/opt/pch.cpp
+++ b/test/pch_test.h
@@ -12,4 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "gmock/gmock.h"
+#include "source/spirv_constant.h"
+#include "test/test_fixture.h"
+#include "test/unit_spirv.h"
diff --git a/test/val/CMakeLists.txt b/test/val/CMakeLists.txt
index 14f355a..3d0eeba 100644
--- a/test/val/CMakeLists.txt
+++ b/test/val/CMakeLists.txt
@@ -38,6 +38,7 @@
        val_ext_inst_test.cpp
        ${VAL_TEST_COMMON_SRCS}
   LIBS ${SPIRV_TOOLS}
+  PCH_FILE pch_test_val
 )
 
 add_spvtools_unittest(TARGET val_limits
@@ -59,6 +60,7 @@
        val_primitives_test.cpp
        ${VAL_TEST_COMMON_SRCS}
   LIBS ${SPIRV_TOOLS}
+  PCH_FILE pch_test_val
 )
 
 add_spvtools_unittest(TARGET val_stuvw
@@ -72,4 +74,5 @@
        val_webgpu_test.cpp
        ${VAL_TEST_COMMON_SRCS}
   LIBS ${SPIRV_TOOLS}
+  PCH_FILE pch_test_val
 )
diff --git a/source/opt/pch.cpp b/test/val/pch_test_val.cpp
similarity index 95%
copy from source/opt/pch.cpp
copy to test/val/pch_test_val.cpp
index b8d3f6c..fc92e37 100644
--- a/source/opt/pch.cpp
+++ b/test/val/pch_test_val.cpp
@@ -12,4 +12,4 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include "pch_test_val.h"
diff --git a/source/opt/pch.cpp b/test/val/pch_test_val.h
similarity index 84%
copy from source/opt/pch.cpp
copy to test/val/pch_test_val.h
index b8d3f6c..7b5881c 100644
--- a/source/opt/pch.cpp
+++ b/test/val/pch_test_val.h
@@ -12,4 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "pch.h"
+#include <string>
+
+#include "gmock/gmock.h"
+#include "test/unit_spirv.h"
+#include "test/val/val_fixtures.h"