Просмотр исходного кода

Restore support for explicitly referenced CMakeLists.txt sources

Since commit v3.11.0-rc1~467^2 (VS,Xcode: Add CMakeLists.txt sources
without mutating targets, 2017-10-18) we do not add `CMakeLists.txt` to
target sources but instead generate references to them directly.  This
broke projects that explicitly specify their `CMakeLists.txt` file as a
source file because the explicit entry is no longer consolidated with
the generated one.

Teach the relevant generators to avoid duplicating `CMakeLists.txt`
source references and add test cases.

Fixes: #17828
Brad King 7 лет назад
Родитель
Сommit
8480c2afc0

+ 15 - 8
Source/cmGlobalXCodeGenerator.cxx

@@ -821,6 +821,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
   return buildFile;
   return buildFile;
 }
 }
 
 
+void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
+  cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const
+{
+  std::string listfile =
+    target->GetLocalGenerator()->GetCurrentSourceDirectory();
+  listfile += "/CMakeLists.txt";
+  cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(listfile);
+  if (std::find(sources.begin(), sources.end(), srcCMakeLists) ==
+      sources.end()) {
+    sources.push_back(srcCMakeLists);
+  }
+}
+
 std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
 std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
                                                 const std::string& lang,
                                                 const std::string& lang,
                                                 bool& keepLastKnownFileType)
                                                 bool& keepLastKnownFileType)
@@ -1043,10 +1056,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
     }
     }
 
 
     // Add CMakeLists.txt file for user convenience.
     // Add CMakeLists.txt file for user convenience.
-    std::string listfile =
-      gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
-    listfile += "/CMakeLists.txt";
-    classes.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+    this->AddXCodeProjBuildRule(gtgt, classes);
 
 
     std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
     std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
 
 
@@ -2343,10 +2353,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
     }
     }
 
 
     // Add CMakeLists.txt file for user convenience.
     // Add CMakeLists.txt file for user convenience.
-    std::string listfile =
-      gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
-    listfile += "/CMakeLists.txt";
-    sources.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+    this->AddXCodeProjBuildRule(gtgt, sources);
 
 
     for (auto sourceFile : sources) {
     for (auto sourceFile : sources) {
       if (!sourceFile->GetPropertyAsBool("GENERATED")) {
       if (!sourceFile->GetPropertyAsBool("GENERATED")) {

+ 2 - 0
Source/cmGlobalXCodeGenerator.h

@@ -198,6 +198,8 @@ private:
                                           cmGeneratorTarget* target);
                                           cmGeneratorTarget* target);
   cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
   cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
                                        cmGeneratorTarget* gtgt);
                                        cmGeneratorTarget* gtgt);
+  void AddXCodeProjBuildRule(cmGeneratorTarget* target,
+                             std::vector<cmSourceFile*>& sources) const;
   bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
   bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
   bool IsHeaderFile(cmSourceFile*);
   bool IsHeaderFile(cmSourceFile*);
   void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
   void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);

+ 12 - 1
Source/cmLocalVisualStudio7Generator.cxx

@@ -1347,7 +1347,18 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
       for (size_t ci = 0; ci < configs.size(); ++ci) {
       for (size_t ci = 0; ci < configs.size(); ++ci) {
         acs.Configs.push_back(ci);
         acs.Configs.push_back(ci);
       }
       }
-      sources.Sources.emplace_back(std::move(acs));
+      bool haveCMakeLists = false;
+      for (cmGeneratorTarget::AllConfigSource& si : sources.Sources) {
+        if (si.Source == sf) {
+          haveCMakeLists = true;
+          // Replace the explicit source reference with our generated one.
+          si = acs;
+          break;
+        }
+      }
+      if (!haveCMakeLists) {
+        sources.Sources.emplace_back(std::move(acs));
+      }
     }
     }
   }
   }
 
 

+ 7 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -1898,7 +1898,14 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
   std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
   std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
     this->GeneratorTarget->GetAllConfigSources();
     this->GeneratorTarget->GetAllConfigSources();
 
 
+  cmSourceFile const* srcCMakeLists =
+    this->LocalGenerator->CreateVCProjBuildRule();
+
   for (cmGeneratorTarget::AllConfigSource const& si : sources) {
   for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+    if (si.Source == srcCMakeLists) {
+      // Skip explicit reference to CMakeLists.txt source.
+      continue;
+    }
     std::string tool;
     std::string tool;
     switch (si.Kind) {
     switch (si.Kind) {
       case cmGeneratorTarget::SourceKindAppManifest:
       case cmGeneratorTarget::SourceKindAppManifest:

+ 25 - 0
Tests/RunCMake/VS10Project/ExplicitCMakeLists-check.cmake

@@ -0,0 +1,25 @@
+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(foundCMakeLists 0)
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+  if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*CMakeLists.txt")
+    set(rule "${CMAKE_MATCH_1}")
+    if(NOT rule STREQUAL "CustomBuild")
+      set(RunCMake_TEST_FAILED "CMakeLists.txt referenced as ${rule} instead of CustomBuild")
+      return()
+    endif()
+    if(foundCMakeLists)
+      set(RunCMake_TEST_FAILED "CMakeLists.txt referenced multiple times")
+      return()
+    endif()
+    set(foundCMakeLists 1)
+  endif()
+endforeach()
+if(NOT foundCMakeLists)
+  set(RunCMake_TEST_FAILED "CMakeLists.txt not referenced")
+endif()

+ 3 - 0
Tests/RunCMake/VS10Project/ExplicitCMakeLists.cmake

@@ -0,0 +1,3 @@
+set(CMAKE_CONFIGURATION_TYPES Debug)
+enable_language(CXX)
+add_executable(foo foo.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)

+ 3 - 0
Tests/RunCMake/VS10Project/RunCMakeTest.cmake

@@ -1,4 +1,7 @@
 include(RunCMake)
 include(RunCMake)
+
+run_cmake(ExplicitCMakeLists)
+
 run_cmake(VsConfigurationType)
 run_cmake(VsConfigurationType)
 run_cmake(VsTargetsFileReferences)
 run_cmake(VsTargetsFileReferences)
 run_cmake(VsCustomProps)
 run_cmake(VsCustomProps)

+ 20 - 0
Tests/RunCMake/XcodeProject/ExplicitCMakeLists-check.cmake

@@ -0,0 +1,20 @@
+set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/ExplicitCMakeLists.xcodeproj/project.pbxproj")
+if(NOT EXISTS "${xcProjectFile}")
+  set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.")
+  return()
+endif()
+
+set(foundCMakeLists 0)
+file(STRINGS "${xcProjectFile}" lines)
+foreach(line IN LISTS lines)
+  if(line MATCHES "PBXBuildFile.*fileRef.*CMakeLists.txt")
+    if(foundCMakeLists)
+      set(RunCMake_TEST_FAILED "CMakeLists.txt referenced multiple times")
+      return()
+    endif()
+    set(foundCMakeLists 1)
+  endif()
+endforeach()
+if(NOT foundCMakeLists)
+  set(RunCMake_TEST_FAILED "CMakeLists.txt not referenced")
+endif()

+ 2 - 0
Tests/RunCMake/XcodeProject/ExplicitCMakeLists.cmake

@@ -0,0 +1,2 @@
+enable_language(CXX)
+add_executable(foo foo.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)

+ 2 - 0
Tests/RunCMake/XcodeProject/RunCMakeTest.cmake

@@ -4,6 +4,8 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 9)
   set(IOS_DEPLOYMENT_TARGET "-DCMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET=10")
   set(IOS_DEPLOYMENT_TARGET "-DCMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET=10")
 endif()
 endif()
 
 
+run_cmake(ExplicitCMakeLists)
+
 run_cmake(XcodeFileType)
 run_cmake(XcodeFileType)
 run_cmake(XcodeAttributeLocation)
 run_cmake(XcodeAttributeLocation)
 run_cmake(XcodeAttributeGenex)
 run_cmake(XcodeAttributeGenex)