Merge topic 'toc_on_ppc' into release-3.16

90d8bd2deb Merge branch 'backport-3.15-toc_on_ppc' into backport-3.16-toc_on_ppc
b35926e260 Check for support before adding bigtoc linker flag
958f858ad8 Check for support before adding bigtoc linker flag
8c7b7df788 bootstrap: Add target_link_options command

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4122
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index ea5a3b3..5cc9328 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -98,7 +98,9 @@
     )
 
     set(CMAKE_PCH_EXTENSION .pch)
-    set(CMAKE_PCH_PROLOGUE "#pragma clang system_header")
+    if (NOT CMAKE_GENERATOR MATCHES "Xcode")
+      set(CMAKE_PCH_PROLOGUE "#pragma clang system_header")
+    endif()
     set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE>)
     set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER>)
   endmacro()
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index 6960571..1c050a2 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -111,7 +111,9 @@
   list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
 
   set(CMAKE_PCH_EXTENSION .gch)
-  set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header")
+  if (NOT CMAKE_GENERATOR MATCHES "Xcode")
+    set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header")
+  endif()
   set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -include <PCH_HEADER>)
   set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -x ${__pch_header_${lang}} -include <PCH_HEADER>)
 endmacro()
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index d39fe33..b0c91b2 100644
--- a/Modules/FindThreads.cmake
+++ b/Modules/FindThreads.cmake
@@ -77,7 +77,7 @@
   if(NOT Threads_FOUND)
      CHECK_LIBRARY_EXISTS(${LIBNAME} ${FUNCNAME} "" ${VARNAME})
      if(${VARNAME})
-       set(CMAKE_THREAD_LIBS_INIT "${LIBNAME}")
+       set(CMAKE_THREAD_LIBS_INIT "-l${LIBNAME}")
        set(CMAKE_HAVE_THREADS_LIBRARY 1)
        set(Threads_FOUND TRUE)
      endif()
@@ -88,7 +88,7 @@
 # Do NOT even think about using it outside of this file!
 macro(_check_pthreads_flag)
   if(NOT Threads_FOUND)
-    # If we did not find a thread library look for -pthread compiler option.
+    # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread
     if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG)
       message(STATUS "Check if compiler accepts -pthread")
       if(CMAKE_C_COMPILER_LOADED)
@@ -164,7 +164,7 @@
       _check_threads_lib(pthreads pthread_create CMAKE_HAVE_PTHREADS_CREATE)
       _check_threads_lib(pthread  pthread_create CMAKE_HAVE_PTHREAD_CREATE)
       if(CMAKE_SYSTEM_NAME MATCHES "SunOS")
-          # On sun also check for thread library with thr_create
+          # On sun also check for -lthread
           _check_threads_lib(thread thr_create CMAKE_HAVE_THR_CREATE)
       endif()
     endif()
@@ -195,7 +195,7 @@
     # are available.
     CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA)
     if(CMAKE_HAVE_HP_CMA)
-      set(CMAKE_THREAD_LIBS_INIT "cma")
+      set(CMAKE_THREAD_LIBS_INIT "-lcma")
       set(CMAKE_HP_PTHREADS_INIT 1)
       set(Threads_FOUND TRUE)
     endif()
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 96656a5..09fb87d 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1558,13 +1558,24 @@
   for (cmLocalGenerator* lg : this->LocalGenerators) {
     lg->CreateEvaluationFileOutputs();
     for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) {
-      if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+      if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+          gt->GetType() == cmStateEnums::UTILITY ||
+          gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
         continue;
       }
       lg->AddUnityBuild(gt);
       lg->AddPchDependencies(gt);
     }
   }
+  // The above transformations may have changed the classification of sources.
+  // Clear the source list and classification cache (KindedSources) of all
+  // targets so that it will be recomputed correctly by the generators later
+  // now that the above transformations are done for all targets.
+  for (cmLocalGenerator* lg : this->LocalGenerators) {
+    for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) {
+      gt->ClearSourcesCache();
+    }
+  }
   return true;
 }
 
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 2e499b3..1754421 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2307,6 +2307,7 @@
   }
   const std::string buildType = cmSystemTools::UpperCase(config);
 
+  // FIXME: Refactor collection of sources to not evaluate object libraries.
   std::vector<cmSourceFile*> sources;
   target->GetSourceFiles(sources, buildType);
 
@@ -2381,9 +2382,25 @@
                 target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/",
                 target->GetName(), ".dir/${PDB_PREFIX}");
 
-              file << "if (EXISTS \"" << from_file << "\")\n";
+              const std::string to_file =
+                cmStrCat(to_dir, pchReuseFrom, extension);
+
+              std::string dest_file = to_file;
+
+              const std::string prefix = target->GetSafeProperty("PREFIX");
+              if (!prefix.empty()) {
+                dest_file = cmStrCat(to_dir, prefix, pchReuseFrom, extension);
+              }
+
+              file << "if (EXISTS \"" << from_file << "\" AND \"" << from_file
+                   << "\" IS_NEWER_THAN \"" << dest_file << "\")\n";
               file << "  file(COPY \"" << from_file << "\""
                    << " DESTINATION \"" << to_dir << "\")\n";
+              if (!prefix.empty()) {
+                file << "  file(REMOVE \"" << dest_file << "\")\n";
+                file << "  file(RENAME \"" << to_file << "\" \"" << dest_file
+                     << "\")\n";
+              }
               file << "endif()\n";
             }
 
@@ -2469,6 +2486,7 @@
     cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/",
              target->GetName(), ".dir/Unity/");
 
+  // FIXME: Refactor collection of sources to not evaluate object libraries.
   std::vector<cmSourceFile*> sources;
   target->GetSourceFiles(sources, buildType);
 
@@ -2519,12 +2537,7 @@
         for (; begin != end; ++begin) {
           cmSourceFile* sf = filtered_sources[begin];
 
-          // Only in Visual Studio generator we keep the source files
-          // for explicit processing.
-          if (!this->GetGlobalGenerator()->IsMultiConfig() ||
-              this->GetGlobalGenerator()->IsXcode()) {
-            target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
-          }
+          target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
           sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
 
           if (beforeInclude) {
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 94b6495..5c0b881 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2141,7 +2141,6 @@
         this->WriteExtraSource(e1, si.Source);
         break;
       case cmGeneratorTarget::SourceKindHeader:
-      case cmGeneratorTarget::SourceKindUnityBatched:
         this->WriteHeaderSource(e1, si.Source);
         break;
       case cmGeneratorTarget::SourceKindIDL:
@@ -2153,6 +2152,7 @@
       case cmGeneratorTarget::SourceKindModuleDefinition:
         tool = "None";
         break;
+      case cmGeneratorTarget::SourceKindUnityBatched:
       case cmGeneratorTarget::SourceKindObjectSource: {
         const std::string& lang = si.Source->GetLanguage();
         if (lang == "C" || lang == "CXX") {
diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in
index ad8bfb0..846a828 100644
--- a/Templates/TestDriver.cxx.in
+++ b/Templates/TestDriver.cxx.in
@@ -54,7 +54,7 @@
   if (new_string == CM_NULL) { /* NOLINT */
     return CM_NULL;            /* NOLINT */
   }
-  strcpy(new_string, string);
+  strcpy(new_string, string);  /* NOLINT */
   for (p = new_string; *p != 0; ++p) {
     *p = CM_CAST(char, tolower(*p));
   }
diff --git a/Tests/CMakeLib/testCTestResourceSpec.cxx b/Tests/CMakeLib/testCTestResourceSpec.cxx
index b981387..b69003d 100644
--- a/Tests/CMakeLib/testCTestResourceSpec.cxx
+++ b/Tests/CMakeLib/testCTestResourceSpec.cxx
@@ -56,6 +56,7 @@
   {"spec33.json", false, {{{}}}},
   {"spec34.json", false, {{{}}}},
   {"spec35.json", false, {{{}}}},
+  {"spec36.json", false, {{{}}}},
   {"noexist.json", false, {{{}}}},
   /* clang-format on */
 };
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec36.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec36.json
new file mode 100644
index 0000000..6175b1a
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec36.json
@@ -0,0 +1,4 @@
+{
+  "local": [
+  ]
+}
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
index 208f3c9..cb1a2e5 100644
--- a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
@@ -4,4 +4,10 @@
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)
 +
+CMake Error at OwnSources.cmake:[0-9]+ \(add_library\):
+  The SOURCES of "A" use a generator expression that depends on the SOURCES
+  themselves.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
 CMake Generate step failed\.  Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt
new file mode 100644
index 0000000..8cdcfd9
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt
@@ -0,0 +1,2 @@
+^(|Warning #670: precompiled header file [^
+]* was not generated in this directory)$
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
new file mode 100644
index 0000000..e306d8e
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.15)
+project(PchReuseFromPrefixed C)
+
+if(CMAKE_C_COMPILE_OPTIONS_USE_PCH)
+  add_definitions(-DHAVE_PCH_SUPPORT)
+endif()
+
+add_library(empty empty.c)
+target_precompile_headers(empty PRIVATE
+  <stdio.h>
+  <string.h>
+)
+target_include_directories(empty PUBLIC include)
+
+add_library(foo foo.c)
+target_include_directories(foo PUBLIC include)
+target_precompile_headers(foo REUSE_FROM empty)
+
+# Visual Studio 2017 and greater
+if (NOT (CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_LESS_EQUAL 19.10))
+  set_target_properties(foo PROPERTIES PREFIX "lib" IMPORT_PREFIX "lib")
+endif()
+
+add_executable(foobar foobar.c)
+target_link_libraries(foobar foo )
+set_target_properties(foobar PROPERTIES PRECOMPILE_HEADERS_REUSE_FROM empty)
+
+enable_testing()
+add_test(NAME foobar COMMAND foobar)
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index ec13663..8d2f4f9 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -17,5 +17,6 @@
 run_cmake(PchPrologueEpilogue)
 run_test(SkipPrecompileHeaders)
 run_test(PchReuseFrom)
+run_test(PchReuseFromPrefixed)
 run_test(PchReuseFromSubdir)
 run_cmake(PchMultilanguage)
diff --git a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
index 8e484d0..24daa64 100644
--- a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
+++ b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
@@ -21,3 +21,4 @@
 endfunction()
 
 run_test(unitybuild_runtest)
+run_test(unitybuild_object_library)
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake b/Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake
new file mode 100644
index 0000000..b400517
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake
@@ -0,0 +1,13 @@
+project(unitybuild_object_library C)
+
+set(CMAKE_UNITY_BUILD ON) # This tests that the variable works in addition to the property
+
+add_library(lib OBJECT func.c)
+
+add_library(other-lib STATIC func.c)
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE lib)
+
+enable_testing()
+add_test(NAME main COMMAND main)