Prechádzať zdrojové kódy

Autogen: Add target's C++ standard to moc_predef.h

Generate `moc_predef.h` using the same C++ standard level that will be
used to compile the target so that the compiler's predefined macros can
be more accurately recovered.

Fixes: #24624
Qt-Issue: https://bugreports.qt.io/browse/QTBUG-110847
Orkun Tokdemir 2 rokov pred
rodič
commit
429a452705

+ 16 - 1
Source/cmQtAutoGenInitializer.cxx

@@ -43,6 +43,7 @@
 #include "cmSourceFile.h"
 #include "cmSourceFileLocationKind.h"
 #include "cmSourceGroup.h"
+#include "cmStandardLevelResolver.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
@@ -1699,8 +1700,22 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
         jval[1u] = pair.second;
       });
     info.SetConfig("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
-    info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
     info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);
+
+    cmStandardLevelResolver resolver{ this->Makefile };
+    auto CompileOptionFlag =
+      resolver.GetCompileOptionDef(this->GenTarget, "CXX", "");
+
+    auto CompileOptionValue =
+      this->GenTarget->Makefile->GetSafeDefinition(CompileOptionFlag);
+
+    if (!CompileOptionValue.empty()) {
+      if (this->Moc.PredefsCmd.size() >= 3) {
+        this->Moc.PredefsCmd.insert(this->Moc.PredefsCmd.begin() + 1,
+                                    CompileOptionValue);
+      }
+    }
+    info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
   }
 
   // Write uic settings

+ 1 - 0
Tests/RunCMake/Autogen/MocPredefs-build-stderr.txt

@@ -0,0 +1 @@
+.*

+ 60 - 0
Tests/RunCMake/Autogen/MocPredefs-check.cxx

@@ -0,0 +1,60 @@
+#include <iostream>
+
+#include "check_predefs.h"
+
+#define TO_STRING(x) TO_STRING0(x)
+#define TO_STRING0(x) #x
+
+int main()
+{
+  int ret = 0;
+#if defined(__STRICT_ANSI__)
+#  if !defined(CHECK___STRICT_ANSI__)
+  std::cout << "__STRICT_ANSI__: Expected " << TO_STRING(__STRICT_ANSI__)
+            << " but it is not defined.\n";
+  ret = 1;
+#  elif __STRICT_ANSI__ != CHECK___STRICT_ANSI__
+  std::cout << "__STRICT_ANSI__: Expected " << TO_STRING(__STRICT_ANSI__)
+            << " but got: " << TO_STRING(CHECK___STRICT_ANSI__) << "\n";
+  ret = 1;
+#  endif
+#elif defined(CHECK___STRICT_ANSI__)
+  std::cout << "__STRICT_ANSI__: Expected undefined but got: "
+            << TO_STRING(CHECK___STRICT_ANSI__) << "\n";
+  ret = 1;
+#endif
+
+#if defined(__cplusplus)
+#  if !defined(CHECK___cplusplus)
+  std::cout << "__cplusplus: Expected " << TO_STRING(__cplusplus)
+            << " but it is not defined.\n";
+  ret = 1;
+#  elif __cplusplus != CHECK___cplusplus
+  std::cout << "__cplusplus: Expected " << TO_STRING(__cplusplus)
+            << " but got: " << TO_STRING(CHECK___cplusplus) << "\n";
+  ret = 1;
+#  endif
+#elif defined(CHECK___cplusplus)
+  std::cout << "__cplusplus: Expected undefined but got: "
+            << TO_STRING(CHECK___cplusplus) << "\n";
+  ret = 1;
+#endif
+
+#if defined(_MSVC_LANG)
+#  if !defined(CHECK__MSVC_LANG)
+  std::cout << "_MSVC_LANG: Expected " << TO_STRING(_MSVC_LANG)
+            << " but it is not defined.\n";
+  ret = 1;
+#  elif _MSVC_LANG != CHECK__MSVC_LANG
+  std::cout << "_MSVC_LANG: Expected " << TO_STRING(_MSVC_LANG)
+            << " but got: " << TO_STRING(CHECK__MSVC_LANG) << "\n";
+  ret = 1;
+#  endif
+#elif defined(CHECK__MSVC_LANG)
+  std::cout << "_MSVC_LANG: Expected undefined but got: "
+            << TO_STRING(CHECK__MSVC_LANG) << "\n";
+  ret = 1;
+#endif
+
+  return ret;
+}

+ 3 - 0
Tests/RunCMake/Autogen/MocPredefs-prefix.cmake

@@ -0,0 +1,3 @@
+file(READ ${in} predefs)
+string(REGEX REPLACE "#define +" "#define CHECK_" predefs "${predefs}")
+file(WRITE ${out} "${predefs}")

+ 40 - 0
Tests/RunCMake/Autogen/MocPredefs.cmake

@@ -0,0 +1,40 @@
+cmake_policy(SET CMP0129 NEW)
+enable_language(CXX)
+
+find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+add_library(MocPredefs MocPredefs.cxx)
+
+if(NOT DEFINED CMAKE_CXX_COMPILER_PREDEFINES_COMMAND)
+  return()
+endif()
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "LCC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "1.26")
+  return()
+endif()
+
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(_isMultiConfig)
+  set(moc_predefs_h "moc_predefs_$<CONFIG>.h")
+  set(check_dir "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
+else()
+  set(moc_predefs_h "moc_predefs.h")
+  set(check_dir "${CMAKE_CURRENT_BINARY_DIR}")
+endif()
+
+add_custom_command(TARGET MocPredefs POST_BUILD VERBATIM COMMAND
+  ${CMAKE_COMMAND}
+    -Din=${CMAKE_CURRENT_BINARY_DIR}/MocPredefs_autogen/${moc_predefs_h}
+    -Dout=${check_dir}/check_predefs.h
+    -P${CMAKE_CURRENT_SOURCE_DIR}/MocPredefs-prefix.cmake
+  )
+
+add_executable(MocPredefs-check MocPredefs-check.cxx)
+target_include_directories(MocPredefs-check PRIVATE ${check_dir})
+add_dependencies(MocPredefs-check MocPredefs)
+
+add_custom_target(MocPredefs-run-check ALL VERBATIM COMMAND MocPredefs-check)

+ 3 - 0
Tests/RunCMake/Autogen/MocPredefs.cxx

@@ -0,0 +1,3 @@
+void MocPredefs()
+{
+}

+ 7 - 0
Tests/RunCMake/Autogen/RunCMakeTest.cmake

@@ -15,4 +15,11 @@ if (DEFINED with_qt_version)
   run_cmake(CMP0111-imported-target-full)
   run_cmake(CMP0111-imported-target-libname)
   run_cmake(CMP0111-imported-target-implib-only)
+
+  block()
+    set(RunCMake_TEST_BINARY_DIR  ${RunCMake_BINARY_DIR}/MocPredefs-build)
+    run_cmake(MocPredefs)
+    set(RunCMake_TEST_NO_CLEAN 1)
+    run_cmake_command(MocPredefs-build ${CMAKE_COMMAND} --build . --config Debug)
+  endblock()
 endif ()