From 7480fa0a5fd0ebc3fe06c702f3368e06a50c10ab Mon Sep 17 00:00:00 2001
From: Marc Chevrier <marc.chevrier@gmail.com>
Date: Thu, 8 Dec 2022 14:52:56 +0100
Subject: COMPILE_DEFINITIONS property: ensure leading -D is removed in all
 cases

Fixes: #24186
---
 Help/command/add_compile_definitions.rst                    |  3 +++
 Help/prop_dir/COMPILE_DEFINITIONS.rst                       |  3 +++
 Help/prop_sf/COMPILE_DEFINITIONS.rst                        |  3 +++
 Help/prop_tgt/COMPILE_DEFINITIONS.rst                       |  3 +++
 Help/release/dev/COMPILE_DEFINITIONS-property-cleanup.rst   |  6 ++++++
 Source/cmGlobalXCodeGenerator.cxx                           |  8 +++++++-
 Source/cmLocalGenerator.cxx                                 |  7 ++++++-
 Tests/RunCMake/CMakeLists.txt                               |  1 +
 Tests/RunCMake/CompileDefinitions/RemoveLeadingMinusD.cmake | 11 +++++++++++
 Tests/RunCMake/CompileDefinitions/RunCMakeTest.cmake        | 13 +++++++++++++
 Tests/RunCMake/CompileDefinitions/foo.c                     |  4 ++++
 Tests/RunCMake/add_compile_definitions/CMakeLists.txt       |  5 +++++
 Tests/RunCMake/add_compile_definitions/RunCMakeTest.cmake   | 13 +++++++++++++
 Tests/RunCMake/add_compile_definitions/foo.c                |  4 ++++
 .../add_compile_definitions/remove_leading_minusD.cmake     |  6 ++++++
 .../RunCMake/target_compile_definitions/RunCMakeTest.cmake  | 13 +++++++++++++
 Tests/RunCMake/target_compile_definitions/foo.c             |  4 ++++
 .../target_compile_definitions/remove_leading_minusD.cmake  |  9 +++++++++
 18 files changed, 114 insertions(+), 2 deletions(-)
 create mode 100644 Help/release/dev/COMPILE_DEFINITIONS-property-cleanup.rst
 create mode 100644 Tests/RunCMake/CompileDefinitions/RemoveLeadingMinusD.cmake
 create mode 100644 Tests/RunCMake/CompileDefinitions/foo.c
 create mode 100644 Tests/RunCMake/add_compile_definitions/CMakeLists.txt
 create mode 100644 Tests/RunCMake/add_compile_definitions/RunCMakeTest.cmake
 create mode 100644 Tests/RunCMake/add_compile_definitions/foo.c
 create mode 100644 Tests/RunCMake/add_compile_definitions/remove_leading_minusD.cmake
 create mode 100644 Tests/RunCMake/target_compile_definitions/foo.c
 create mode 100644 Tests/RunCMake/target_compile_definitions/remove_leading_minusD.cmake

diff --git a/Help/command/add_compile_definitions.rst b/Help/command/add_compile_definitions.rst
index ad1fc43..b2eb2af 100644
--- a/Help/command/add_compile_definitions.rst
+++ b/Help/command/add_compile_definitions.rst
@@ -21,6 +21,9 @@ Function-style definitions are not supported. CMake will automatically
 escape the value correctly for the native build system (note that CMake
 language syntax may require escapes to specify some values).
 
+.. versionadded:: 3.26
+  Any leading ``-D`` on an item will be removed.
+
 .. |command_name| replace:: ``add_compile_definitions``
 .. include:: GENEX_NOTE.txt
 
diff --git a/Help/prop_dir/COMPILE_DEFINITIONS.rst b/Help/prop_dir/COMPILE_DEFINITIONS.rst
index 18f4567..5a12c1e 100644
--- a/Help/prop_dir/COMPILE_DEFINITIONS.rst
+++ b/Help/prop_dir/COMPILE_DEFINITIONS.rst
@@ -19,6 +19,9 @@ directory's parent.
 CMake will automatically drop some definitions that are not supported
 by the native build tool.
 
+.. versionadded:: 3.26
+  Any leading ``-D`` on an item will be removed.
+
 .. include:: /include/COMPILE_DEFINITIONS_DISCLAIMER.txt
 
 Contents of ``COMPILE_DEFINITIONS`` may use "generator expressions" with
diff --git a/Help/prop_sf/COMPILE_DEFINITIONS.rst b/Help/prop_sf/COMPILE_DEFINITIONS.rst
index 6317690..2af896e 100644
--- a/Help/prop_sf/COMPILE_DEFINITIONS.rst
+++ b/Help/prop_sf/COMPILE_DEFINITIONS.rst
@@ -16,6 +16,9 @@ CMake will automatically drop some definitions that are not supported
 by the native build tool.  Xcode does not support per-configuration
 definitions on source files.
 
+.. versionadded:: 3.26
+  Any leading ``-D`` on an item will be removed.
+
 .. include:: /include/COMPILE_DEFINITIONS_DISCLAIMER.txt
 
 Contents of ``COMPILE_DEFINITIONS`` may use :manual:`cmake-generator-expressions(7)`
diff --git a/Help/prop_tgt/COMPILE_DEFINITIONS.rst b/Help/prop_tgt/COMPILE_DEFINITIONS.rst
index 059f913..c128a9b 100644
--- a/Help/prop_tgt/COMPILE_DEFINITIONS.rst
+++ b/Help/prop_tgt/COMPILE_DEFINITIONS.rst
@@ -13,6 +13,9 @@ values).
 CMake will automatically drop some definitions that are not supported
 by the native build tool.
 
+.. versionadded:: 3.26
+  Any leading ``-D`` on an item will be removed.
+
 .. include:: /include/COMPILE_DEFINITIONS_DISCLAIMER.txt
 
 Contents of ``COMPILE_DEFINITIONS`` may use "generator expressions" with the
diff --git a/Help/release/dev/COMPILE_DEFINITIONS-property-cleanup.rst b/Help/release/dev/COMPILE_DEFINITIONS-property-cleanup.rst
new file mode 100644
index 0000000..e24bc26
--- /dev/null
+++ b/Help/release/dev/COMPILE_DEFINITIONS-property-cleanup.rst
@@ -0,0 +1,6 @@
+COMPILE_DEFINITIONS-property-cleanup
+------------------------------------
+
+* For all ``COMPILE_DEFINITIONS`` properties, any leading ``-D`` on an item
+  will be removed regardless how to was defined: as is or inside a generator
+  expression.
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 6751efd..e5c50cd 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -4995,7 +4995,13 @@ void cmGlobalXCodeGenerator::AppendDefines(
   std::string def;
   for (auto const& define : defines) {
     // Start with -D if requested.
-    def = cmStrCat(dflag ? "-D" : "", define);
+    if (dflag && !cmHasLiteralPrefix(define, "-D")) {
+      def = cmStrCat("-D", define);
+    } else if (!dflag && cmHasLiteralPrefix(define, "-D")) {
+      def = define.substr(2);
+    } else {
+      def = define;
+    }
 
     // Append the flag with needed escapes.
     std::string tmp;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 5bf9d32..cedb367 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -3377,7 +3377,12 @@ void cmLocalGenerator::AppendDefines(
     if (!this->CheckDefinition(d.Value)) {
       continue;
     }
-    defines.insert(d);
+    // remove any leading -D
+    if (cmHasLiteralPrefix(d.Value, "-D")) {
+      defines.emplace(d.Value.substr(2), d.Backtrace);
+    } else {
+      defines.insert(d);
+    }
   }
 }
 
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 78615d9..d5c07dd 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -693,6 +693,7 @@ add_RunCMake_test(target_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_I
 set_property(TEST RunCMake.target_link_options APPEND
   PROPERTY LABELS "CUDA")
 
+add_RunCMake_test(add_compile_definitions)
 add_RunCMake_test(target_compile_definitions)
 add_RunCMake_test(target_compile_features)
 add_RunCMake_test(target_compile_options
diff --git a/Tests/RunCMake/CompileDefinitions/RemoveLeadingMinusD.cmake b/Tests/RunCMake/CompileDefinitions/RemoveLeadingMinusD.cmake
new file mode 100644
index 0000000..3db6cff1f
--- /dev/null
+++ b/Tests/RunCMake/CompileDefinitions/RemoveLeadingMinusD.cmake
@@ -0,0 +1,11 @@
+
+enable_language(C)
+
+set_property(SOURCE foo.c PROPERTY COMPILE_DEFINITIONS -DDEF0 "$<1:-DDEF1>")
+
+add_library(lib1 foo.c)
+set_property(TARGET lib1 PROPERTY COMPILE_DEFINITIONS -DDEF2 "$<1:-DDEF3>")
+set_property(TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS -DDEF4 "$<1:-DDEF5>")
+
+add_library(lib2 foo.c)
+target_link_libraries(lib2 PRIVATE lib1)
diff --git a/Tests/RunCMake/CompileDefinitions/RunCMakeTest.cmake b/Tests/RunCMake/CompileDefinitions/RunCMakeTest.cmake
index 233fe34..eebcd22 100644
--- a/Tests/RunCMake/CompileDefinitions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileDefinitions/RunCMakeTest.cmake
@@ -1,3 +1,16 @@
 include(RunCMake)
 
 run_cmake(SetEmpty)
+
+
+macro(run_cmake_build test)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${test} ${CMAKE_COMMAND} --build . --config Release)
+
+  unset(RunCMake_TEST_BINARY_DIR)
+  unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+run_cmake(RemoveLeadingMinusD)
+run_cmake_build(RemoveLeadingMinusD)
diff --git a/Tests/RunCMake/CompileDefinitions/foo.c b/Tests/RunCMake/CompileDefinitions/foo.c
new file mode 100644
index 0000000..74a86e1
--- /dev/null
+++ b/Tests/RunCMake/CompileDefinitions/foo.c
@@ -0,0 +1,4 @@
+
+void foo()
+{
+}
diff --git a/Tests/RunCMake/add_compile_definitions/CMakeLists.txt b/Tests/RunCMake/add_compile_definitions/CMakeLists.txt
new file mode 100644
index 0000000..14ef56e
--- /dev/null
+++ b/Tests/RunCMake/add_compile_definitions/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.11)
+
+project(${RunCMake_TEST} LANGUAGES NONE)
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/add_compile_definitions/RunCMakeTest.cmake b/Tests/RunCMake/add_compile_definitions/RunCMakeTest.cmake
new file mode 100644
index 0000000..27d77ef
--- /dev/null
+++ b/Tests/RunCMake/add_compile_definitions/RunCMakeTest.cmake
@@ -0,0 +1,13 @@
+include(RunCMake)
+
+macro(run_cmake_build test)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${test} ${CMAKE_COMMAND} --build . --config Release)
+
+  unset(RunCMake_TEST_BINARY_DIR)
+  unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+run_cmake(remove_leading_minusD)
+run_cmake_build(remove_leading_minusD)
diff --git a/Tests/RunCMake/add_compile_definitions/foo.c b/Tests/RunCMake/add_compile_definitions/foo.c
new file mode 100644
index 0000000..74a86e1
--- /dev/null
+++ b/Tests/RunCMake/add_compile_definitions/foo.c
@@ -0,0 +1,4 @@
+
+void foo()
+{
+}
diff --git a/Tests/RunCMake/add_compile_definitions/remove_leading_minusD.cmake b/Tests/RunCMake/add_compile_definitions/remove_leading_minusD.cmake
new file mode 100644
index 0000000..0d94340
--- /dev/null
+++ b/Tests/RunCMake/add_compile_definitions/remove_leading_minusD.cmake
@@ -0,0 +1,6 @@
+
+enable_language(C)
+
+add_compile_definitions(-DDEF0 "$<1:-DDEF1>")
+
+add_library(lib1 foo.c)
diff --git a/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake
index a419cc9..4dd01db 100644
--- a/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake
@@ -2,3 +2,16 @@ include(RunCMake)
 
 run_cmake(empty_keyword_args)
 run_cmake(unknown_imported_target)
+
+
+macro(run_cmake_build test)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${test} ${CMAKE_COMMAND} --build . --config Release)
+
+  unset(RunCMake_TEST_BINARY_DIR)
+  unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+run_cmake(remove_leading_minusD)
+run_cmake_build(remove_leading_minusD)
diff --git a/Tests/RunCMake/target_compile_definitions/foo.c b/Tests/RunCMake/target_compile_definitions/foo.c
new file mode 100644
index 0000000..74a86e1
--- /dev/null
+++ b/Tests/RunCMake/target_compile_definitions/foo.c
@@ -0,0 +1,4 @@
+
+void foo()
+{
+}
diff --git a/Tests/RunCMake/target_compile_definitions/remove_leading_minusD.cmake b/Tests/RunCMake/target_compile_definitions/remove_leading_minusD.cmake
new file mode 100644
index 0000000..53c03c1
--- /dev/null
+++ b/Tests/RunCMake/target_compile_definitions/remove_leading_minusD.cmake
@@ -0,0 +1,9 @@
+
+enable_language(C)
+
+add_library(lib1 foo.c)
+target_compile_definitions(lib1 PRIVATE -DDEF0 "$<1:-DDEF1>")
+target_compile_definitions(lib1 PUBLIC -DDEF2 "$<1:-DDEF3>")
+
+add_library(lib2 foo.c)
+target_link_libraries(lib2 PRIVATE lib1)
-- 
cgit v0.12