summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml14
-rw-r--r--Help/command/foreach.rst5
-rw-r--r--Help/guide/ide-integration/index.rst6
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0124.rst20
-rw-r--r--Help/release/dev/foreach-variable-scope.rst5
-rw-r--r--Modules/CMakeCompilerIdDetection.cmake2
-rw-r--r--Modules/CMakeDetermineCompileFeatures.cmake6
-rw-r--r--Modules/FindBLAS.cmake23
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmForEachCommand.cxx37
-rw-r--r--Source/cmLocalNinjaGenerator.cxx17
-rw-r--r--Source/cmLocalNinjaGenerator.h5
-rw-r--r--Source/cmMakefile.cxx14
-rw-r--r--Source/cmMakefile.h1
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx30
-rw-r--r--Source/cmNinjaTargetGenerator.cxx25
-rw-r--r--Source/cmNinjaTargetGenerator.h3
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx4
-rw-r--r--Source/cmPolicies.h5
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx7
-rw-r--r--Source/kwsys/ProcessUNIX.c4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake7
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake2
-rw-r--r--Tests/RunCMake/ToolchainFile/LangVars.cmake7
-rw-r--r--Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in18
-rw-r--r--Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake1
-rw-r--r--Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake8
-rw-r--r--Tests/RunCMake/foreach/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake51
-rw-r--r--Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake53
34 files changed, 332 insertions, 59 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 465dc2c..18844d1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -363,6 +363,13 @@ test:intel2021.1.2-makefiles:
CMAKE_CI_BUILD_NAME: intel2021.1.2_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8
+test:intel2021.2.0-makefiles:
+ extends:
+ - .cmake_test_linux_intelclassic_makefiles
+ variables:
+ CMAKE_CI_BUILD_NAME: intel2021.2.0_makefiles
+ CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.2.0-el8
+
test:oneapi2021.1.1-makefiles:
extends:
- .cmake_test_linux_inteloneapi_makefiles
@@ -377,6 +384,13 @@ test:oneapi2021.1.2-makefiles:
CMAKE_CI_BUILD_NAME: oneapi2021.1.2_makefiles
CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8
+test:oneapi2021.2.0-makefiles:
+ extends:
+ - .cmake_test_linux_inteloneapi_makefiles
+ variables:
+ CMAKE_CI_BUILD_NAME: oneapi2021.2.0_makefiles
+ CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.2.0-el8
+
build:linux-x86_64-package:
extends:
- .linux_package
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index 8de6deb..d9f54ca 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -14,9 +14,12 @@ semicolon or whitespace.
All commands between ``foreach`` and the matching ``endforeach`` are recorded
without being invoked. Once the ``endforeach`` is evaluated, the recorded
list of commands is invoked once for each item in ``<items>``.
-At the beginning of each iteration the variable ``loop_var`` will be set
+At the beginning of each iteration the variable ``<loop_var>`` will be set
to the value of the current item.
+The scope of ``<loop_var>`` is restricted to the loop scope. See policy
+:policy:`CMP0124` for details.
+
The commands :command:`break` and :command:`continue` provide means to
escape from the normal control flow.
diff --git a/Help/guide/ide-integration/index.rst b/Help/guide/ide-integration/index.rst
index addf932..779883b 100644
--- a/Help/guide/ide-integration/index.rst
+++ b/Help/guide/ide-integration/index.rst
@@ -69,9 +69,9 @@ While reading, parsing, and evaluating the contents of ``CMakePresets.json`` is
straightforward, it is not trivial. In addition to the documentation, IDE
vendors may also wish to refer to the CMake source code and test cases for a
better understanding of how to implement the format.
-:download:`This file </manual/presets/schema.json>` provides a machine-readable
-JSON schema for the ``CMakePresets.json`` format that IDE vendors may find
-useful for validation and providing editing assistance.
+:download:`This file <../../manual/presets/schema.json>` provides a
+machine-readable JSON schema for the ``CMakePresets.json`` format that IDE
+vendors may find useful for validation and providing editing assistance.
Configuring
===========
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index b41ce59..08449a7 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.21
.. toctree::
:maxdepth: 1
+ CMP0124: foreach() loop variables are only available in the loop scope. </policy/CMP0124>
CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. </policy/CMP0123>
CMP0122: UseSWIG use standard library name conventions for csharp language. </policy/CMP0122>
CMP0121: The list command detects invalid indicies. </policy/CMP0121>
diff --git a/Help/policy/CMP0124.rst b/Help/policy/CMP0124.rst
new file mode 100644
index 0000000..88d03e3
--- /dev/null
+++ b/Help/policy/CMP0124.rst
@@ -0,0 +1,20 @@
+CMP0124
+-------
+
+.. versionadded:: 3.21
+
+The loop variables created by :command:`foreach` command have now their scope
+restricted to the loop scope.
+
+Starting with CMake 3.21, the :command:`foreach` command ensures that the loop
+variables have their scope restricted to the loop scope.
+
+The ``OLD`` behavior for this policy let the loop variables to exist, with an
+empty value, in the outer scope of loop scope.
+
+This policy was introduced in CMake version 3.21. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn when the policy
+is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/foreach-variable-scope.rst b/Help/release/dev/foreach-variable-scope.rst
new file mode 100644
index 0000000..29a57bb
--- /dev/null
+++ b/Help/release/dev/foreach-variable-scope.rst
@@ -0,0 +1,5 @@
+foreach-variable-scope
+----------------------
+
+* The :command:`foreach` command restrict loop variables to the loop scope.
+ See policy :policy:`CMP0124` for details.
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index c79d423..850fc14 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -18,7 +18,7 @@ function(compiler_id_detection outvar lang)
file(GLOB lang_files
"${CMAKE_ROOT}/Modules/Compiler/*-DetermineCompiler.cmake")
set(nonlang CXX)
- if (lang STREQUAL CXX)
+ if ("x${lang}" STREQUAL "xCXX")
set(nonlang C)
endif()
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
index f767847..ee7fedb 100644
--- a/Modules/CMakeDetermineCompileFeatures.cmake
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -4,7 +4,7 @@
function(cmake_determine_compile_features lang)
- if(lang STREQUAL C AND COMMAND cmake_record_c_compile_features)
+ if("x${lang}" STREQUAL "xC" AND COMMAND cmake_record_c_compile_features)
message(CHECK_START "Detecting ${lang} compile features")
set(CMAKE_C90_COMPILE_FEATURES)
@@ -54,7 +54,7 @@ function(cmake_determine_compile_features lang)
message(CHECK_PASS "done")
- elseif(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
+ elseif("x${lang}" STREQUAL "xCXX" AND COMMAND cmake_record_cxx_compile_features)
message(CHECK_START "Detecting ${lang} compile features")
set(CMAKE_CXX98_COMPILE_FEATURES)
@@ -110,7 +110,7 @@ function(cmake_determine_compile_features lang)
message(CHECK_PASS "done")
- elseif(lang STREQUAL CUDA AND COMMAND cmake_record_cuda_compile_features)
+ elseif("x${lang}" STREQUAL "xCUDA" AND COMMAND cmake_record_cuda_compile_features)
message(CHECK_START "Detecting ${lang} compile features")
set(CMAKE_CUDA03_COMPILE_FEATURES)
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index f3a8b74..024ff14 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -333,12 +333,21 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
if(CMAKE_Fortran_COMPILER_LOADED AND CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND NOT APPLE)
set(BLAS_mkl_INTFACE "gf")
set(BLAS_mkl_THREADING "gnu")
- set(BLAS_mkl_OMP "gomp")
else()
set(BLAS_mkl_INTFACE "intel")
set(BLAS_mkl_THREADING "intel")
- set(BLAS_mkl_OMP "iomp5")
endif()
+
+ foreach(lang IN ITEMS C CXX Fortran)
+ if(CMAKE_${lang}_COMPILER_LOADED)
+ find_package(OpenMP COMPONENTS ${lang})
+ if(${OpenMP_${lang}_FOUND})
+ set(BLAS_mkl_OMP ${OpenMP_${lang}_LIBRARIES})
+ break()
+ endif()
+ endif()
+ endforeach()
+
set(BLAS_mkl_LM "-lm")
set(BLAS_mkl_LDL "-ldl")
endif()
@@ -403,7 +412,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
# mkl >= 10.3
list(APPEND BLAS_SEARCH_LIBS
- "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
+ "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}")
endif()
if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
# old version
@@ -412,7 +421,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
# mkl >= 10.3
list(APPEND BLAS_SEARCH_LIBS
- "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
+ "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}")
endif()
if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
list(APPEND BLAS_SEARCH_LIBS
@@ -468,7 +477,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
# mkl >= 10.3
list(APPEND BLAS_SEARCH_LIBS
- "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
+ "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}")
endif()
if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
# old version
@@ -477,7 +486,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
# mkl >= 10.3
list(APPEND BLAS_SEARCH_LIBS
- "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
+ "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}")
endif()
if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
list(APPEND BLAS_SEARCH_LIBS
@@ -540,7 +549,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
${BLAS_mkl_SEARCH_SYMBOL}
""
"${SEARCH_LIBS}"
- "${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}"
+ "${BLAS_mkl_OMP};${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}"
"${BLAS_mkl_MKLROOT}"
"${BLAS_mkl_LIB_PATH_SUFFIXES}"
)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index e0b5dc2..d740db0 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 20)
-set(CMake_VERSION_PATCH 20210502)
+set(CMake_VERSION_PATCH 20210504)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index bcacb15..4845a6d 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -17,6 +17,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
@@ -25,7 +26,7 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
+#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -113,9 +114,11 @@ bool cmForEachFunctionBlocker::ReplayItems(
// At end of for each execute recorded commands
// store the old value
- std::string oldDef;
- if (cmProp d = mf.GetDefinition(this->Args.front())) {
- oldDef = *d;
+ cm::optional<std::string> oldDef;
+ if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) {
+ oldDef = mf.GetSafeDefinition(this->Args.front());
+ } else if (mf.IsNormalDefinitionSet(this->Args.front())) {
+ oldDef = *mf.GetDefinition(this->Args.front());
}
auto restore = false;
@@ -131,9 +134,14 @@ bool cmForEachFunctionBlocker::ReplayItems(
}
if (restore) {
- // restore the variable to its prior value
- mf.AddDefinition(this->Args.front(), oldDef);
+ if (oldDef) {
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args.front(), *oldDef);
+ } else {
+ mf.RemoveDefinition(this->Args.front());
+ }
}
+
return true;
}
@@ -185,10 +193,15 @@ bool cmForEachFunctionBlocker::ReplayZipLists(
assert("Sanity check" && iterationVars.size() == values.size());
// Store old values for iteration variables
- std::map<std::string, std::string> oldDefs;
+ std::map<std::string, cm::optional<std::string>> oldDefs;
for (auto i = 0u; i < values.size(); ++i) {
- if (cmProp d = mf.GetDefinition(iterationVars[i])) {
- oldDefs.emplace(iterationVars[i], *d);
+ const auto& varName = iterationVars[i];
+ if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) {
+ oldDefs.emplace(varName, mf.GetSafeDefinition(varName));
+ } else if (mf.IsNormalDefinitionSet(varName)) {
+ oldDefs.emplace(varName, *mf.GetDefinition(varName));
+ } else {
+ oldDefs.emplace(varName, cm::nullopt);
}
}
@@ -226,7 +239,11 @@ bool cmForEachFunctionBlocker::ReplayZipLists(
// Restore the variables to its prior value
if (restore) {
for (auto const& p : oldDefs) {
- mf.AddDefinition(p.first, p.second);
+ if (p.second) {
+ mf.AddDefinition(p.first, *p.second);
+ } else {
+ mf.RemoveDefinition(p.first);
+ }
}
}
return true;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index c2a6410..588f70b 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -410,7 +410,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps(
}
std::string cmLocalNinjaGenerator::WriteCommandScript(
- std::vector<std::string> const& cmdLines, std::string const& customStep,
+ std::vector<std::string> const& cmdLines, std::string const& outputConfig,
+ std::string const& commandConfig, std::string const& customStep,
cmGeneratorTarget const* target) const
{
std::string scriptPath;
@@ -419,9 +420,13 @@ std::string cmLocalNinjaGenerator::WriteCommandScript(
} else {
scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
}
+ scriptPath += this->GetGlobalNinjaGenerator()->ConfigDirectory(outputConfig);
cmSystemTools::MakeDirectory(scriptPath);
scriptPath += '/';
scriptPath += customStep;
+ if (this->GlobalGenerator->IsMultiConfig()) {
+ scriptPath += cmStrCat('-', commandConfig);
+ }
#ifdef _WIN32
scriptPath += ".bat";
#else
@@ -464,7 +469,8 @@ std::string cmLocalNinjaGenerator::WriteCommandScript(
}
std::string cmLocalNinjaGenerator::BuildCommandLine(
- std::vector<std::string> const& cmdLines, std::string const& customStep,
+ std::vector<std::string> const& cmdLines, std::string const& outputConfig,
+ std::string const& commandConfig, std::string const& customStep,
cmGeneratorTarget const* target) const
{
// If we have no commands but we need to build a command anyway, use noop.
@@ -483,8 +489,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
cmdLinesTotal += cmd.length() + 6;
}
if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
- std::string const scriptPath =
- this->WriteCommandScript(cmdLines, customStep, target);
+ std::string const scriptPath = this->WriteCommandScript(
+ cmdLines, outputConfig, commandConfig, customStep, target);
std::string cmd
#ifndef _WIN32
= "/bin/sh "
@@ -697,7 +703,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
gg->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines, customStep),
+ this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig,
+ customStep),
this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig,
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 8b6824f..a73fa27 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -61,7 +61,8 @@ public:
}
std::string BuildCommandLine(
- std::vector<std::string> const& cmdLines,
+ std::vector<std::string> const& cmdLines, std::string const& outputConfig,
+ std::string const& commandConfig,
std::string const& customStep = std::string(),
cmGeneratorTarget const* target = nullptr) const;
@@ -119,6 +120,8 @@ private:
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
+ std::string const& outputConfig,
+ std::string const& commandConfig,
std::string const& customStep,
cmGeneratorTarget const* target) const;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 40a67a3..dba8560 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2507,6 +2507,20 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const
return def != nullptr;
}
+bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const
+{
+ cmProp def = this->StateSnapshot.GetDefinition(name);
+#ifndef CMAKE_BOOTSTRAP
+ if (cmVariableWatch* vv = this->GetVariableWatch()) {
+ if (!def) {
+ vv->VariableAccessed(
+ name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this);
+ }
+ }
+#endif
+ return def != nullptr;
+}
+
cmProp cmMakefile::GetDefinition(const std::string& name) const
{
cmProp def = this->StateSnapshot.GetDefinition(name);
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 71d765c..3c07808 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -486,6 +486,7 @@ public:
const std::string& GetSafeDefinition(const std::string&) const;
const std::string& GetRequiredDefinition(const std::string& name) const;
bool IsDefinitionSet(const std::string&) const;
+ bool IsNormalDefinitionSet(const std::string&) const;
bool GetDefExpandList(const std::string& name, std::vector<std::string>& out,
bool emptyArgs = false) const;
/**
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 1d511f2..1b514b8 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -287,7 +287,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule(
// If there is no ranlib the command will be ":". Skip it.
cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands());
- rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
+ rule.Command =
+ this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config);
// Write the linker rule with response file if needed.
rule.Comment =
@@ -310,7 +311,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
cmNinjaRule rule(this->LanguageLinkerCudaDeviceRule(config));
rule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"),
- " -arch=$ARCH $REGISTER -o=$out $in") });
+ " -arch=$ARCH $REGISTER -o=$out $in") },
+ config, config);
rule.Comment = "Rule for CUDA device linking.";
rule.Description = "Linking CUDA $out";
this->GetGlobalGenerator()->AddRule(rule);
@@ -336,7 +338,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
compileCmd, vars);
rule.Name = this->LanguageLinkerCudaDeviceCompileRule(config);
- rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd });
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd },
+ config, config);
rule.Comment = "Rule for compiling CUDA device stubs.";
rule.Description = "Compiling CUDA device stub $out";
this->GetGlobalGenerator()->AddRule(rule);
@@ -345,7 +348,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
rule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"),
" -64 -cmdline=--compile-only -compress-all -link "
- "--embedded-fatbin=$out $PROFILES") });
+ "--embedded-fatbin=$out $PROFILES") },
+ config, config);
rule.Comment = "Rule for CUDA fatbinaries.";
rule.Description = "Creating fatbinary $out";
this->GetGlobalGenerator()->AddRule(rule);
@@ -475,7 +479,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
linkCmds.emplace_back("$POST_BUILD");
- rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
+ rule.Command =
+ this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config);
// Write the linker rule with response file if needed.
rule.Comment =
@@ -500,7 +505,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
std::vector<std::string> cmd;
cmd.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out");
cmd.emplace_back("$POST_BUILD");
- rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd);
+ rule.Command =
+ this->GetLocalGenerator()->BuildCommandLine(cmd, config, config);
}
rule.Description = "Creating executable symlink $out";
rule.Comment = "Rule for creating executable symlink.";
@@ -512,7 +518,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
cmd.push_back(cmakeCommand +
" -E cmake_symlink_library $in $SONAME $out");
cmd.emplace_back("$POST_BUILD");
- rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd);
+ rule.Command =
+ this->GetLocalGenerator()->BuildCommandLine(cmd, config, config);
}
rule.Description = "Creating library symlink $out";
rule.Comment = "Rule for creating library symlink.";
@@ -1312,10 +1319,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
preLinkCmdLines.push_back("cd " + homeOutDir);
}
- vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
- this->GeneratorTarget);
- std::string postBuildCmdLine = localGen.BuildCommandLine(
- postBuildCmdLines, "post-build", this->GeneratorTarget);
+ vars["PRE_LINK"] = localGen.BuildCommandLine(
+ preLinkCmdLines, config, fileConfig, "pre-link", this->GeneratorTarget);
+ std::string postBuildCmdLine =
+ localGen.BuildCommandLine(postBuildCmdLines, config, fileConfig,
+ "post-build", this->GeneratorTarget);
cmNinjaVars symlinkVars;
bool const symlinkNeeded =
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 2e0ffdb..f7777fc 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -539,7 +539,8 @@ cmNinjaRule GetScanRule(
cmRulePlaceholderExpander::RuleVariables const& vars,
const std::string& responseFlag, const std::string& flags,
cmRulePlaceholderExpander* const rulePlaceholderExpander,
- cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds)
+ cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds,
+ const std::string& outputConfig)
{
cmNinjaRule rule(ruleName);
// Scanning always uses a depfile for preprocessor dependencies.
@@ -580,7 +581,8 @@ cmNinjaRule GetScanRule(
for (std::string& scanCmd : scanCmds) {
rulePlaceholderExpander->ExpandRuleVariables(generator, scanCmd, scanVars);
}
- rule.Command = generator->BuildCommandLine(scanCmds);
+ rule.Command =
+ generator->BuildCommandLine(scanCmds, outputConfig, outputConfig);
return rule;
}
@@ -672,7 +674,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
auto scanRule = GetScanRule(
scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(),
- this->GetLocalGenerator(), std::move(scanCommands));
+ this->GetLocalGenerator(), std::move(scanCommands), config);
scanRule.Comment =
cmStrCat("Rule for generating ", lang, " dependencies.");
@@ -702,7 +704,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
auto scanRule = GetScanRule(
scanRuleName, vars, "", flags, rulePlaceholderExpander.get(),
- this->GetLocalGenerator(), std::move(scanCommands));
+ this->GetLocalGenerator(), std::move(scanCommands), config);
// Write the rule for generating dependencies for the given language.
scanRule.Comment = cmStrCat("Rule for generating ", lang,
@@ -734,7 +736,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
ddModmapArg, " --dd=$out @", rule.RspFile);
ddCmds.emplace_back(std::move(ccmd));
}
- rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds);
+ rule.Command =
+ this->GetLocalGenerator()->BuildCommandLine(ddCmds, config, config);
}
rule.Comment =
cmStrCat("Rule to generate ninja dyndep files for ", lang, '.');
@@ -930,7 +933,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
vars);
}
- rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+ rule.Command =
+ this->GetLocalGenerator()->BuildCommandLine(compileCmds, config, config);
// Write the rule for compiling file of the given language.
rule.Comment = cmStrCat("Rule for compiling ", lang, " files.");
@@ -1248,7 +1252,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->ExportObjectCompileCommand(
language, sourceFileName, objectDir, objectFileName, objectFileDir,
- vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]);
+ vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
objBuild.Outputs.push_back(objectFileName);
if (firstForConfig) {
@@ -1619,7 +1623,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName,
std::string const& objectFileDir, std::string const& flags,
- std::string const& defines, std::string const& includes)
+ std::string const& defines, std::string const& includes,
+ std::string const& outputConfig)
{
if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) {
return;
@@ -1681,8 +1686,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
compileObjectVars);
}
- std::string cmdLine =
- this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+ std::string cmdLine = this->GetLocalGenerator()->BuildCommandLine(
+ compileCmds, outputConfig, outputConfig);
this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName);
}
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 79dc622..3a28cef 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -162,7 +162,8 @@ protected:
std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName,
std::string const& objectFileDir, std::string const& flags,
- std::string const& defines, std::string const& includes);
+ std::string const& defines, std::string const& includes,
+ std::string const& outputConfig);
void AdditionalCleanFiles(const std::string& config);
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 92c5b52..7a04c47 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -139,8 +139,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
}
} else {
- std::string command =
- lg->BuildCommandLine(commands, "utility", this->GeneratorTarget);
+ std::string command = lg->BuildCommandLine(
+ commands, config, fileConfig, "utility", this->GeneratorTarget);
std::string desc;
cmProp echoStr = genTarget->GetProperty("EchoString");
if (echoStr) {
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 0a5bb4b..0ff12d5 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -369,7 +369,10 @@ class cmMakefile;
21, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0123, \
"ARMClang cpu/arch compile and link flags must be set explicitly.", \
- 3, 21, 0, cmPolicies::WARN)
+ 3, 21, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0124, \
+ "foreach() loop variables are only available in the loop scope.", 3, \
+ 21, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 0255d60..cc1586d 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -5037,7 +5037,9 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
{
// For out of source files, we first check if a matching source group
// for this file exists, otherwise we check if the path relative to current
- // source- or binary-dir is used within the link and return that
+ // source- or binary-dir is used within the link and return that.
+ // In case of .cs files we can't do that automatically for files in the
+ // binary directory, because this leads to compilation errors.
std::string link;
std::string sourceGroupedFile;
std::string const& fullFileName = source->GetFullPath();
@@ -5059,7 +5061,8 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
link = sourceGroupedFile;
} else if (cmHasPrefix(fullFileName, srcDir)) {
link = fullFileName.substr(srcDir.length() + 1);
- } else if (cmHasPrefix(fullFileName, binDir)) {
+ } else if (!cmHasSuffix(fullFileName, ".cs") &&
+ cmHasPrefix(fullFileName, binDir)) {
link = fullFileName.substr(binDir.length() + 1);
} else if (cmProp l = source->GetProperty("VS_CSHARP_Link")) {
link = *l;
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index e1e7721..5ae846a 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -122,6 +122,10 @@ static inline void kwsysProcess_usleep(unsigned int msec)
/* The maximum amount to read from a pipe at a time. */
#define KWSYSPE_PIPE_BUFFER_SIZE 1024
+#if defined(__NVCOMPILER)
+# pragma diag_suppress 550 /* variable set but never used (in FD_ZERO) */
+#endif
+
/* Keep track of times using a signed representation. Switch to the
native (possibly unsigned) representation only when calling native
functions. */
diff --git a/Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt
new file mode 100644
index 0000000..628b6bc
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt
@@ -0,0 +1,2 @@
+
+Post-build Debug Release \.*$
diff --git a/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake
index 00aa896..de528be 100644
--- a/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake
@@ -14,3 +14,10 @@ add_custom_target(
ALL
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gen.txt"
)
+
+add_executable(exe main.c)
+
+add_custom_command(
+ TARGET exe POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Post-build $<CONFIG> $<COMMAND_CONFIG:$<CONFIG>> ${very_long}"
+ )
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index aa42739..e7acbc2 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -198,8 +198,11 @@ run_cmake_build(PostBuild release Release Exe)
run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LongCommandLine-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
run_cmake_configure(LongCommandLine)
+unset(RunCMake_TEST_OPTIONS)
run_cmake_build(LongCommandLine release Release custom)
+run_cmake_build(LongCommandLine release-config Release exe:Debug)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
diff --git a/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake b/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake
new file mode 100644
index 0000000..be07dc3
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake
@@ -0,0 +1,2 @@
+set(C 1)
+set(CXX 1)
diff --git a/Tests/RunCMake/ToolchainFile/LangVars.cmake b/Tests/RunCMake/ToolchainFile/LangVars.cmake
new file mode 100644
index 0000000..169e639
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/LangVars.cmake
@@ -0,0 +1,7 @@
+foreach(test_language C CXX)
+ enable_language(${test_language})
+ if(DEFINED CMAKE_${test_language}_STANDARD_DEFAULT
+ AND NOT CMAKE_${test_language}_COMPILE_FEATURES)
+ message(FATAL_ERROR "Compile features not found for ${test_language}")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
index 659523c..304c105 100644
--- a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
@@ -9,6 +9,7 @@ run_cmake_toolchain(CallEnableLanguage)
run_cmake_toolchain(CallProject)
run_cmake_toolchain(CheckLanguage)
run_cmake_toolchain(FlagsInit)
+run_cmake_toolchain(LangVars)
run_cmake_toolchain(LinkFlagsInit)
function(run_IncludeDirectories)
diff --git a/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in b/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in
new file mode 100644
index 0000000..63e5a5c
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+//General Information about an assembly is controlled through the following
+//set of attributes. Change these attribute values to modify the information
+//associated with an assembly.
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
index 80d76e4..9c9409c 100644
--- a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
@@ -13,6 +13,7 @@ set(SOURCE_GROUPS_TO_FIND
"CSharpSourceGroup\\\\nested\\\\baz\\.cs"
"CSharpSourceGroup\\\\images\\\\empty\\.bmp"
"VsCsharpSourceGroup\\.png"
+ "AssemblyInfo\\.cs"
)
foreach(GROUP_NAME IN LISTS SOURCE_GROUPS_TO_FIND)
diff --git a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
index 510d712..b67868f 100644
--- a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
+++ b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
@@ -20,3 +20,11 @@ add_library(VsCsharpSourceGroup SHARED ${SRC_FILES} ${IMAGE_FILES} ${RESOURCE_FI
source_group("CSharpSourceGroup" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/foo.cs)
source_group("CSharpSourceGroup/nested" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/nested/baz.cs)
source_group("Images" FILES ${IMAGE_FILES})
+
+# Test covering CMake Issue 22104.
+# Basically there should not be any link tags for files in the binary directory.
+include(CSharpUtilities)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/cmake/AssemblyInfo.cs.in" "Properties/AssemblyInfo.cs")
+
+target_sources(VsCsharpSourceGroup PRIVATE "Properties/AssemblyInfo.cs")
+csharp_set_designer_cs_properties("Properties/AssemblyInfo.cs")
diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake
index d3f7c23..15ca477 100644
--- a/Tests/RunCMake/foreach/RunCMakeTest.cmake
+++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake
@@ -20,3 +20,5 @@ run_cmake(foreach-RANGE-non-int-test-3-2)
run_cmake(foreach-RANGE-non-int-test-3-3)
run_cmake(foreach-RANGE-invalid-test)
run_cmake(foreach-RANGE-out-of-range-test)
+run_cmake(foreach-var-scope-CMP0124-OLD)
+run_cmake(foreach-var-scope-CMP0124-NEW)
diff --git a/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake
new file mode 100644
index 0000000..7e2eee0
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake
@@ -0,0 +1,51 @@
+
+cmake_policy(SET CMP0124 NEW)
+
+foreach(VAR a b c)
+endforeach()
+if (DEFINED VAR)
+ message(SEND_ERROR "Variable 'VAR' unexpectedly defined.")
+endif()
+
+set(LIST1 a b c)
+set(LIST2 x y z)
+foreach(VAR1_1 VAR1_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (DEFINED VAR1_1 OR DEFINED VAR1_2)
+ message(SEND_ERROR "Variables 'VAR1_1' or 'VAR1_2' unexpectedly defined.")
+endif()
+
+
+set (VAR2 OLD)
+foreach(VAR2 a b c)
+endforeach()
+if (NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR2' not defined or wrong value.")
+endif()
+
+set (VAR2_2 OLD)
+foreach(VAR2_1 VAR2_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (DEFINED VAR2_1 OR NOT DEFINED VAR2_2)
+ message(SEND_ERROR "Variable 'VAR2_1' unexpectedly defined or variable 'VAR2_2' not defined.")
+endif()
+
+
+set (VAR3 OLD CACHE STRING "")
+foreach(VAR3 a b c)
+endforeach()
+# check that only cache variable is defined
+set(OLD_VALUE "${VAR3}")
+unset(VAR3 CACHE)
+if (DEFINED VAR3 OR NOT OLD_VALUE STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR3' wrongly defined or wrong value.")
+endif()
+
+set (VAR3_2 OLD CACHE STRING "")
+foreach(VAR3_1 VAR3_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+set(OLD_VALUE "${VAR3_2}")
+unset(VAR3_2 CACHE)
+if (DEFINED VAR3_1 OR DEFINED VAR3_2 OR NOT OLD_VALUE STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR3_1' unexpectedly defined or variable 'VAR2_2' wrongly defined or wrong value.")
+endif()
diff --git a/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake
new file mode 100644
index 0000000..f955982
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake
@@ -0,0 +1,53 @@
+
+cmake_policy(SET CMP0124 OLD)
+
+foreach(VAR a b c)
+endforeach()
+if (NOT DEFINED VAR OR NOT VAR STREQUAL "")
+ message(SEND_ERROR "Variable 'VAR' not defined or wrong value.")
+endif()
+
+set(LIST1 a b c)
+set(LIST2 x y z)
+foreach(VAR1_1 VAR1_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (NOT DEFINED VAR1_1 OR NOT VAR1_1 STREQUAL ""
+ OR NOT DEFINED VAR1_2 OR NOT VAR1_2 STREQUAL "")
+ message(SEND_ERROR "Variables 'VAR1_1' or 'VAR1_2' not defined or wrong value.")
+endif()
+
+
+set (VAR2 OLD)
+foreach(VAR2 a b c)
+endforeach()
+if (NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR2' not defined or wrong value.")
+endif()
+
+set (VAR2_2 OLD)
+foreach(VAR2_1 VAR2_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (NOT DEFINED VAR2_1 OR NOT VAR2_1 STREQUAL ""
+ OR NOT DEFINED VAR2_2 OR NOT VAR2_2 STREQUAL "OLD")
+ message(SEND_ERROR "Variables 'VAR2_1' or 'VAR2_2' not defined or wrong value.")
+endif()
+
+
+set (VAR3 OLD CACHE STRING "")
+foreach(VAR3 a b c)
+endforeach()
+# a normal variable is defined, holding cache variable value
+unset(VAR3 CACHE)
+if (NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR3' not defined or wrong value.")
+endif()
+
+set (VAR3_2 OLD CACHE STRING "")
+foreach(VAR3_1 VAR3_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+# a normal variable is defined, holding cache variable value
+unset(VAR3_2 CACHE)
+if (NOT DEFINED VAR3_1 OR NOT VAR3_1 STREQUAL ""
+ OR NOT DEFINED VAR3_2 OR NOT VAR3_2 STREQUAL "OLD")
+ message(SEND_ERROR "Variables 'VAR3_1' or 'VAR3_2' not defined or wrong value.")
+endif()