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
This commit is contained in:
parent
6e4e7c6547
commit
4e7f67383f
@ -7,14 +7,15 @@ Add an executable to the project using the specified source files.
|
||||
|
||||
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
|
||||
[EXCLUDE_FROM_ALL]
|
||||
source1 [source2 ...])
|
||||
[source1] [source2 ...])
|
||||
|
||||
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
|
||||
directory corresponding to the source tree directory in which the
|
||||
|
@ -14,13 +14,14 @@ Normal Libraries
|
||||
|
||||
add_library(<name> [STATIC | SHARED | MODULE]
|
||||
[EXCLUDE_FROM_ALL]
|
||||
source1 [source2 ...])
|
||||
[source1] [source2 ...])
|
||||
|
||||
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``).
|
||||
|
||||
``STATIC``, ``SHARED``, or ``MODULE`` may be given to specify the type of
|
||||
|
6
Help/release/dev/defer-target-source-check.rst
Normal file
6
Help/release/dev/defer-target-source-check.rst
Normal file
@ -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`.
|
@ -18,7 +18,7 @@ class cmExecutionStatus;
|
||||
bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
|
||||
cmExecutionStatus&)
|
||||
{
|
||||
if (args.size() < 2) {
|
||||
if (args.empty()) {
|
||||
this->SetError("called with incorrect number of arguments");
|
||||
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());
|
||||
cmTarget* tgt =
|
||||
this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll);
|
||||
|
@ -362,14 +362,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
|
||||
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());
|
||||
|
||||
this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
|
||||
|
@ -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(
|
||||
const std::string& filename) const
|
||||
{
|
||||
@ -1292,6 +1329,11 @@ bool cmGlobalGenerator::Compute()
|
||||
localGen->TraceDependencies();
|
||||
}
|
||||
|
||||
// Make sure that all (non-imported) targets have source files added!
|
||||
if (this->CheckTargetsForMissingSources()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->ForceLinkerLanguages();
|
||||
|
||||
// Compute the manifest of main targets generated.
|
||||
|
@ -539,6 +539,8 @@ private:
|
||||
|
||||
virtual void ForceLinkerLanguages();
|
||||
|
||||
bool CheckTargetsForMissingSources() const;
|
||||
|
||||
void CreateLocalGenerators();
|
||||
|
||||
void CheckCompilerIdCompatibility(cmMakefile* mf,
|
||||
|
@ -1,4 +1,4 @@
|
||||
^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\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)$
|
||||
|
@ -1,11 +1,4 @@
|
||||
^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\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)$
|
||||
|
@ -1 +0,0 @@
|
||||
1
|
@ -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\)$
|
@ -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\)$
|
||||
|
@ -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\)$
|
||||
|
@ -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 @@
|
||||
.
|
||||
1
|
||||
|
@ -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,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
|
||||
anything.
|
||||
Call Stack \(most recent call first\):
|
||||
|
@ -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:
|
||||
|
||||
[^
|
||||
|
@ -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\)$
|
||||
|
@ -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\)$
|
||||
|
@ -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$
|
@ -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\)$
|
||||
|
@ -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\)$
|
||||
|
@ -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$
|
Loading…
Reference in New Issue
Block a user