Browse Source

Swift: Add abstraction for compilation mode

Add a `CMAKE_Swift_COMPILATION_MODE` variable and corresponding
`Swift_COMPILATION_MODE` target property to control the compilation
mode.  Select among `wholemodule`, `singlefile`, and `incremental`.

Add policy CMP0157 to remove the default `-wmo` flags in favor of the
abstract setting.

Issue: #25366
Evan Wilde 2 years ago
parent
commit
c1d787e473

+ 1 - 0
Auxiliary/vim/syntax/cmake.vim

@@ -374,6 +374,7 @@ syn keyword cmakeProperty contained
             \ Swift_LANGUAGE_VERSION
             \ Swift_MODULE_DIRECTORY
             \ Swift_MODULE_NAME
+            \ Swift_COMPILATION_MODE
             \ TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
             \ TARGET_MESSAGES
             \ TARGET_SUPPORTS_SHARED_LIBS

+ 1 - 0
Help/manual/cmake-policies.7.rst

@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.29
 .. toctree::
    :maxdepth: 1
 
+   CMP0157: Swift compilation mode is selected by an abstraction. </policy/CMP0157>
    CMP0156: De-duplicate libraries on link lines based on linker capabilities. </policy/CMP0156>
 
 Policies Introduced by CMake 3.28

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -392,6 +392,7 @@ Properties on Targets
    /prop_tgt/STATIC_LIBRARY_FLAGS_CONFIG
    /prop_tgt/STATIC_LIBRARY_OPTIONS
    /prop_tgt/SUFFIX
+   /prop_tgt/Swift_COMPILATION_MODE
    /prop_tgt/Swift_DEPENDENCIES_FILE
    /prop_tgt/Swift_LANGUAGE_VERSION
    /prop_tgt/Swift_MODULE_DIRECTORY

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -115,6 +115,7 @@ Variables that Provide Information
    /variable/CMAKE_SOURCE_DIR
    /variable/CMAKE_STATIC_LIBRARY_PREFIX
    /variable/CMAKE_STATIC_LIBRARY_SUFFIX
+   /variable/CMAKE_Swift_COMPILATION_MODE
    /variable/CMAKE_Swift_MODULE_DIRECTORY
    /variable/CMAKE_Swift_NUM_THREADS
    /variable/CMAKE_TOOLCHAIN_FILE

+ 48 - 0
Help/policy/CMP0157.rst

@@ -0,0 +1,48 @@
+CMP0157
+-------
+
+.. versionadded:: 3.29
+
+Swift compilation mode is selected by an abstraction.
+
+The Swift compiler can compile modules in different modes. The desired build
+mode depends whether the developer is iterating and wants to incrementally make
+changes, or if they are building a release for distribution and want more
+optimizations applied to the resulting binary.
+
+CMake versions 3.26 through 3.28 build Swift binaries with whole-module
+optimizations enabled when configured in a non-debug build type.
+For CMake versions earlier than 3.26, the developer needs to specify
+the necessary flag manually for the :ref:`Ninja Generators`, and cannot
+not specify whole-module optimizations to the :generator:`Xcode` generator.
+
+CMake versions 3.29 and above prefer to set the compilation mode using
+the :prop_tgt:`Swift_COMPILATION_MODE` target property, which can be
+initialized by the :variable:`CMAKE_Swift_COMPILATION_MODE` variable.
+
+This policy provides compatibility for projects that have not been updated.
+The policy setting takes effect as of the first :command:`project` or
+:command:`enable_language` command that enables the ``Swift`` language.
+
+.. note::
+
+  Once the policy has taken effect at the top of a project, that choice
+  must be used throughout the tree. In projects that have nested projects
+  in subdirectories, be sure to convert everything together.
+
+The ``OLD`` behavior for this policy builds all Swift targets in
+``wholemodule`` mode for non-debug configurations.  :ref:`Ninja Generators`
+prepend the ``-wmo`` flag to the default set of Swift flags.
+The :generator:`Xcode` generator sets the ``SWIFT_COMPILATION_MODE``
+attribute to ``wholemodule`` in the generated Xcode project file.
+
+The ``NEW`` behavior for this policy is to apply the compilation mode specified
+in the :prop_tgt:`Swift_COMPILATION_MODE` target property, initialized as each
+target is created by the :variable:`CMAKE_Swift_COMPILATION_MODE` variable.
+
+This policy was introduced in CMake version 3.29. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn when this policy
+is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt

+ 19 - 0
Help/prop_tgt/Swift_COMPILATION_MODE-VALUES.txt

@@ -0,0 +1,19 @@
+``incremental``
+  Compiles each Swift source in the module separately, resulting in better
+  parallelism in the build. The compiler emits additional information into
+  the build directory improving rebuild performance when small changes are made
+  to the source between rebuilds. This is the best option to use while
+  iterating on changes in a project.
+
+``wholemodule``
+  Whole-module optimizations are slowest to compile, but results in the most
+  optimized library. The entire context is loaded into once instance of the
+  compiler, so there is no parallelism across source files in the module.
+
+``singlefile``
+  Compiles each source in a Swift modules separately, resulting in better
+  parallelism. Unlike the ``incremental`` build mode, no additional information
+  is emitted by the compiler during the build, so rebuilding after making small
+  changes to the source file will not run faster. This option should be used
+  sparingly, preferring ``incremental`` builds, unless working around a compiler
+  bug.

+ 33 - 0
Help/prop_tgt/Swift_COMPILATION_MODE.rst

@@ -0,0 +1,33 @@
+Swift_COMPILATION_MODE
+----------------------
+
+.. versionadded:: 3.29
+
+Specify how Swift compiles a target.
+
+The allowed values are:
+
+.. include:: Swift_COMPILATION_MODE-VALUES.txt
+
+Use :manual:`generator expressions <cmake-generator-expressions(7)>` to support
+per-configuration specification. For example, the code:
+
+.. code-block:: cmake
+
+  add_library(foo foo.swift)
+  set_property(TARGET foo PROPERTY
+    Swift_COMPILATION_MODE "$<IF:$<CONFIG:Release>,wholemodule,incremental>")
+
+sets the Swift compilation mode to wholemodule mode in the release configuration
+and sets the property to incremental mode in other configurations.
+
+The property is initialized from the value of the
+:variable:`CMAKE_Swift_COMPILATION_MODE` variable, if it is set. If the property
+is not set or is empty, then CMake uses the default value ``incremental`` to
+specify the swift compilation mode.
+
+.. note::
+
+   This property only has effect when policy :policy:`CMP0157` is set to ``NEW``
+   prior to the first :command:`project` or :command:`enable_language` command
+   that enables the Swift language.

+ 32 - 0
Help/variable/CMAKE_Swift_COMPILATION_MODE.rst

@@ -0,0 +1,32 @@
+CMAKE_Swift_COMPILATION_MODE
+----------------------------
+
+.. versionadded:: 3.29
+
+Specify how Swift compiles a target. This variable is used to initialize the
+:prop_tgt:`Swift_COMPILATION_MODE` property on targets as they are created.
+
+The allowed values are:
+
+.. include:: ../prop_tgt/Swift_COMPILATION_MODE-VALUES.txt
+
+Use :manual:`generator expressions <cmake-generator-expressions(7)>` to support
+per-configuration specification. For example, the code:
+
+.. code-block:: cmake
+
+   set(CMAKE_Swift_COMPILATION_MODE
+     "$<IF:$<CONFIG:Release>,wholemodule,incremental>")
+
+sets the default Swift compilation mode to wholemodule mode when building a
+release configuration and to incremental mode in other configurations.
+
+If this variable is not set then the :prop_tgt:`Swift_COMPILATION_MODE` target
+property will not be set automatically. If that property is unset then CMake
+uses the default value ``incremental`` to build the Swift source files.
+
+.. note::
+
+   This property only has effect when policy :policy:`CMP0157` is set to ``NEW``
+   prior to the first :command:`project` or :command:`enable_language` command
+   that enables the Swift language.

+ 29 - 17
Modules/CMakeSwiftInformation.cmake

@@ -68,30 +68,42 @@ set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -libc MD)
 set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -libc MTd)
 set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -libc MDd)
 
+set(CMAKE_Swift_FLAGS_DEBUG_INIT "-Onone -g")
+set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O")
+set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g")
+set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize")
+
 if(CMAKE_GENERATOR STREQUAL "Xcode")
+  string(APPEND CMAKE_Swift_FLAGS_DEBUG_INIT " ${CMAKE_Swift_FLAGS_DEBUG_LINKER_FLAGS}")
+  string(APPEND CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT " ${CMAKE_Swift_FLAGS_RELWITHDEBINFO_LINKER_FLAGS}")
+endif()
+
+# Warns if unset and uses old policy.
+# Old policy flag-smashes the wmo and incremental flags onto the compiler flags.
+# New policy respects the Swift_COMPILATION_MODE target property to add
+# incremental and wholemodule optimization flags as appropriate.
+cmake_policy(GET CMP0157 __SWIFT_COMP_MODE_CMP0157)
+if(__SWIFT_COMP_MODE_CMP0157 STREQUAL "NEW")
+  set(CMAKE_Swift_COMPILATION_MODE_DEFAULT "incremental")
+else()
   # Xcode has a separate Xcode project option (SWIFT_COMPILATION_MODE) used to set
   # whether compiling with whole-module optimizations or incrementally. Setting
   # these options here will have no effect when compiling with the built-in driver,
   # and will explode violently, leaving build products in the source directory, when
-  # using the old swift driver.
-  set(CMAKE_Swift_FLAGS_DEBUG_INIT "-Onone -g ${CMAKE_Swift_FLAGS_DEBUG_LINKER_FLAGS}")
-  set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O")
-  set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g ${CMAKE_Swift_FLAGS_RELWITHDEBINFO_LINKER_FLAGS}")
-  set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize")
-else()
-  set(CMAKE_Swift_FLAGS_DEBUG_INIT "-Onone -g -incremental")
-  set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O")
-  set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g")
-  set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize")
-
-  # Enable Whole Module Optimization by default unless the old
-  # C++ driver is being used, which behaves differently under WMO.
-  if(NOT CMAKE_Swift_COMPILER_USE_OLD_DRIVER)
-    string(APPEND CMAKE_Swift_FLAGS_RELEASE_INIT " -wmo")
-    string(APPEND CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT " -wmo")
-    string(APPEND CMAKE_Swift_FLAGS_MINSIZEREL_INIT " -wmo")
+  # using the old swift driver. Don't append `-incremental` or `-wmo` to the
+  # flags in the Xcode generator.
+  if(NOT CMAKE_GENERATOR STREQUAL "Xcode")
+    # Enable Whole Module Optimization by default unless the old
+    # C++ driver is being used, which behaves differently under WMO.
+    if(NOT CMAKE_Swift_COMPILER_USE_OLD_DRIVER)
+      string(APPEND CMAKE_Swift_FLAGS_RELEASE_INIT " -wmo")
+      string(APPEND CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT " -wmo")
+      string(APPEND CMAKE_Swift_FLAGS_MINSIZEREL_INIT " -wmo")
+    endif()
+    string(APPEND CMAKE_Swift_FLAGS_DEBUG_INIT " -incremental")
   endif()
 endif()
+unset(__SWIFT_COMP_MODE_CMP0157)
 
 if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
   if(NOT DEFINED CMAKE_Swift_LINK_WHAT_YOU_USE_FLAG)

+ 8 - 0
Source/cmCoreTryCompile.cxx

@@ -904,6 +904,14 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
               ? "NEW"
               : "OLD");
 
+    /* Set the appropriate policy information for Swift compilation mode */
+    fprintf(
+      fout, "cmake_policy(SET CMP0157 %s)\n",
+      this->Makefile->GetDefinition("CMAKE_Swift_COMPILATION_MODE_DEFAULT")
+          .IsEmpty()
+        ? "OLD"
+        : "NEW");
+
     // Workaround for -Wl,-headerpad_max_install_names issue until we can avoid
     // adding that flag in the platform and compiler language files
     fprintf(fout,

+ 33 - 3
Source/cmGlobalXCodeGenerator.cxx

@@ -2479,6 +2479,25 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
       buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS",
                                   swiftDefs.CreateList());
     }
+
+    if (cm::optional<cmSwiftCompileMode> swiftCompileMode =
+          this->CurrentLocalGenerator->GetSwiftCompileMode(gtgt, configName)) {
+      switch (*swiftCompileMode) {
+        case cmSwiftCompileMode::Wholemodule:
+          buildSettings->AddAttribute("SWIFT_COMPILATION_MODE",
+                                      this->CreateString("wholemodule"));
+          break;
+        case cmSwiftCompileMode::Incremental:
+        case cmSwiftCompileMode::Singlefile:
+          break;
+        case cmSwiftCompileMode::Unknown:
+          this->CurrentLocalGenerator->IssueMessage(
+            MessageType::AUTHOR_WARNING,
+            cmStrCat("Unknown Swift_COMPILATION_MODE on target '",
+                     gtgt->GetName(), "'"));
+          break;
+      }
+    }
   }
 
   std::string extraLinkOptionsVar;
@@ -4610,6 +4629,10 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
     buildSettings->AddAttribute("CODE_SIGNING_ALLOWED",
                                 this->CreateString("NO"));
   }
+
+  // This code supports the OLD behavior of CMP0157. We should be able to
+  // remove computing the debug configuration set once the old behavior is
+  // removed.
   auto debugConfigs = this->GetCMakeInstance()->GetDebugConfigs();
   std::set<std::string> debugConfigSet(debugConfigs.begin(),
                                        debugConfigs.end());
@@ -4619,9 +4642,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
 
     cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings);
 
-    if (debugConfigSet.count(cmSystemTools::UpperCase(config.first)) == 0) {
-      buildSettingsForCfg->AddAttribute("SWIFT_COMPILATION_MODE",
-                                        this->CreateString("wholemodule"));
+    // Supports the OLD behavior of CMP0157. CMP0157 OLD behavior globally set
+    // wholemodule compilation for all non-debug configurations, for all
+    // targets.
+    if (this->CurrentMakefile
+          ->GetDefinition("CMAKE_Swift_COMPILATION_MODE_DEFAULT")
+          .IsEmpty()) {
+      if (debugConfigSet.count(cmSystemTools::UpperCase(config.first)) == 0) {
+        buildSettingsForCfg->AddAttribute("SWIFT_COMPILATION_MODE",
+                                          this->CreateString("wholemodule"));
+      }
     }
 
     // Put this last so it can override existing settings

+ 61 - 0
Source/cmLocalGenerator.cxx

@@ -1651,6 +1651,39 @@ std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags(
   if (lang == "Fortran") {
     this->AppendFlags(compileFlags,
                       this->GetTargetFortranFlags(target, config));
+  } else if (lang == "Swift") {
+    // Only set the compile mode if CMP0157 is set
+    if (cm::optional<cmSwiftCompileMode> swiftCompileMode =
+          this->GetSwiftCompileMode(target, config)) {
+      std::string swiftCompileModeFlag;
+      switch (*swiftCompileMode) {
+        case cmSwiftCompileMode::Incremental: {
+          swiftCompileModeFlag = "-incremental";
+          if (cmValue flag =
+                mf->GetDefinition("CMAKE_Swift_COMPILE_OPTIONS_INCREMENTAL")) {
+            swiftCompileModeFlag = *flag;
+          }
+          break;
+        }
+        case cmSwiftCompileMode::Wholemodule: {
+          swiftCompileModeFlag = "-wmo";
+          if (cmValue flag =
+                mf->GetDefinition("CMAKE_Swift_COMPILE_OPTIONS_WMO")) {
+            swiftCompileModeFlag = *flag;
+          }
+          break;
+        }
+        case cmSwiftCompileMode::Singlefile:
+          break;
+        case cmSwiftCompileMode::Unknown: {
+          this->IssueMessage(
+            MessageType::AUTHOR_WARNING,
+            cmStrCat("Unknown Swift_COMPILATION_MODE on target '",
+                     target->GetName(), "'"));
+        }
+      }
+      this->AppendFlags(compileFlags, swiftCompileModeFlag);
+    }
   }
 
   this->AddCMP0018Flags(compileFlags, target, lang, config);
@@ -2955,6 +2988,34 @@ cm::optional<std::string> cmLocalGenerator::GetMSVCDebugFormatName(
   return msvcDebugInformationFormat;
 }
 
+cm::optional<cmSwiftCompileMode> cmLocalGenerator::GetSwiftCompileMode(
+  cmGeneratorTarget const* target, std::string const& config)
+{
+  cmMakefile const* mf = this->GetMakefile();
+  cmValue const swiftCompileModeDefault =
+    mf->GetDefinition("CMAKE_Swift_COMPILATION_MODE_DEFAULT");
+  if (!cmNonempty(swiftCompileModeDefault)) {
+    return {};
+  }
+  cmValue swiftCompileMode = target->GetProperty("Swift_COMPILATION_MODE");
+  if (!swiftCompileMode) {
+    swiftCompileMode = swiftCompileModeDefault;
+  }
+
+  std::string const expandedCompileMode =
+    cmGeneratorExpression::Evaluate(*swiftCompileMode, this, config, target);
+  if (expandedCompileMode == "wholemodule") {
+    return cmSwiftCompileMode::Wholemodule;
+  }
+  if (expandedCompileMode == "singlefile") {
+    return cmSwiftCompileMode::Singlefile;
+  }
+  if (expandedCompileMode == "incremental") {
+    return cmSwiftCompileMode::Incremental;
+  }
+  return cmSwiftCompileMode::Unknown;
+}
+
 namespace {
 
 inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf,

+ 13 - 0
Source/cmLocalGenerator.h

@@ -67,6 +67,15 @@ enum class cmBuildStep
   Link
 };
 
+/** What compilation mode the swift files are in */
+enum class cmSwiftCompileMode
+{
+  Wholemodule,
+  Incremental,
+  Singlefile,
+  Unknown,
+};
+
 /** Target and source file which have a specific output.  */
 struct cmSourcesWithOutput
 {
@@ -549,6 +558,10 @@ public:
                               const std::string& prop,
                               const std::string& config);
 
+  // Return Swift_COMPILATION_MODE value if CMP0157 is NEW.
+  cm::optional<cmSwiftCompileMode> GetSwiftCompileMode(
+    cmGeneratorTarget const* target, std::string const& config);
+
 protected:
   // The default implementation converts to a Windows shortpath to
   // help older toolchains handle spaces and such.  A generator may

+ 6 - 2
Source/cmPolicies.h

@@ -477,7 +477,10 @@ class cmMakefile;
   SELECT(                                                                     \
     POLICY, CMP0156,                                                          \
     "De-duplicate libraries on link lines based on linker capabilities.", 3,  \
-    29, 0, cmPolicies::WARN)
+    29, 0, cmPolicies::WARN)                                                  \
+  SELECT(POLICY, CMP0157,                                                     \
+         "Swift compilation mode selected by an abstraction.", 3, 29, 0,      \
+         cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -518,7 +521,8 @@ class cmMakefile;
   F(CMP0142)                                                                  \
   F(CMP0154)                                                                  \
   F(CMP0155)                                                                  \
-  F(CMP0156)
+  F(CMP0156)                                                                  \
+  F(CMP0157)
 
 #define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F)                                  \
   F(CMP0116)                                                                  \

+ 1 - 0
Source/cmTarget.cxx

@@ -438,6 +438,7 @@ TargetProperty const StaticTargetProperties[] = {
   // ---- Swift
   { "Swift_LANGUAGE_VERSION"_s, IC::CanCompileSources },
   { "Swift_MODULE_DIRECTORY"_s, IC::CanCompileSources },
+  { "Swift_COMPILATION_MODE"_s, IC::CanCompileSources },
   // ---- moc
   { "AUTOMOC"_s, IC::CanCompileSources },
   { "AUTOMOC_COMPILER_PREDEFINES"_s, IC::CanCompileSources },

+ 3 - 0
Tests/RunCMake/Swift/CMP0157-NEW-stderr.txt

@@ -0,0 +1,3 @@
+CMake Warning \(dev\) in CMakeLists.txt:
+  Unknown Swift_COMPILATION_MODE on target 'greetings_who_knows'
+This warning is for project developers.  Use -Wno-dev to suppress it.

+ 4 - 0
Tests/RunCMake/Swift/CMP0157-NEW.cmake

@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.28)
+
+cmake_policy(SET CMP0157 NEW)
+include(CMP0157-common.cmake)

+ 4 - 0
Tests/RunCMake/Swift/CMP0157-OLD.cmake

@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.28)
+
+cmake_policy(SET CMP0157 OLD)
+include(CMP0157-common.cmake)

+ 3 - 0
Tests/RunCMake/Swift/CMP0157-WARN.cmake

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.28)
+
+include(CMP0157-common.cmake)

+ 19 - 0
Tests/RunCMake/Swift/CMP0157-common.cmake

@@ -0,0 +1,19 @@
+enable_language(Swift)
+
+add_executable(greetings_default hello.swift)
+
+add_executable(greetings_wmo hello.swift)
+set_target_properties(greetings_wmo PROPERTIES
+  Swift_COMPILATION_MODE "wholemodule")
+
+add_executable(greetings_incremental hello.swift)
+set_target_properties(greetings_incremental PROPERTIES
+  Swift_COMPILATION_MODE "incremental")
+
+add_executable(greetings_singlefile hello.swift)
+set_target_properties(greetings_singlefile PROPERTIES
+  Swift_COMPILATION_MODE "singlefile")
+
+add_executable(greetings_who_knows hello.swift)
+set_target_properties(greetings_who_knows PROPERTIES
+  Swift_COMPILATION_MODE "not-a-real-mode")

+ 12 - 0
Tests/RunCMake/Swift/RunCMakeTest.cmake

@@ -3,6 +3,10 @@ include(RunCMake)
 if(RunCMake_GENERATOR STREQUAL Xcode)
   if(XCODE_VERSION VERSION_LESS 6.1)
     run_cmake(XcodeTooOld)
+  elseif(CMake_TEST_Swift)
+    run_cmake(CMP0157-NEW)
+    run_cmake(CMP0157-OLD)
+    run_cmake(CMP0157-WARN)
   endif()
 elseif(RunCMake_GENERATOR STREQUAL Ninja)
   if(CMake_TEST_Swift)
@@ -45,11 +49,19 @@ elseif(RunCMake_GENERATOR STREQUAL Ninja)
       run_cmake_command(IncrementalSwift-second ${CMAKE_COMMAND} --build ${IncrementalSwift_TEST_BINARY_DIR} -- -d explain)
     endblock()
 
+    run_cmake(CMP0157-NEW)
+    run_cmake(CMP0157-OLD)
+    run_cmake(CMP0157-WARN)
+
   endif()
 elseif(RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
   if(CMake_TEST_Swift)
     set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release")
     run_cmake(SwiftSimple)
+
+    run_cmake(CMP0157-NEW)
+    run_cmake(CMP0157-OLD)
+    run_cmake(CMP0157-WARN)
     unset(RunCMake_TEST_OPTIONS)
   endif()
 else()

+ 1 - 0
Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt

@@ -40,6 +40,7 @@
    \* CMP0154
    \* CMP0155
    \* CMP0156
+   \* CMP0157
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)

+ 20 - 0
Tests/SwiftOnly/CMakeLists.txt

@@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.3)
 if(POLICY CMP0126)
   cmake_policy(SET CMP0126 NEW)
 endif()
+if(POLICY CMP0157)
+  cmake_policy(SET CMP0157 NEW)
+endif()
 
 # NOTE: Force the Release mode configuration as there are some issues with the
 # debug information handling on macOS on certain Xcode builds.
@@ -54,3 +57,20 @@ target_link_libraries(SwiftOnly PRIVATE SwiftIface)
 if(CMAKE_Swift_COMPILER_VERSION VERSION_GREATER_EQUAL 5.2)
   add_subdirectory("SwiftPlugin")
 endif()
+
+function(test_cmp0157_default mode)
+
+  cmake_policy(GET CMP0157 cmp0157_wmo)
+  if(cmp0157_wmo STREQUAL "NEW")
+    set(CMAKE_Swift_COMPILATION_MODE "${mode}")
+    add_executable(hi_${mode} main.swift)
+    get_target_property(${mode}_swift_comp_mode hi_${mode} "Swift_COMPILATION_MODE")
+    if(NOT ${mode}_swift_comp_mode STREQUAL ${mode})
+      message(SEND_ERROR "expected ${mode} -- found ${${mode}_swift_comp_mode}")
+    endif()
+  endif()
+endfunction()
+
+test_cmp0157_default("wholemodule")
+test_cmp0157_default("incremental")
+test_cmp0157_default("singlefile")