Browse Source

Precompile headers: Add unit tests

Cristian Adam 6 years ago
parent
commit
5772930164

+ 2 - 0
Tests/RunCMake/CMakeLists.txt

@@ -573,3 +573,5 @@ if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])")
 endif()
 
 add_RunCMake_test("CTestCommandExpandLists")
+
+add_RunCMake_test(PrecompileHeaders)

+ 3 - 0
Tests/RunCMake/PrecompileHeaders/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.15.0)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 17 - 0
Tests/RunCMake/PrecompileHeaders/DisabledPch-check.cmake

@@ -0,0 +1,17 @@
+if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+    set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/CMakeFiles/foo.dir/cmake_pch.h")
+    set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/CMakeFiles/foobar.dir/cmake_pch.h")
+else()
+    set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/cmake_pch.h")
+    set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/cmake_pch.h")
+endif()
+
+if (NOT EXISTS ${foo_pch_header})
+   set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} does not exist")
+   return()
+endif()
+
+if (EXISTS ${foobar_pch_header})
+   set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} should not exist")
+   return()
+endif()

+ 14 - 0
Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.15)
+project(DisabledPch C)
+
+add_library(foo foo.c)
+target_include_directories(foo PUBLIC include)
+target_precompile_headers(foo PUBLIC
+  foo.h
+  <stdio.h>
+  \"string.h\"
+)
+
+add_executable(foobar foobar.c)
+target_link_libraries(foobar foo)
+set_target_properties(foobar PROPERTIES DISABLE_PRECOMPILE_HEADERS ON)

+ 36 - 0
Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake

@@ -0,0 +1,36 @@
+if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+  set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/CMakeFiles/foo.dir/cmake_pch.h")
+  set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/CMakeFiles/foobar.dir/cmake_pch.h")
+else()
+  set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/cmake_pch.h")
+  set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/cmake_pch.h")
+endif()
+
+if (NOT EXISTS ${foo_pch_header})
+  set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} does not exist")
+  return()
+endif()
+
+if (NOT EXISTS ${foobar_pch_header})
+  set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} does not exist")
+  return()
+endif()
+
+file(STRINGS ${foo_pch_header} foo_pch_header_strings)
+
+if (NOT "#include \"foo.h\"" IN_LIST foo_pch_header_strings OR
+    NOT "#include <stdio.h>" IN_LIST foo_pch_header_strings OR
+    NOT "#include \"string.h\"" IN_LIST foo_pch_header_strings)
+  set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} has bad content")
+  return()
+endif()
+
+file(STRINGS ${foobar_pch_header} foobar_pch_header_strings)
+
+if (NOT "#include \"foo.h\"" IN_LIST foobar_pch_header_strings OR
+    NOT "#include <stdio.h>" IN_LIST foobar_pch_header_strings OR
+    NOT "#include \"string.h\"" IN_LIST foobar_pch_header_strings OR
+    NOT "#include \"bar.h\"" IN_LIST foobar_pch_header_strings)
+  set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} has bad content")
+  return()
+endif()

+ 4 - 1
Tests/PrecompileHeaders/CMakeLists.txt → Tests/RunCMake/PrecompileHeaders/PchInterface.cmake

@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 3.15)
-project(PrecompileHeaders C)
+project(PchInterface C)
 
 add_library(foo foo.c)
 target_include_directories(foo PUBLIC include)
@@ -15,3 +15,6 @@ target_precompile_headers(bar INTERFACE bar.h)
 
 add_executable(foobar foobar.c)
 target_link_libraries(foobar foo bar)
+
+enable_testing()
+add_test(NAME foobar COMMAND foobar)

+ 12 - 0
Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue-check.cmake

@@ -0,0 +1,12 @@
+if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+    set(main_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/main.dir/CMakeFiles/main.dir/cmake_pch.hxx")
+else()
+    set(main_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/main.dir/cmake_pch.hxx")
+endif()
+
+file(STRINGS ${main_pch_header} main_pch_header_strings)
+string(REGEX MATCH "#pragma warning\\(push, 0\\).*#include.*pch.h.*#pragma warning\\(pop\\)" matched_code ${main_pch_header_strings})
+if(NOT matched_code)
+  set(RunCMake_TEST_FAILED "Generated pch file doesn't include expected prologue and epilogue code")
+  return()
+endif()

+ 11 - 0
Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake

@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(PchPrologueEpilogue)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_PCH_PROLOGUE "#pragma warning(push, 0)")
+set(CMAKE_PCH_EPILOGUE "#pragma warning(pop)")
+
+add_executable(main main.cpp)
+target_precompile_headers(main PRIVATE pch.h)

+ 18 - 0
Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake

@@ -0,0 +1,18 @@
+cmake_policy(SET CMP0057 NEW)
+include(RunCMake)
+
+function(run_test name)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+  run_cmake(${name})
+  # Precompiled headers are not supported with multiple architectures.
+  if(NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+    set(RunCMake_TEST_NO_CLEAN 1)
+    run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug)
+    run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug)
+  endif()
+endfunction()
+
+run_cmake(DisabledPch)
+run_test(PchInterface)
+run_cmake(PchPrologueEpilogue)
+run_test(SkipPrecompileHeaders)

+ 13 - 0
Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake

@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(SkipPrecompileHeaders)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_executable(pch-test main.cpp non-pch.cpp)
+target_precompile_headers(pch-test PRIVATE pch.h)
+
+set_source_files_properties(non-pch.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
+
+enable_testing()
+add_test(NAME pch-test COMMAND pch-test)

+ 0 - 0
Tests/PrecompileHeaders/foo.c → Tests/RunCMake/PrecompileHeaders/foo.c


+ 0 - 0
Tests/PrecompileHeaders/foobar.c → Tests/RunCMake/PrecompileHeaders/foobar.c


+ 0 - 0
Tests/PrecompileHeaders/include/bar.h → Tests/RunCMake/PrecompileHeaders/include/bar.h


+ 0 - 0
Tests/PrecompileHeaders/include/foo.h → Tests/RunCMake/PrecompileHeaders/include/foo.h


+ 4 - 0
Tests/RunCMake/PrecompileHeaders/main.cpp

@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}

+ 3 - 0
Tests/RunCMake/PrecompileHeaders/non-pch.cpp

@@ -0,0 +1,3 @@
+#ifdef PCH_INCLUDED
+#  error "PCH must not be included into this file!"
+#endif

+ 3 - 0
Tests/RunCMake/PrecompileHeaders/pch.h

@@ -0,0 +1,3 @@
+#pragma once
+
+#define PCH_INCLUDED 1

+ 1 - 0
Tests/RunCMake/VS10Project/RunCMakeTest.cmake

@@ -25,6 +25,7 @@ run_cmake(VsProjectImport)
 run_cmake(VsPackageReferences)
 run_cmake(VsDpiAware)
 run_cmake(VsDpiAwareBadParam)
+run_cmake(VsPrecompileHeaders)
 
 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
   run_cmake(VsJustMyCode)

+ 69 - 0
Tests/RunCMake/VS10Project/VsPrecompileHeaders-check.cmake

@@ -0,0 +1,69 @@
+set(pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/cmake_pch.hxx")
+set(pch_source "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/cmake_pch.cxx")
+
+file(TO_NATIVE_PATH "${pch_source}" pch_source_win)
+
+if(NOT EXISTS "${pch_header}")
+  set(RunCMake_TEST_FAILED "Generated PCH header ${pch_header} does not exist.")
+  return()
+endif()
+if(NOT EXISTS "${pch_source}")
+  set(RunCMake_TEST_FAILED "Generated PCH header ${pch_source} does not exist.")
+  return()
+endif()
+
+set(tgt_project "${RunCMake_TEST_BINARY_DIR}/tgt.vcxproj")
+if (NOT EXISTS "${tgt_project}")
+  set(RunCMake_TEST_FAILED "Generated project file ${tgt_project} doesn't exist.")
+  return()
+endif()
+
+file(STRINGS ${tgt_project} tgt_projects_strings)
+
+foreach(line IN LISTS tgt_projects_strings)
+  if (line MATCHES "<PrecompiledHeader.*>Use</PrecompiledHeader>")
+    set(have_pch_use ON)
+  endif()
+
+  if (line MATCHES "<PrecompiledHeader.*>Create</PrecompiledHeader>")
+    set(have_pch_create ON)
+  endif()
+
+  if (line MATCHES "<PrecompiledHeaderFile.*>${pch_header}</PrecompiledHeaderFile>")
+    set(have_pch_header ON)
+  endif()
+
+  if (line MATCHES "<ForcedIncludeFiles.*>${pch_header}</ForcedIncludeFiles>")
+    set(have_force_pch_header ON)
+  endif()
+
+  string(FIND "${line}" "<ClCompile Include=\"${pch_source_win}\">" find_pos)
+  if (NOT find_pos EQUAL "-1")
+    set(have_pch_source_compile ON)
+  endif()
+endforeach()
+
+if (NOT have_pch_use)
+  set(RunCMake_TEST_FAILED "Generated project should have the <PrecompiledHeader>Use</PrecompiledHeader> block.")
+  return()
+endif()
+
+if (NOT have_pch_create)
+  set(RunCMake_TEST_FAILED "Generated project should have the <PrecompiledHeader>Create</PrecompiledHeader> block.")
+  return()
+endif()
+
+if (NOT have_pch_header)
+  set(RunCMake_TEST_FAILED "Generated project should have the <PrecompiledHeaderFile>${pch_header}</PrecompiledHeaderFile> block.")
+  return()
+endif()
+
+if (NOT have_force_pch_header)
+  set(RunCMake_TEST_FAILED "Generated project should have the <ForcedIncludeFiles>${pch_header}</ForcedIncludeFiles> block.")
+  return()
+endif()
+
+if (NOT have_pch_source_compile)
+  set(RunCMake_TEST_FAILED "Generated project should have the <ClCompile Include=\"${pch_source_win}\"> block.")
+  return()
+endif()

+ 4 - 0
Tests/RunCMake/VS10Project/VsPrecompileHeaders.cmake

@@ -0,0 +1,4 @@
+project(VsPrecompileHeaders CXX)
+
+add_library(tgt SHARED empty.cxx)
+target_precompile_headers(tgt PRIVATE stdafx.h)

+ 1 - 0
Tests/RunCMake/XcodeProject/RunCMakeTest.cmake

@@ -12,6 +12,7 @@ run_cmake(XcodeObjectNeedsQuote)
 run_cmake(XcodeOptimizationFlags)
 run_cmake(XcodePreserveNonOptimizationFlags)
 run_cmake(XcodePreserveObjcFlag)
+run_cmake(XcodePrecompileHeaders)
 if (NOT XCODE_VERSION VERSION_LESS 6)
   run_cmake(XcodePlatformFrameworks)
 endif()

+ 35 - 0
Tests/RunCMake/XcodeProject/XcodePrecompileHeaders-check.cmake

@@ -0,0 +1,35 @@
+set(pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/cmake_pch.hxx")
+
+if(NOT EXISTS "${pch_header}")
+  set(RunCMake_TEST_FAILED "Generated PCH header ${pch_header} does not exist.")
+  return()
+endif()
+
+set(tgt_project "${RunCMake_TEST_BINARY_DIR}/XcodePrecompileHeaders.xcodeproj/project.pbxproj")
+if (NOT EXISTS "${tgt_project}")
+  set(RunCMake_TEST_FAILED "Generated project file ${tgt_project} doesn't exist.")
+  return()
+endif()
+
+file(STRINGS ${tgt_project} tgt_projects_strings)
+
+foreach(line IN LISTS tgt_projects_strings)
+  if (line MATCHES "GCC_PRECOMPILE_PREFIX_HEADER = YES;")
+    set(have_pch_prefix ON)
+  endif()
+
+  string(FIND "${line}" "GCC_PREFIX_HEADER = \"${pch_header}\";" find_pos)
+  if (NOT find_pos EQUAL "-1")
+    set(have_pch_header ON)
+  endif()
+endforeach()
+
+if (NOT have_pch_prefix)
+  set(RunCMake_TEST_FAILED "Generated project should have the GCC_PRECOMPILE_PREFIX_HEADER = YES; line.")
+  return()
+endif()
+
+if (NOT have_pch_header)
+  set(RunCMake_TEST_FAILED "Generated project should have the GCC_PREFIX_HEADER = \"${pch_header}\"; line.")
+  return()
+endif()

+ 4 - 0
Tests/RunCMake/XcodeProject/XcodePrecompileHeaders.cmake

@@ -0,0 +1,4 @@
+project(XcodePrecompileHeaders CXX)
+
+add_library(tgt foo.cpp)
+target_precompile_headers(tgt PRIVATE stdafx.h)