VS: Add policy to build custom commands concurrently

In commit 33c15ae2b9 (VS: Build custom commands concurrently when
possible, 2023-01-19, v3.26.0-rc1~56^2) we added `BuildInParallel` to
custom commands in `.vcxproj` files, but that had to be reverted by
commit abb1c12162 (VS: Revert "Build custom commands concurrently when
possible", 2023-03-07, v3.26.0-rc6~3^2) because some projects may have
custom commands that accidentally rely on serial execution in MSBuild.

Add a policy to use `BuildInParallel` for custom commands in projects
that have been updated to set the policy to `NEW`.

Fixes: #18405
This commit is contained in:
Brad King 2023-03-10 11:47:24 -05:00
parent 9db40bec4e
commit d6353e74b4
8 changed files with 92 additions and 4 deletions

View File

@ -57,6 +57,7 @@ Policies Introduced by CMake 3.27
.. toctree::
:maxdepth: 1
CMP0147: Visual Studio generators build custom commands in parallel. </policy/CMP0147>
CMP0146: The FindCUDA module is removed. </policy/CMP0146>
CMP0145: The Dart and FindDart modules are removed. </policy/CMP0145>
CMP0144: find_package uses upper-case PACKAGENAME_ROOT variables. </policy/CMP0144>

24
Help/policy/CMP0147.rst Normal file
View File

@ -0,0 +1,24 @@
CMP0147
-------
.. versionadded:: 3.27
:ref:`Visual Studio Generators` build custom commands in parallel.
Visual Studio 15.8 (2017) and newer support building custom commands in
parallel. CMake 3.27 and above prefer to enable this behavior by adding
a ``BuildInParallel`` setting to custom commands in ``.vcxproj`` files.
This policy provides compatibility for projects that have not been updated
to expect this, e.g., because their custom commands were accidentally
relying on serial execution by MSBuild.
The ``OLD`` behavior for this policy is to not add ``BuildInParallel``.
The ``NEW`` behavior for this policy is to add ``BuildInParallel`` for
VS 15.8 and newer.
This policy was introduced in CMake version 3.27. 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

View File

@ -0,0 +1,5 @@
vs-BuildInParallel
------------------
* :ref:`Visual Studio Generators`, for VS 15.8 (2017) and newer, now
build custom commands in parallel. See policy :policy:`CMP0147`.

View File

@ -441,7 +441,10 @@ class cmMakefile;
SELECT(POLICY, CMP0145, "The Dart and FindDart modules are removed.", 3, \
27, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0146, "The FindCUDA module is removed.", 3, 27, 0, \
cmPolicies::WARN)
cmPolicies::WARN) \
SELECT(POLICY, CMP0147, \
"Visual Studio generators build custom commands in parallel.", 3, \
27, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@ -481,7 +484,9 @@ class cmMakefile;
F(CMP0131) \
F(CMP0142)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) F(CMP0116)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
F(CMP0116) \
F(CMP0147)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies

View File

@ -1810,10 +1810,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
outputs.str(), comment, ccg);
} else {
// FIXME(#18405): Enable BuildInParallel::Yes via an option or policy.
BuildInParallel buildInParallel = BuildInParallel::No;
if (command.GetCMP0147Status() == cmPolicies::NEW &&
!command.GetUsesTerminal() &&
!(command.HasMainDependency() && source->GetIsGenerated())) {
buildInParallel = BuildInParallel::Yes;
}
this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
outputs.str(), comment, ccg, symbolic,
BuildInParallel::No);
buildInParallel);
}
}
}

View File

@ -0,0 +1,40 @@
set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
if(NOT EXISTS "${vcProjectFile}")
set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
return()
endif()
set(found_CustomBuild_cmp0147_new 0)
set(found_CustomBuild_cmp0147_old 0)
set(found_BuildInParallel_cmp0147_new 0)
set(found_BuildInParallel_cmp0147_old 0)
set(in_CustomBuild_cmp0147 "")
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES [[<CustomBuild Include=".*\\cmp0147-old\.txt\.rule">]])
set(found_CustomBuild_cmp0147_old 1)
set(in_CustomBuild_cmp0147 "old")
endif()
if(line MATCHES [[<CustomBuild Include=".*\\cmp0147-new\.txt\.rule">]])
set(found_CustomBuild_cmp0147_new 1)
set(in_CustomBuild_cmp0147 "new")
endif()
if(line MATCHES [[</CustomBuild>]])
set(in_CustomBuild_cmp0147 "")
endif()
if(line MATCHES [[<BuildInParallel .*>true</BuildInParallel>]] AND in_CustomBuild_cmp0147)
set(found_BuildInParallel_cmp0147_${in_CustomBuild_cmp0147} 1)
endif()
endforeach()
if(NOT found_CustomBuild_cmp0147_new)
string(APPEND RunCMake_TEST_FAILED "CustomBuild for cmp0147-new.txt.rule not found in\n ${vcProjectFile}\n")
endif()
if(NOT found_CustomBuild_cmp0147_old)
string(APPEND RunCMake_TEST_FAILED "CustomBuild for cmp0147-old.txt.rule not found in\n ${vcProjectFile}\n")
endif()
if(NOT found_BuildInParallel_cmp0147_new)
string(APPEND RunCMake_TEST_FAILED "BuildInParallel for cmp0147-new.txt.rule not found in\n ${vcProjectFile}\n")
endif()
if(found_BuildInParallel_cmp0147_old)
string(APPEND RunCMake_TEST_FAILED "BuildInParallel for cmp0147-old.txt.rule incorrectly found in\n ${vcProjectFile}\n")
endif()

View File

@ -0,0 +1,5 @@
cmake_policy(VERSION 3.26) # CMP0147 left unset
add_custom_command(OUTPUT "cmp0147-old.txt" COMMAND echo)
cmake_policy(SET CMP0147 NEW)
add_custom_command(OUTPUT "cmp0147-new.txt" COMMAND echo)
add_custom_target(foo DEPENDS "cmp0147-old.txt" "cmp0147-new.txt")

View File

@ -8,6 +8,9 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREA
endif()
run_cmake(CustomCommandGenex)
if(NOT RunCMake_GENERATOR MATCHES "^Visual Studio 1[1-5] ")
run_cmake(CustomCommandParallel)
endif()
run_cmake(VsCsharpSourceGroup)
run_cmake(VsCSharpCompilerOpts)
run_cmake(ExplicitCMakeLists)