Merge topic 'export-empty-args'

2151e5f79d export, install: Improve argument parsing
2e71df0156 export: Explicitly allow empty NAMESPACE
5564c2cd9a cmArgumentParser: Improve bad argument handling
3f38f9511b cmArgumentParser: Add support for MaybeEmpty<std::string>
1ec7201558 cmStringAlgorithms: Add cmStripWhitespace
2ca58c5ac9 set: Improve error message consistency

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !11472
This commit is contained in:
Brad King
2025-12-10 14:37:24 +00:00
committed by Kitware Robot
39 changed files with 461 additions and 42 deletions

View File

@@ -100,6 +100,7 @@ Policies Introduced by CMake 4.3
.. toctree::
:maxdepth: 1
CMP0208: export(EXPORT) does not allow empty arguments. </policy/CMP0208>
CMP0207: file(GET_RUNTIME_DEPENDENCIES) normalizes paths before matching. </policy/CMP0207>
CMP0206: The CPack Archive Generator defaults to UID 0 and GID 0. </policy/CMP0206>
CMP0205: file(CREATE_LINK) with COPY_ON_ERROR copies directory content. </policy/CMP0205>

30
Help/policy/CMP0208.rst Normal file
View File

@@ -0,0 +1,30 @@
CMP0208
-------
.. versionadded:: 4.3
:command:`export(EXPORT)` does not allow empty arguments.
In CMake 4.2 and below, the :command:`export(EXPORT)` command silently
accepted ``NAMESPACE``, ``FILE`` or ``CXX_MODULES_DIRECTORY`` arguments with
empty or missing values.
CMake 4.3 and above issue a diagnostic if any of these keywords are present
without an associated value, or of the value given to ``FILE`` or
``CXX_MODULES_DIRECTORY`` is empty. (``NAMESPACE`` is allowed to have an empty
value, but an empty value must be quoted.) A diagnostic is also issued
immediately if the value of ``EXPORT`` is missing or empty. (Previously, this
would result in an error at generate-time because no export set whose name is
empty can exist.)
This policy provides compatibility with projects which may have relied on the
previous lack of enforcement. The ``OLD`` behavior for this policy permits
these keywords to be present without an accompanying value, or to be given an
empty value. The ``NEW`` behavior requires that a value be given, and that
the value (except for ``NAMESPACE``) is non-empty.
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.3
.. |WARNS_OR_DOES_NOT_WARN| replace:: warns
.. include:: include/STANDARD_ADVICE.rst
.. include:: include/DEPRECATED.rst

View File

@@ -0,0 +1,5 @@
export-empty-args
-----------------
* The :command:`export(EXPORT)` command no longer allows certain
arguments to be missing or empty. See policy :policy:`CMP0208`.

View File

@@ -5,6 +5,7 @@
#include <algorithm>
#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
@@ -72,6 +73,16 @@ void Instance::Bind(std::string& val)
ExpectAtLeast{ 1 });
}
void Instance::Bind(MaybeEmpty<std::string>& val)
{
this->Bind(
[&val](cm::string_view arg) -> Continue {
val = std::string(arg);
return Continue::No;
},
ExpectAtLeast{ 1 });
}
void Instance::Bind(NonEmpty<std::string>& val)
{
this->Bind(
@@ -204,11 +215,41 @@ bool ParseResult::MaybeReportError(cmMakefile& mf) const
return false;
}
std::string e;
for (auto const& ke : this->KeywordErrors) {
e = cmStrCat(e, "Error after keyword \"", ke.first, "\":\n", ke.second);
for (auto const& kel : this->KeywordErrors) {
e = cmStrCat(e, "Error after keyword \"", kel.first, "\":\n");
for (auto const& ke : kel.second) {
e += ke;
}
}
mf.IssueMessage(MessageType::FATAL_ERROR, e);
return true;
}
bool ParseResult::Check(cm::string_view context,
std::vector<std::string> const* unparsedArguments,
cmExecutionStatus& status) const
{
if (unparsedArguments && !unparsedArguments->empty()) {
status.SetError(cmStrCat(context, " given unknown argument: \""_s,
unparsedArguments->front(), "\"."_s));
return false;
}
if (!this->KeywordErrors.empty()) {
std::string msg = cmStrCat(
context, (context.empty() ? ""_s : " "_s), "given invalid "_s,
(this->KeywordErrors.size() > 1 ? "arguments:"_s : "argument:"_s));
for (auto const& kel : this->KeywordErrors) {
for (auto const& ke : kel.second) {
msg =
cmStrCat(msg, "\n "_s, kel.first, ": "_s, cmStripWhitespace(ke));
}
}
status.SetError(msg);
return false;
}
return true;
}
} // namespace ArgumentParser

View File

@@ -8,6 +8,7 @@
#include <cstddef>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -23,13 +24,17 @@
template <typename Result>
class cmArgumentParser; // IWYU pragma: keep
class cmExecutionStatus;
class cmMakefile;
namespace ArgumentParser {
class ParseResult
{
std::map<cm::string_view, std::string> KeywordErrors;
using KeywordErrorList = std::set<std::string>;
using KeywordErrorMap = std::map<cm::string_view, KeywordErrorList>;
KeywordErrorMap KeywordErrors;
public:
explicit operator bool() const { return this->KeywordErrors.empty(); }
@@ -37,15 +42,21 @@ public:
void AddKeywordError(cm::string_view key, cm::string_view text)
{
this->KeywordErrors[key] += text;
this->KeywordErrors[key].emplace(text);
}
std::map<cm::string_view, std::string> const& GetKeywordErrors() const
KeywordErrorMap const& GetKeywordErrors() const
{
return this->KeywordErrors;
}
bool MaybeReportError(cmMakefile& mf) const;
/// Check if argument parsing succeeded. Return \c false and set an error if
/// any errors were encountered, or if \p unparsedArguments is non-empty.
bool Check(cm::string_view context,
std::vector<std::string> const* unparsedArguments,
cmExecutionStatus& status) const;
};
template <typename Result>
@@ -212,6 +223,7 @@ public:
void Bind(std::function<Continue(cm::string_view)> f, ExpectAtLeast expect);
void Bind(bool& val);
void Bind(std::string& val);
void Bind(MaybeEmpty<std::string>& val);
void Bind(NonEmpty<std::string>& val);
void Bind(Maybe<std::string>& val);
void Bind(MaybeEmpty<std::vector<std::string>>& val);

View File

@@ -36,6 +36,12 @@ struct MaybeEmpty<std::vector<T>> : public std::vector<T>
using std::vector<T>::vector;
using std::vector<T>::operator=;
};
template <>
struct MaybeEmpty<std::string> : public std::string
{
using std::string::basic_string;
using std::string::operator=;
};
template <typename T>
struct NonEmpty;

View File

@@ -210,10 +210,10 @@ static bool HandleTargetsMode(std::vector<std::string> const& args,
static bool HandleExportMode(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
struct ExportArguments
struct ExportArguments : public ArgumentParser::ParseResult
{
ArgumentParser::NonEmpty<std::string> ExportSetName;
ArgumentParser::NonEmpty<std::string> Namespace;
ArgumentParser::MaybeEmpty<std::string> Namespace;
ArgumentParser::NonEmpty<std::string> Filename;
ArgumentParser::NonEmpty<std::string> CxxModulesDirectory;
cm::optional<cmPackageInfoArguments> PackageInfo;
@@ -249,12 +249,23 @@ static bool HandleExportMode(std::vector<std::string> const& args,
cmMakefile& mf = status.GetMakefile();
cmGlobalGenerator* gg = mf.GetGlobalGenerator();
if (arguments.PackageInfo) {
if (arguments.PackageInfo->PackageName.empty()) {
// TODO: Fix our use of the parser to enforce this.
status.SetError("PACKAGE_INFO missing required value.");
if (!arguments.Check(args[0], &unknownArgs, status)) {
cmPolicies::PolicyStatus const p =
status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0208);
if (arguments.PackageInfo || !unknownArgs.empty() ||
p == cmPolicies::NEW) {
return false;
}
if (p == cmPolicies::WARN) {
status.GetMakefile().IssueMessage(
MessageType::AUTHOR_WARNING, cmStrCat("export "_s, status.GetError()));
status.GetMakefile().IssueMessage(
MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0208));
}
}
if (arguments.PackageInfo) {
if (!arguments.Filename.empty()) {
status.SetError("PACKAGE_INFO and FILE are mutually exclusive.");
return false;
@@ -269,12 +280,6 @@ static bool HandleExportMode(std::vector<std::string> const& args,
}
}
if (!unknownArgs.empty()) {
status.SetError("EXPORT given unknown argument: \"" + unknownArgs.front() +
"\".");
return false;
}
std::string fname;
if (arguments.Filename.empty()) {
if (arguments.PackageInfo) {

View File

@@ -2340,12 +2340,9 @@ bool HandlePackageInfoMode(std::vector<std::string> const& args,
// ica.Bind("CXX_MODULES_DIRECTORY"_s, cxxModulesDirectory); TODO?
std::vector<std::string> unknownArgs;
ica.Parse(args, &unknownArgs);
ArgumentParser::ParseResult result = ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
status.SetError(
cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
if (!result.Check(args[0], &unknownArgs, status)) {
return false;
}
@@ -2353,12 +2350,6 @@ bool HandlePackageInfoMode(std::vector<std::string> const& args,
return false;
}
if (arguments.PackageName.empty()) {
// TODO: Fix our use of the parser to enforce this.
status.SetError(cmStrCat(args[0], " missing package name."));
return false;
}
if (exportName.empty()) {
status.SetError(cmStrCat(args[0], " missing EXPORT."));
return false;

View File

@@ -621,6 +621,8 @@ class cmMakefile;
WARN) \
SELECT(POLICY, CMP0207, \
"file(GET_RUNTIME_DEPENDENCIES) normalizes paths before matching.", \
4, 3, 0, WARN) \
SELECT(POLICY, CMP0208, "export(EXPORT) does not allow empty arguments.", \
4, 3, 0, WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)

View File

@@ -98,8 +98,8 @@ bool cmSetCommand(std::vector<std::string> const& args,
{
if (!cmState::StringToCacheEntryType(std::string{ type },
this->Type)) {
this->AddKeywordError("TYPE"_s,
cmStrCat("Invalid value: ", type, '.'));
this->AddKeywordError(
"TYPE"_s, cmStrCat(" invalid value: \""_s, type, "\"\n"_s));
}
return ArgumentParser::Continue::No;
}

View File

@@ -38,6 +38,24 @@ std::string cmTrimWhitespace(cm::string_view str)
return std::string(start, stop + 1);
}
cm::string_view cmStripWhitespace(cm::string_view str)
{
std::string::size_type const l = str.size();
std::string::size_type s = 0;
while (s < l && cmIsSpace(str[s])) {
++s;
}
if (s == l) {
return cm::string_view{};
}
std::string::size_type e = l - 1;
while (cmIsSpace(str[e])) {
--e;
}
return str.substr(s, e + 1 - s);
}
std::string cmRemoveQuotes(cm::string_view str)
{
// We process only strings that have two quotes at least.

View File

@@ -62,6 +62,12 @@ inline bool cmIsSpace(char ch)
/** Returns a string that has whitespace removed from the start and the end. */
std::string cmTrimWhitespace(cm::string_view str);
/**
* Returns a string view that has whitespace removed from the start and the
* end.
*/
cm::string_view cmStripWhitespace(cm::string_view str);
/** Returns a string that has quotes removed from the start and the end. */
std::string cmRemoveQuotes(cm::string_view str);

View File

@@ -2,6 +2,7 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -294,7 +295,8 @@ bool verifyResult(Result const& result,
for (auto const& ke : result.GetKeywordErrors()) {
auto const ki = keywordErrors.find(ke.first);
ASSERT_TRUE(ki != keywordErrors.end());
ASSERT_TRUE(ke.second == ki->second);
ASSERT_TRUE(ke.second.size() == 1);
ASSERT_TRUE(*ke.second.begin() == ki->second);
}
return true;

View File

@@ -1,4 +1,6 @@
CMake Error at BadArgs0\.cmake:3 \(export\):
export PACKAGE_INFO missing required value\.
CMake Error at BadArgs0\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
PACKAGE_INFO: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,95 @@
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
APPENDIX: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
VERSION: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
COMPAT_VERSION: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
VERSION_SCHEMA: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
LICENSE: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
DEFAULT_LICENSE: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
DESCRIPTION: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
HOMEPAGE_URL: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
DEFAULT_TARGETS: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
DEFAULT_CONFIGURATIONS: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
PROJECT: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs5\.cmake:[0-9]+ \(export\):
export EXPORT given invalid arguments:
DEFAULT_LICENSE: empty string not allowed
LICENSE: empty string not allowed
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1,15 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
set(args EXPORT foo PACKAGE_INFO foo)
export(${args} APPENDIX)
export(${args} VERSION)
export(${args} COMPAT_VERSION)
export(${args} VERSION_SCHEMA)
export(${args} LICENSE)
export(${args} DEFAULT_LICENSE)
export(${args} DESCRIPTION)
export(${args} HOMEPAGE_URL)
export(${args} DEFAULT_TARGETS)
export(${args} DEFAULT_CONFIGURATIONS)
export(${args} PROJECT)
export(${args} LICENSE "" DEFAULT_LICENSE "")

View File

@@ -3,7 +3,7 @@ add_library(bar foo.cxx)
target_link_libraries(bar foo)
install(TARGETS foo EXPORT foo)
export(EXPORT foo NAMESPACE ${NAMESPACE})
export(EXPORT foo NAMESPACE "${NAMESPACE}")
export(EXPORT foo PACKAGE_INFO foo)
install(TARGETS bar EXPORT bar)

View File

@@ -21,6 +21,7 @@ run_cmake(BadArgs1)
run_cmake(BadArgs2)
run_cmake(BadArgs3)
run_cmake(BadArgs4)
run_cmake(BadArgs5)
run_cmake(BadName)
run_cmake(DuplicateOutput)
run_cmake(BadDefaultTarget)

View File

@@ -1,22 +1,28 @@
CMake Error at BadArgs0\.cmake:1 \(install\):
install PACKAGE_INFO missing package name\.
CMake Error at BadArgs0\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
PACKAGE_INFO: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs0\.cmake:2 \(install\):
CMake Error at BadArgs0\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO missing EXPORT\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs0\.cmake:3 \(install\):
install PACKAGE_INFO missing EXPORT\.
CMake Error at BadArgs0\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
EXPORT: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs0\.cmake:7 \(install\):
install PACKAGE_INFO missing package name\.
CMake Error at BadArgs0\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
PACKAGE_INFO: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,95 @@
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
APPENDIX: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
VERSION: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
COMPAT_VERSION: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
VERSION_SCHEMA: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
LICENSE: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
DEFAULT_LICENSE: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
DESCRIPTION: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
HOMEPAGE_URL: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
DEFAULT_TARGETS: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
DEFAULT_CONFIGURATIONS: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid argument:
PROJECT: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:[0-9]+ \(install\):
install PACKAGE_INFO given invalid arguments:
DEFAULT_LICENSE: empty string not allowed
LICENSE: empty string not allowed
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1,15 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
set(args PACKAGE_INFO test EXPORT foo)
install(${args} APPENDIX)
install(${args} VERSION)
install(${args} COMPAT_VERSION)
install(${args} VERSION_SCHEMA)
install(${args} LICENSE)
install(${args} DEFAULT_LICENSE)
install(${args} DESCRIPTION)
install(${args} HOMEPAGE_URL)
install(${args} DEFAULT_TARGETS)
install(${args} DEFAULT_CONFIGURATIONS)
install(${args} PROJECT)
install(${args} LICENSE "" DEFAULT_LICENSE "")

View File

@@ -32,6 +32,7 @@ endfunction()
run_cmake(BadArgs0)
run_cmake(BadArgs1)
run_cmake(BadArgs2)
run_cmake(BadArgs3)
run_cmake(BadName)
run_cmake(BadDefaultTarget)
run_cmake(ReferencesNonExportedTarget)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,6 @@
CMake Error at EmptyExport-CMP0208-NEW\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
EXPORT: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1,3 @@
cmake_policy(SET CMP0208 NEW)
export(EXPORT)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,4 @@
CMake Error at EmptyExport-CMP0208-OLD\.cmake:[0-9]+ \(export\):
export Export set "" not found\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1,3 @@
cmake_policy(SET CMP0208 OLD)
export(EXPORT)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,6 @@
CMake Error at EmptyExportFile-CMP0208-NEW\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
FILE: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1,6 @@
cmake_policy(SET CMP0208 NEW)
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo)
export(EXPORT foo FILE)

View File

@@ -0,0 +1,6 @@
cmake_policy(SET CMP0208 OLD)
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo)
export(EXPORT foo FILE)

View File

@@ -0,0 +1,15 @@
CMake Warning \(dev\) at EmptyExportFile-CMP0208-WARN\.cmake:[0-9]+ \(export\):
export EXPORT given invalid argument:
FILE: missing required value
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.
CMake Warning \(dev\) at EmptyExportFile-CMP0208-WARN\.cmake:[0-9]+ \(export\):
Policy CMP0208 is not set: export\(EXPORT\) does not allow empty arguments\.
Run "cmake --help-policy CMP0208" for policy details\. Use the cmake_policy
command to set the policy and suppress this warning\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.

View File

@@ -0,0 +1,4 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo)
export(EXPORT foo FILE)

View File

@@ -0,0 +1,5 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo)
# Ensure we can export with an explicitly-empty namespace.
export(EXPORT foo NAMESPACE "")

View File

@@ -1,5 +1,11 @@
include(RunCMake)
run_cmake(EmptyExport-CMP0208-OLD)
run_cmake(EmptyExport-CMP0208-NEW)
run_cmake(EmptyExportFile-CMP0208-WARN)
run_cmake(EmptyExportFile-CMP0208-OLD)
run_cmake(EmptyExportFile-CMP0208-NEW)
run_cmake(EmptyNamespace)
run_cmake(CustomTarget)
run_cmake(Empty)
run_cmake(Repeat-CMP0103-WARN)

View File

@@ -1,6 +1,7 @@
CMake Error at CacheWrongTYPE\.cmake:[0-9]+ \(set\):
Error after keyword "TYPE":
Invalid value: FOO\.
invalid value: "FOO"
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)