Explorar el Código

Defer check for sources within a target until generation.

The `add_library` and `add_executable` commands can now be called with
no source-files and won't generate a warning or error message, as long
as source-files will be added later via the `target_sources` command.
If during the generation step still no sources are associated with
targets created by such calls a useful error message will be generated
and generation fails.

Targets of type `INTERFACE_LIBRARY`, `UTILITY` or `GLOBAL_TARGET` are
excluded from this check because we do not need sources for these target
types during generation.

Fixes: #16872
Deniz Bahadir hace 8 años
padre
commit
4e7f67383f
Se han modificado 24 ficheros con 97 adiciones y 75 borrados
  1. 7 6
      Help/command/add_executable.rst
  2. 6 5
      Help/command/add_library.rst
  3. 6 0
      Help/release/dev/defer-target-source-check.rst
  4. 1 7
      Source/cmAddExecutableCommand.cxx
  5. 0 8
      Source/cmAddLibraryCommand.cxx
  6. 42 0
      Source/cmGlobalGenerator.cxx
  7. 2 0
      Source/cmGlobalGenerator.h
  8. 1 1
      Tests/RunCMake/add_executable/NoSources-stderr.txt
  9. 1 8
      Tests/RunCMake/add_executable/NoSourcesButLinkObjects-stderr.txt
  10. 0 1
      Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
  11. 0 11
      Tests/RunCMake/add_executable/OnlyObjectSources-stderr.txt
  12. 4 3
      Tests/RunCMake/add_library/MODULEwithNoSources-stderr.txt
  13. 4 3
      Tests/RunCMake/add_library/MODULEwithNoSourcesButLinkObjects-stderr.txt
  14. 0 1
      Tests/RunCMake/add_library/MODULEwithOnlyObjectSources-stderr.txt
  15. 1 1
      Tests/RunCMake/add_library/OBJECTwithNoSources-result.txt
  16. 4 2
      Tests/RunCMake/add_library/OBJECTwithNoSources-stderr.txt
  17. 1 2
      Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
  18. 1 2
      Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt
  19. 4 3
      Tests/RunCMake/add_library/SHAREDwithNoSources-stderr.txt
  20. 4 3
      Tests/RunCMake/add_library/SHAREDwithNoSourcesButLinkObjects-stderr.txt
  21. 0 1
      Tests/RunCMake/add_library/SHAREDwithOnlyObjectSources-stderr.txt
  22. 4 3
      Tests/RunCMake/add_library/STATICwithNoSources-stderr.txt
  23. 4 3
      Tests/RunCMake/add_library/STATICwithNoSourcesButLinkObjects-stderr.txt
  24. 0 1
      Tests/RunCMake/add_library/STATICwithOnlyObjectSources-stderr.txt

+ 7 - 6
Help/command/add_executable.rst

@@ -7,14 +7,15 @@ Add an executable to the project using the specified source files.
 
 
   add_executable(<name> [WIN32] [MACOSX_BUNDLE]
   add_executable(<name> [WIN32] [MACOSX_BUNDLE]
                  [EXCLUDE_FROM_ALL]
                  [EXCLUDE_FROM_ALL]
-                 source1 [source2 ...])
+                 [source1] [source2 ...])
 
 
 Adds an executable target called ``<name>`` to be built from the source
 Adds an executable target called ``<name>`` to be built from the source
-files listed in the command invocation.  The ``<name>`` corresponds to the
-logical target name and must be globally unique within a project.  The
-actual file name of the executable built is constructed based on
-conventions of the native platform (such as ``<name>.exe`` or just
-``<name>``).
+files listed in the command invocation.  (The source files can be omitted
+here if they are added later using :command:`target_sources`.)  The
+``<name>`` corresponds to the logical target name and must be globally
+unique within a project.  The actual file name of the executable built is
+constructed based on conventions of the native platform (such as
+``<name>.exe`` or just ``<name>``).
 
 
 By default the executable file will be created in the build tree
 By default the executable file will be created in the build tree
 directory corresponding to the source tree directory in which the
 directory corresponding to the source tree directory in which the

+ 6 - 5
Help/command/add_library.rst

@@ -14,13 +14,14 @@ Normal Libraries
 
 
   add_library(<name> [STATIC | SHARED | MODULE]
   add_library(<name> [STATIC | SHARED | MODULE]
               [EXCLUDE_FROM_ALL]
               [EXCLUDE_FROM_ALL]
-              source1 [source2 ...])
+              [source1] [source2 ...])
 
 
 Adds a library target called ``<name>`` to be built from the source files
 Adds a library target called ``<name>`` to be built from the source files
-listed in the command invocation.  The ``<name>`` corresponds to the
-logical target name and must be globally unique within a project.  The
-actual file name of the library built is constructed based on
-conventions of the native platform (such as ``lib<name>.a`` or
+listed in the command invocation.  (The source files can be omitted here
+if they are added later using :command:`target_sources`.)  The ``<name>``
+corresponds to the logical target name and must be globally unique within
+a project.  The actual file name of the library built is constructed based
+on conventions of the native platform (such as ``lib<name>.a`` or
 ``<name>.lib``).
 ``<name>.lib``).
 
 
 ``STATIC``, ``SHARED``, or ``MODULE`` may be given to specify the type of
 ``STATIC``, ``SHARED``, or ``MODULE`` may be given to specify the type of

+ 6 - 0
Help/release/dev/defer-target-source-check.rst

@@ -0,0 +1,6 @@
+defer-target-source-check
+-------------------------
+
+* :command:`add_library` and :command:`add_executable` commands can now be
+  called without any sources and will not complain as long as sources will
+  be added later via :command:`target_sources`.

+ 1 - 7
Source/cmAddExecutableCommand.cxx

@@ -18,7 +18,7 @@ class cmExecutionStatus;
 bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
 bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
                                          cmExecutionStatus&)
                                          cmExecutionStatus&)
 {
 {
-  if (args.size() < 2) {
+  if (args.empty()) {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
   }
   }
@@ -191,12 +191,6 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
     }
     }
   }
   }
 
 
-  if (s == args.end()) {
-    this->SetError(
-      "called with incorrect number of arguments, no sources provided");
-    return false;
-  }
-
   std::vector<std::string> srclists(s, args.end());
   std::vector<std::string> srclists(s, args.end());
   cmTarget* tgt =
   cmTarget* tgt =
     this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll);
     this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll);

+ 0 - 8
Source/cmAddLibraryCommand.cxx

@@ -362,14 +362,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
     return true;
     return true;
   }
   }
 
 
-  if (s == args.end()) {
-    std::string msg = "You have called ADD_LIBRARY for library ";
-    msg += args[0];
-    msg += " without any source files. This typically indicates a problem ";
-    msg += "with your CMakeLists.txt file";
-    cmSystemTools::Message(msg.c_str(), "Warning");
-  }
-
   srclists.insert(srclists.end(), s, args.end());
   srclists.insert(srclists.end(), s, args.end());
 
 
   this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
   this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);

+ 42 - 0
Source/cmGlobalGenerator.cxx

@@ -261,6 +261,43 @@ void cmGlobalGenerator::ForceLinkerLanguages()
 {
 {
 }
 }
 
 
+bool cmGlobalGenerator::CheckTargetsForMissingSources() const
+{
+  bool failed = false;
+  for (cmLocalGenerator* localGen : this->LocalGenerators) {
+    const std::vector<cmGeneratorTarget*>& targets =
+      localGen->GetGeneratorTargets();
+
+    for (cmGeneratorTarget* target : targets) {
+      if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
+          target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
+          target->GetType() == cmStateEnums::TargetType::UTILITY) {
+        continue;
+      }
+
+      std::vector<std::string> configs;
+      target->Makefile->GetConfigurations(configs);
+      std::vector<cmSourceFile*> srcs;
+      if (configs.empty()) {
+        target->GetSourceFiles(srcs, "");
+      } else {
+        for (std::vector<std::string>::const_iterator ci = configs.begin();
+             ci != configs.end() && srcs.empty(); ++ci) {
+          target->GetSourceFiles(srcs, *ci);
+        }
+      }
+      if (srcs.empty()) {
+        std::ostringstream e;
+        e << "No SOURCES given to target: " << target->GetName();
+        this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+                                               target->GetBacktrace());
+        failed = true;
+      }
+    }
+  }
+  return failed;
+}
+
 bool cmGlobalGenerator::IsExportedTargetsFile(
 bool cmGlobalGenerator::IsExportedTargetsFile(
   const std::string& filename) const
   const std::string& filename) const
 {
 {
@@ -1292,6 +1329,11 @@ bool cmGlobalGenerator::Compute()
     localGen->TraceDependencies();
     localGen->TraceDependencies();
   }
   }
 
 
+  // Make sure that all (non-imported) targets have source files added!
+  if (this->CheckTargetsForMissingSources()) {
+    return false;
+  }
+
   this->ForceLinkerLanguages();
   this->ForceLinkerLanguages();
 
 
   // Compute the manifest of main targets generated.
   // Compute the manifest of main targets generated.

+ 2 - 0
Source/cmGlobalGenerator.h

@@ -539,6 +539,8 @@ private:
 
 
   virtual void ForceLinkerLanguages();
   virtual void ForceLinkerLanguages();
 
 
+  bool CheckTargetsForMissingSources() const;
+
   void CreateLocalGenerators();
   void CreateLocalGenerators();
 
 
   void CheckCompilerIdCompatibility(cmMakefile* mf,
   void CheckCompilerIdCompatibility(cmMakefile* mf,

+ 1 - 1
Tests/RunCMake/add_executable/NoSources-stderr.txt

@@ -1,4 +1,4 @@
 ^CMake Error at NoSources.cmake:[0-9]+ \(add_executable\):
 ^CMake Error at NoSources.cmake:[0-9]+ \(add_executable\):
-  add_executable called with incorrect number of arguments
+  No SOURCES given to target: TestExeWithoutSources
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)$
   CMakeLists.txt:[0-9]+ \(include\)$

+ 1 - 8
Tests/RunCMake/add_executable/NoSourcesButLinkObjects-stderr.txt

@@ -1,11 +1,4 @@
 ^CMake Error at NoSourcesButLinkObjects.cmake:[0-9]+ \(add_executable\):
 ^CMake Error at NoSourcesButLinkObjects.cmake:[0-9]+ \(add_executable\):
-  add_executable called with incorrect number of arguments
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)
-
-
-CMake Error at NoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
-  Cannot specify link libraries for target \"TestExeWithoutSources\" which is
-  not built by this project.
+  No SOURCES given to target: TestExeWithoutSources
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)$
   CMakeLists.txt:[0-9]+ \(include\)$

+ 0 - 1
Tests/RunCMake/add_executable/OnlyObjectSources-result.txt

@@ -1 +0,0 @@
-1

+ 0 - 11
Tests/RunCMake/add_executable/OnlyObjectSources-stderr.txt

@@ -1,11 +0,0 @@
-^CMake Error at OnlyObjectSources.cmake:[0-9]+ \(add_executable\):
-  add_executable called with incorrect number of arguments
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)
-
-
-CMake Error at OnlyObjectSources.cmake:[0-9]+ \(target_sources\):
-  Cannot specify sources for target \"TestExeWithoutSources\" which is not
-  built by this project.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)$

+ 4 - 3
Tests/RunCMake/add_library/MODULEwithNoSources-stderr.txt

@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestModuleLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestModuleLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestModuleLibWithoutSources\".)?$
+^CMake Error at MODULEwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestModuleLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 4 - 3
Tests/RunCMake/add_library/MODULEwithNoSourcesButLinkObjects-stderr.txt

@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestModuleLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestModuleLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestModuleLibWithoutSources\".)*$
+^CMake Error at MODULEwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestModuleLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 0 - 1
Tests/RunCMake/add_library/MODULEwithOnlyObjectSources-stderr.txt

@@ -1 +0,0 @@
-^You have called ADD_LIBRARY for library TestModuleLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file$

+ 1 - 1
Tests/RunCMake/add_library/OBJECTwithNoSources-result.txt

@@ -1 +1 @@
-.
+1

+ 4 - 2
Tests/RunCMake/add_library/OBJECTwithNoSources-stderr.txt

@@ -1,2 +1,4 @@
-^You have called ADD_LIBRARY for library TestObjectLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestObjectLibWithoutSources)*$
+^CMake Error at OBJECTwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestObjectLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 1 - 2
Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt

@@ -1,5 +1,4 @@
-^You have called ADD_LIBRARY for library TestObjectLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file
-CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
+^CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
   Object library target \"TestObjectLibWithoutSources\" may not link to
   Object library target \"TestObjectLibWithoutSources\" may not link to
   anything.
   anything.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):

+ 1 - 2
Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt

@@ -1,5 +1,4 @@
-^You have called ADD_LIBRARY for library TestObjectLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file
-CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
+^CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
   OBJECT library \"TestObjectLibWithoutSources\" contains:
   OBJECT library \"TestObjectLibWithoutSources\" contains:
 
 
     [^
     [^

+ 4 - 3
Tests/RunCMake/add_library/SHAREDwithNoSources-stderr.txt

@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestSharedLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestSharedLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestSharedLibWithoutSources\".)*$
+^CMake Error at SHAREDwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestSharedLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 4 - 3
Tests/RunCMake/add_library/SHAREDwithNoSourcesButLinkObjects-stderr.txt

@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestSharedLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestSharedLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestSharedLibWithoutSources\".)*$
+^CMake Error at SHAREDwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestSharedLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 0 - 1
Tests/RunCMake/add_library/SHAREDwithOnlyObjectSources-stderr.txt

@@ -1 +0,0 @@
-^You have called ADD_LIBRARY for library TestSharedLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file$

+ 4 - 3
Tests/RunCMake/add_library/STATICwithNoSources-stderr.txt

@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestStaticLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: Cannot determine link language for target \"TestStaticLibWithoutSources\".)?(
-CMake Error: CMake can not determine linker language for target: TestStaticLibWithoutSources)+$
+^CMake Error at STATICwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestStaticLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 4 - 3
Tests/RunCMake/add_library/STATICwithNoSourcesButLinkObjects-stderr.txt

@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestStaticLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: Cannot determine link language for target \"TestStaticLibWithoutSources\".)?(
-CMake Error: CMake can not determine linker language for target: TestStaticLibWithoutSources)+$
+^CMake Error at STATICwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestStaticLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 0 - 1
Tests/RunCMake/add_library/STATICwithOnlyObjectSources-stderr.txt

@@ -1 +0,0 @@
-^You have called ADD_LIBRARY for library TestStaticLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file$