Link step: Add LINK_WARNING_AS_ERROR target property

Add a way to specify, in a portable way, to raise an error for any
warning during the link step. For that purpose, define:
* CMAKE_LINK_WARNING_AS_ERROR variable
* LINK_WARNING_AS_ERROR target property

Fixes: #25343
This commit is contained in:
Marc Chevrier
2024-11-06 11:53:59 +01:00
parent 656267c871
commit 7907c83175
58 changed files with 421 additions and 28 deletions

View File

@@ -342,6 +342,7 @@ Properties on Targets
/prop_tgt/LINK_OPTIONS
/prop_tgt/LINK_SEARCH_END_STATIC
/prop_tgt/LINK_SEARCH_START_STATIC
/prop_tgt/LINK_WARNING_AS_ERROR
/prop_tgt/LINK_WHAT_YOU_USE
/prop_tgt/LINKER_LANGUAGE
/prop_tgt/LINKER_TYPE

View File

@@ -499,6 +499,7 @@ Variables that Control the Build
/variable/CMAKE_LINK_LIBRARY_FLAG
/variable/CMAKE_LINK_LIBRARY_USING_FEATURE
/variable/CMAKE_LINK_LIBRARY_USING_FEATURE_SUPPORTED
/variable/CMAKE_LINK_WARNING_AS_ERROR
/variable/CMAKE_LINK_WHAT_YOU_USE
/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK
/variable/CMAKE_LINKER_TYPE

View File

@@ -513,6 +513,14 @@ Options
:variable:`CMAKE_COMPILE_WARNING_AS_ERROR`, preventing warnings from being
treated as errors on compile.
.. option:: --link-no-warning-as-error
.. versionadded:: 3.32
Ignore target property :prop_tgt:`LINK_WARNING_AS_ERROR` and variable
:variable:`CMAKE_LINK_WARNING_AS_ERROR`, preventing warnings from being
treated as errors on link.
.. option:: --profiling-output=<path>
.. versionadded:: 3.18

View File

@@ -0,0 +1,27 @@
LINK_WARNING_AS_ERROR
---------------------
.. versionadded:: 3.32
Specify whether to treat warnings on link as errors.
If enabled, adds a flag to treat warnings on link as errors.
If the :option:`cmake --link-no-warning-as-error` option is given
on the :manual:`cmake(1)` command line, this property is ignored.
This property is not implemented for all linkers. It is silently ignored
if there is no implementation for the linker being used. The currently
implemented :variable:`compiler linker IDs <CMAKE_<LANG>_COMPILER_LINKER_ID>`
are:
* ``AIX``
* ``AppleClang``
* ``GNU``
* ``GNUgold``
* ``LLD``
* ``MOLD``
* ``MSVC``
* ``Solaris``
This property is initialized by the value of the variable
:variable:`CMAKE_LINK_WARNING_AS_ERROR` if it is set when a target is
created.

View File

@@ -0,0 +1,11 @@
link-warning-as-error
---------------------
* The :variable:`CMAKE_LINK_WARNING_AS_ERROR` variable and corresponding
:prop_tgt:`LINK_WARNING_AS_ERROR` target property were added to enable
link with a linker-specific flag to treat warnings as errors.
* The :manual:`cmake(1)` command line gained the
:option:`--link-no-warning-as-error <cmake --link-no-warning-as-error>`
option which causes the effects of the :prop_tgt:`LINK_WARNING_AS_ERROR`
target property and :variable:`CMAKE_LINK_WARNING_AS_ERROR` variable to be
ignored.

View File

@@ -0,0 +1,9 @@
CMAKE_LINK_WARNING_AS_ERROR
---------------------------
.. versionadded:: 3.32
Specify whether to treat warnings on link as errors.
This variable is used to initialize the
:prop_tgt:`LINK_WARNING_AS_ERROR` property on all the targets.

View File

@@ -6,4 +6,6 @@
include_guard()
macro(__linker_aix lang)
# Linker warning as error
set(CMAKE_${lang}_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:-bhalt:0")
endmacro()

View File

@@ -7,4 +7,6 @@
include_guard()
macro(__linker_appleclang lang)
# Linker warning as error
set(CMAKE_${lang}_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:-fatal_warnings")
endmacro()

View File

@@ -65,10 +65,14 @@ function(__linker_gnu lang)
set(CMAKE_${lang}_LINK_DEPENDS_USE_LINKER FALSE)
endif()
# Linker warning as error
set(CMAKE_${lang}_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:--fatal-warnings")
return(PROPAGATE CMAKE_${lang}_LINKER_DEPFILE_FLAGS
CMAKE_${lang}_LINKER_DEPFILE_FORMAT
CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED
CMAKE_${lang}_LINK_DEPENDS_USE_LINKER)
CMAKE_${lang}_LINK_DEPENDS_USE_LINKER
CMAKE_${lang}_LINK_OPTIONS_WARNING_AS_ERROR)
endfunction()
endblock()

View File

@@ -3,8 +3,20 @@
include_guard()
include(Linker/GNU)
block(SCOPE_FOR POLICIES)
cmake_policy(SET CMP0054 NEW)
macro(__linker_lld lang)
__linker_gnu(${lang})
if(CMAKE_${lang}_COMPILER_LINKER_FRONTEND_VARIANT STREQUAL "MSVC")
include(Linker/MSVC)
__linker_msvc(${lang})
else()
include(Linker/GNU)
__linker_gnu(${lang})
endif()
endmacro()
endblock()

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(ASM)
__linker_mold(ASM)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(C)
__linker_mold(C)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(CUDA)
__linker_mold(CUDA)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(CXX)
__linker_mold(CXX)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(Fortran)
__linker_mold(Fortran)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(HIP)
__linker_mold(HIP)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(OBJC)
__linker_mold(OBJC)

View File

@@ -1,6 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/GNU)
include(Linker/MOLD)
__linker_gnu(OBJCXX)
__linker_mold(OBJCXX)

23
Modules/Linker/MOLD.cmake Normal file
View File

@@ -0,0 +1,23 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# This module is shared by multiple linkers; use include blocker.
include_guard()
block(SCOPE_FOR POLICIES)
cmake_policy(SET CMP0054 NEW)
macro(__linker_mold lang)
if(CMAKE_EFFECTIVE_SYSTEM_NAME STREQUAL "Apple")
include(Linker/AppleClang)
__linker_appleclang(${lang})
else()
include(Linker/GNU)
__linker_gnu(${lang})
endif()
endmacro()
endblock()

View File

@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/MSVC)
__linker_msvc(ASM)

View File

@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/MSVC)
__linker_msvc(C)

View File

@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/MSVC)
__linker_msvc(CUDA)

View File

@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/MSVC)
__linker_msvc(CXX)

View File

@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/MSVC)
__linker_msvc(Fortran)

View File

@@ -0,0 +1,6 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(Linker/MSVC)
__linker_msvc(HIP)

12
Modules/Linker/MSVC.cmake Normal file
View File

@@ -0,0 +1,12 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# This module is shared by multiple linkers; use include blocker.
include_guard()
macro(__linker_msvc lang)
# Linker warning as error
set(CMAKE_${lang}_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:/WX")
endmacro()

View File

@@ -6,4 +6,6 @@
include_guard()
macro(__linker_solaris lang)
# Linker warning as error
set(CMAKE_${lang}_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:-z,fatal-warnings")
endmacro()

View File

@@ -3069,6 +3069,9 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache(
if (this->GetCMakeInstance()->GetIgnoreCompileWarningAsError()) {
singleLine.push_back("--compile-no-warning-as-error");
}
if (this->GetCMakeInstance()->GetIgnoreLinkWarningAsError()) {
singleLine.push_back("--link-no-warning-as-error");
}
singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
gti.Message = "Running CMake cache editor...";
@@ -3105,6 +3108,9 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
if (this->GetCMakeInstance()->GetIgnoreCompileWarningAsError()) {
singleLine.push_back("--compile-no-warning-as-error");
}
if (this->GetCMakeInstance()->GetIgnoreLinkWarningAsError()) {
singleLine.push_back("--link-no-warning-as-error");
}
singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
gti.CommandLines.push_back(std::move(singleLine));

View File

@@ -1958,6 +1958,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
this->CMakeCmd(), " --regenerate-during-build",
cm->GetIgnoreCompileWarningAsError() ? " --compile-no-warning-as-error"
: "",
cm->GetIgnoreLinkWarningAsError() ? " --link-no-warning-as-error" : "",
" -S",
lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
cmOutputConverter::SHELL),

View File

@@ -328,6 +328,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
if (cm->GetIgnoreCompileWarningAsError()) {
commandLines[0].emplace_back("--compile-no-warning-as-error");
}
if (cm->GetIgnoreLinkWarningAsError()) {
commandLines[0].emplace_back("--link-no-warning-as-error");
}
// Add the rule. Note that we cannot use the CMakeLists.txt
// file as the main dependency because it would get

View File

@@ -777,14 +777,14 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
}
makefileStream << ConvertToMakefilePath(checkCache) << ": $(TARGETS)\n";
makefileStream << '\t'
<< ConvertToMakefilePath(cmSystemTools::GetCMakeCommand())
<< " -S" << ConvertToMakefilePath(root->GetSourceDirectory())
<< " -B" << ConvertToMakefilePath(root->GetBinaryDirectory())
<< (cm->GetIgnoreCompileWarningAsError()
? " --compile-no-warning-as-error"
: "")
<< '\n';
makefileStream
<< '\t' << ConvertToMakefilePath(cmSystemTools::GetCMakeCommand()) << " -S"
<< ConvertToMakefilePath(root->GetSourceDirectory()) << " -B"
<< ConvertToMakefilePath(root->GetBinaryDirectory())
<< (cm->GetIgnoreCompileWarningAsError() ? " --compile-no-warning-as-error"
: "")
<< (cm->GetIgnoreLinkWarningAsError() ? " --link-no-warning-as-error" : "")
<< '\n';
}
static bool objectIdLessThan(const std::unique_ptr<cmXCodeObject>& l,
@@ -2551,6 +2551,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
} else {
this->CurrentLocalGenerator->AppendLinkerTypeFlags(extraLinkOptions, gtgt,
configName, llang);
this->CurrentLocalGenerator->AppendWarningAsErrorLinkerFlags(
extraLinkOptions, gtgt, llang);
cmValue targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {

View File

@@ -1675,6 +1675,7 @@ void cmLocalGenerator::GetTargetFlags(
this->AppendLinkerTypeFlags(extraLinkFlags, target, config, linkLanguage);
this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config,
linkLanguage);
this->AppendWarningAsErrorLinkerFlags(extraLinkFlags, target, linkLanguage);
this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage);
this->AppendDependencyInfoLinkerFlags(extraLinkFlags, target, config,
linkLanguage);
@@ -3609,6 +3610,34 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
}
}
void cmLocalGenerator::AppendWarningAsErrorLinkerFlags(
std::string& flags, cmGeneratorTarget* target, const std::string& lang)
{
if (this->GetCMakeInstance()->GetIgnoreLinkWarningAsError()) {
return;
}
switch (target->GetType()) {
case cmStateEnums::EXECUTABLE:
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
break;
default:
return;
}
const auto wError = target->GetProperty("LINK_WARNING_AS_ERROR");
const auto wErrorOpts = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_LINK_OPTIONS_WARNING_AS_ERROR"));
if (wError.IsOn() && wErrorOpts.IsSet()) {
auto items = cmExpandListWithBacktrace(wErrorOpts, target->GetBacktrace());
target->ResolveLinkerWrapper(items, lang);
for (const auto& item : items) {
this->AppendFlagEscape(flags, item.Value);
}
}
}
void cmLocalGenerator::AppendDependencyInfoLinkerFlags(
std::string& flags, cmGeneratorTarget* target, const std::string& config,
const std::string& linkLanguage)

View File

@@ -185,6 +185,9 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
void AppendWarningAsErrorLinkerFlags(std::string& flags,
cmGeneratorTarget* target,
const std::string& lang);
void AppendDependencyInfoLinkerFlags(std::string& flags,
cmGeneratorTarget* target,
const std::string& config,

View File

@@ -831,6 +831,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
"$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) ",
cm->GetIgnoreCompileWarningAsError() ? "--compile-no-warning-as-error "
: "",
cm->GetIgnoreLinkWarningAsError() ? "--link-no-warning-as-error " : "",
"--check-build-system ",
this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
" 0");
@@ -1834,6 +1835,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
"$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) ",
cm->GetIgnoreCompileWarningAsError() ? "--compile-no-warning-as-error "
: "",
cm->GetIgnoreLinkWarningAsError() ? "--link-no-warning-as-error " : "",
"--check-build-system ",
this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
" 1");

View File

@@ -262,6 +262,9 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
if (cm->GetIgnoreCompileWarningAsError()) {
commandLines[0].emplace_back("--compile-no-warning-as-error");
}
if (cm->GetIgnoreLinkWarningAsError()) {
commandLines[0].emplace_back("--link-no-warning-as-error");
}
std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
auto cc = cm::make_unique<cmCustomCommand>();
cc->SetOutputs(stampName);
@@ -1007,6 +1010,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
// LINK_OPTIONS are escaped.
this->AppendCompileOptions(extraLinkOptions, opts);
this->AppendWarningAsErrorLinkerFlags(extraLinkOptions, target,
linkLanguage);
Options linkOptions(this, Options::Linker);
if (this->FortranProject) {
linkOptions.AddTable(cmLocalVisualStudio7GeneratorFortranLinkFlagTable);

View File

@@ -158,6 +158,8 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
this->LocalGenerator->AppendPositionIndependentLinkerFlags(
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
this->LocalGenerator->AppendWarningAsErrorLinkerFlags(
flags, this->GeneratorTarget, linkLanguage);
this->LocalGenerator->AppendDependencyInfoLinkerFlags(
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
}

View File

@@ -466,6 +466,7 @@ TargetProperty const StaticTargetProperties[] = {
// Linking properties
{ "LINKER_TYPE"_s, IC::CanCompileSources },
{ "LINK_WARNING_AS_ERROR"_s, IC::CanCompileSources },
{ "ENABLE_EXPORTS"_s, IC::TargetWithSymbolExports },
{ "LINK_LIBRARIES_ONLY_TARGETS"_s, IC::NormalNonImportedTarget },
{ "LINK_LIBRARIES_STRATEGY"_s, IC::NormalNonImportedTarget },

View File

@@ -4448,6 +4448,9 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
// LINK_OPTIONS are escaped.
this->LocalGenerator->AppendCompileOptions(flags, opts);
this->LocalGenerator->AppendWarningAsErrorLinkerFlags(
flags, this->GeneratorTarget, linkLanguage);
cmComputeLinkInformation* pcli =
this->GeneratorTarget->GetLinkInformation(config);
if (!pcli) {

View File

@@ -1244,6 +1244,14 @@ void cmake::SetArgs(const std::vector<std::string>& args)
state->SetIgnoreCompileWarningAsError(true);
return true;
} },
CommandArgument{
"--link-no-warning-as-error", CommandArgument::Values::Zero,
[](std::string const&, cmake* state) -> bool {
std::cout << "Ignoring LINK_WARNING_AS_ERROR target property and "
"CMAKE_LINK_WARNING_AS_ERROR variable.\n";
state->SetIgnoreLinkWarningAsError(true);
return true;
} },
CommandArgument{ "--debugger", CommandArgument::Values::Zero,
[](std::string const&, cmake* state) -> bool {
#ifdef CMake_ENABLE_DEBUGGER

View File

@@ -550,6 +550,14 @@ public:
{
this->IgnoreCompileWarningAsError = b;
}
bool GetIgnoreLinkWarningAsError() const
{
return this->IgnoreLinkWarningAsError;
}
void SetIgnoreLinkWarningAsError(bool b)
{
this->IgnoreLinkWarningAsError = b;
}
void MarkCliAsUsed(const std::string& variable);
@@ -760,6 +768,7 @@ private:
bool WarnUnusedCli = true;
bool CheckSystemVars = false;
bool IgnoreCompileWarningAsError = false;
bool IgnoreLinkWarningAsError = false;
std::map<std::string, bool> UsedCliVariables;
std::string CMakeEditCommand;
std::string CXXEnvironment;

View File

@@ -71,7 +71,7 @@ const cmDocumentationEntry cmDocumentationUsageNote = {
"Run 'cmake --help' for more information."
};
const cmDocumentationEntry cmDocumentationOptions[34] = {
const cmDocumentationEntry cmDocumentationOptions[35] = {
{ "--preset <preset>,--preset=<preset>", "Specify a configure preset." },
{ "--list-presets[=<type>]", "List available presets." },
{ "--workflow [<options>]", "Run a workflow preset." },
@@ -123,6 +123,9 @@ const cmDocumentationEntry cmDocumentationOptions[34] = {
{ "--compile-no-warning-as-error",
"Ignore COMPILE_WARNING_AS_ERROR property and "
"CMAKE_COMPILE_WARNING_AS_ERROR variable." },
{ "--link-no-warning-as-error",
"Ignore LINK_WARNING_AS_ERROR property and "
"CMAKE_LINK_WARNING_AS_ERROR variable." },
{ "--profiling-format=<fmt>",
"Output data for profiling CMake scripts. Supported formats: "
"google-trace" },

View File

@@ -506,6 +506,12 @@ add_RunCMake_test(ToolchainFile)
add_RunCMake_test(find_dependency)
add_RunCMake_test(CompileDefinitions)
add_RunCMake_test(CompileWarningAsError -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|MSVC"
OR (CMAKE_SYSTEM_NAME MATCHES "Linux|Windows" AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
OR (CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_C_COMPILER_ID STREQUAL "SunPro")
OR (CMAKE_SYSTEM_NAME STREQUAL "AIX" AND CMAKE_C_COMPILER_ID STREQUAL "XL"))
add_RunCMake_test(LinkWarningAsError)
endif()
set_property(TEST RunCMake.CompileWarningAsError APPEND PROPERTY LABELS "CUDA")
add_RunCMake_test(CompileFeatures -DCMake_NO_C_STANDARD=${CMake_NO_C_STANDARD} -DCMake_NO_CXX_STANDARD=${CMake_NO_CXX_STANDARD})
add_RunCMake_test(Policy)

View File

@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.31...3.32)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@@ -0,0 +1,19 @@
include(RunCMake)
function(run_link_warn test)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_with_options(${test} ${ARGN})
set(RunCMake_TEST_NO_CLEAN 1)
if(ARGN MATCHES "--link-no-warning-as-error")
# Cause the build system to re-run CMake to verify that this option is preserved.
run_cmake_command(${test}-Touch ${CMAKE_COMMAND} -E touch_nocreate CMakeCache.txt)
endif()
run_cmake_command(${test}-Build ${CMAKE_COMMAND} --build . --verbose)
endfunction()
run_link_warn(WarnErrorOn1)
run_link_warn(WarnErrorOn2)
run_link_warn(WarnErrorOff1)
run_link_warn(WarnErrorOff2)
run_link_warn(WarnErrorOnIgnore "--link-no-warning-as-error")

View File

@@ -0,0 +1,20 @@
set(reference_file "${RunCMake_TEST_BINARY_DIR}/WARNING_AS_ERROR.txt")
if (NOT EXISTS "${reference_file}")
set (RunCMake_TEST_FAILED "${reference_file}: Reference file not found.")
return()
endif()
file(READ "${reference_file}" linker_WarnError)
if(NOT linker_WarnError STREQUAL "UNDEFINED")
if(WARNING_AS_ERROR)
# Add regex [^-] to avoid matching of MSVC compiler flag /WX-
if(NOT actual_stdout MATCHES "${linker_WarnError}[^-]")
set (RunCMake_TEST_FAILED "LINK_WARNING_AS_ERROR: flag is missing.")
endif()
else()
if(actual_stdout MATCHES "${linker_WarnError}[^-]")
set (RunCMake_TEST_FAILED "LINK_WARNING_AS_ERROR: flag unexpectedly present.")
endif()
endif()
endif()

View File

@@ -0,0 +1,54 @@
if(NOT CMAKE_C_LINK_OPTIONS_WARNING_AS_ERROR)
set(linker_WarnError "UNDEFINED")
else()
set(cfg_dir)
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(_isMultiConfig)
set(cfg_dir /Debug)
endif()
set(DUMP_EXE "${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}/dump${CMAKE_EXECUTABLE_SUFFIX}")
add_executable(dump dump.c)
set_property(TARGET dump PROPERTY LINK_WARNING_AS_ERROR OFF)
# ensure no temp file nor response file will be used
set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
add_executable(main main.c)
if (NOT DEFINED CMAKE_LINK_WARNING_AS_ERROR)
set_property(TARGET main PROPERTY LINK_WARNING_AS_ERROR ${link_warning_as_error})
endif()
# use LAUNCH facility to dump linker command
set_property(TARGET main PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"")
add_dependencies(main dump)
# generate reference for WARNING_AS_ERROR flag
string(REPLACE "LINKER:" "" linker_WarnError "${CMAKE_C_LINK_OPTIONS_WARNING_AS_ERROR}")
if (CMAKE_C_LINKER_WRAPPER_FLAG)
set(linker_flag ${CMAKE_C_LINKER_WRAPPER_FLAG})
list(GET linker_flag -1 linker_space)
if (linker_space STREQUAL " ")
list(REMOVE_AT linker_flag -1)
else()
set(linker_space)
endif()
list(JOIN linker_flag " " linker_flag)
if (CMAKE_C_LINKER_WRAPPER_FLAG_SEP)
string(REPLACE "," "${CMAKE_C_LINKER_WRAPPER_FLAG_SEP}" linker_WarnError "${linker_WarnError}")
set(linker_WarnError "${linker_flag}${linker_space}${linker_WarnError}")
else()
set(linker_prefix "${linker_flag}${linker_space}")
string(REPLACE "," ";" linker_WarnError "${linker_WarnError}")
list(TRANSFORM linker_WarnError PREPEND "${linker_prefix}")
list(JOIN linker_WarnError " " linker_WarnError)
endif()
else()
string(REPLACE "," " " linker_WarnError "${linker_WarnError}")
endif()
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/WARNING_AS_ERROR.txt" "${linker_WarnError}")

View File

@@ -0,0 +1,4 @@
set(WARNING_AS_ERROR OFF)
include("${CMAKE_CURRENT_LIST_DIR}/WarnError-validation.cmake")

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(link_warning_as_error OFF)
include(WarnError.cmake)

View File

@@ -0,0 +1,4 @@
set(WARNING_AS_ERROR OFF)
include("${CMAKE_CURRENT_LIST_DIR}/WarnError-validation.cmake")

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(CMAKE_LINK_WARNING_AS_ERROR OFF)
include(WarnError.cmake)

View File

@@ -0,0 +1,4 @@
set(WARNING_AS_ERROR ON)
include("${CMAKE_CURRENT_LIST_DIR}/WarnError-validation.cmake")

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(link_warning_as_error ON)
include(WarnError.cmake)

View File

@@ -0,0 +1,4 @@
set(WARNING_AS_ERROR ON)
include("${CMAKE_CURRENT_LIST_DIR}/WarnError-validation.cmake")

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(CMAKE_LINK_WARNING_AS_ERROR ON)
include(WarnError.cmake)

View File

@@ -0,0 +1,4 @@
set(WARNING_AS_ERROR OFF)
include("${CMAKE_CURRENT_LIST_DIR}/WarnError-validation.cmake")

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(link_warning_as_error ON)
include(WarnError.cmake)

View File

@@ -0,0 +1,13 @@
#include "stdio.h"
int main(int argc, char* argv[])
{
int i;
for (i = 1; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
return 0;
}

View File

@@ -0,0 +1,5 @@
int main(void)
{
return 0;
}