[cmake-developers] CMake API for warnings
Ruslan Baratov
ruslan_baratov at yahoo.com
Wed Apr 20 09:50:54 EDT 2016
So here is a summary of this feature so far:
Introducing new 3 functions for controlling compiler warnings:
1) add_compile_warnings
* similar to add_definitions, add_compile_options
* modify COMPILE_WARNINGS directory property (append)
2) target_compile_warnings
* similar to target_compile_options, target_compile_definitions
* modify COMPILE_WARNINGS target property (append)
3) source_files_compile_warnings
* similar to set_source_files_properties
* modify COMPILE_WARNINGS sources property (append)
Same API for all:
*_compile_warnings(
<global/target/source>
DISABLE <warning-id> # add <warning-id>=off to COMPILE_WARNINGS
property
ENABLE <warning-id> # add <warning-id>=on to COMPILE_WARNINGS
property
TREAT_AS_ERROR <warning-id> # add <warning-id>=error to
COMPILE_WARNINGS property
)
General warning-id's:
* all (compiler specific "all", e.g. /Wall or -Wall)
* default
* level<N>
* none
* everything (all possible warnings for compiler, if there is no such
option use maximum level plus some warnings explicitly)
Group warnings-id's:
* inline # MSVC: 4711 (automatic-inline), 4714 (force-not-inlined),
4710 (not-inlined), 4514 (unreferenced-inline)
* compatibility-c++98 # Clang: `-Wc++98-compat`,
`-Wc++98-compat-pedantic`
Simple warning-id examples:
* undef # Clang/GCC: `-Wunder`; MSVC: 4668
* shift-sign-overflow # Clang: `-Wshift-sign-overflow`, GCC: nothing,
MSVC: nothing
* inherits-via-dominance # Clang/GCC: nothing, MSVC: 4250
Since I'm expecting cross-platform behaviour here I think that such
general warnings-id like 'all', 'default', 'level<N>' might
be confusing since different compilers with the same levels will define
different groups of warnings (no tests/examples, I'm just pretty sure
about that).
So I'm afraid we will end with code like this:
if(MSVC)
add_compile_warnings(ENABLE level3)
else()
add_compile_warnings(ENABLE level4)
endif()
I think that goal of this feature is to avoid such compiler specific
switches.
Note that there is no such problem with 'none', 'everything',
group/simple warning-id.
Properties will be set in form <warning-id>=on|off|error, e.g.:
add_compile_warnings(DISABLE undef unused ENABLE inline
TREAT_AS_ERROR everything)
will set COMPILE_WARNINGS directory property to:
undef=off unused=off inline=on everything=error
Generator expressions can be used for config-specific warnings:
set(debug_off $<$<CONFIG:Debug>:off>)
set(non_debug_error $<$<NOT:$<CONFIG:Debug>>:error>)
set_directory_properties(... COMPILE_WARNINGS
undef=${debug_off}${non_debug_error} ${old_warnings})
In case of any conflicts return CMake warning for developer message
(cmake -Wdev/cmake -Wno-dev).
Implementation details:
Abstracted unmodified <warning-id> will be kept until the very last
point when we need real flags generated. E.g. do not expand 'everything'
on any step since this will
mask possible configuration errors:
add_compile_warnings(DISABLE all ENABLE undef) # OK: turn off
everything except 'undef'
add_compile_warnings(DISABLE warning-A warning-B ... undef ...
warning-Y warning-Z ENABLE undef) # ERROR: user want undef=on and undef=off
Directory properties affect targets and sources, target properties
affect sources of this target. E.g.:
add_compile_warnings(DISABLE undef)
target_compile_warnings(foo DISABLE unused)
effectively equivalent to:
target_compile_warnings(foo DISABLE undef unused)
Question: do we need to control this? probably by
'target_compile_warnings(foo DISABLE unused IGNORE DIRECTORY)' ?
<warning-id> may expand to nothing in case warning make no sense for
current language or warning not implemented by compiler:
add_compile_warnings(ENABLE switch-enum)
add_executable(foo foo.c) # C target, no warning will be added
add_executable(boo boo.cpp) # C++ target, -Wswitch-enum will be added
add_compile_warning(ENABLE inherits-via-dominance)
add_executable(foo foo.cpp) # Clang/GCC: nothing, MSVC: 4250
After this feature implemented we need to introduce new policy to avoid
adding warnings flags to CMAKE_CXX_FLAGS by default (e.g. "/W3" added by
default for Visual Studio).
Warnings should not be propagated via INTERFACE because unlike
definitions or other compiler flags they doesn't affect final binary or
compatibility.
Questions that is not touched so far:
On 29-Mar-16 22:42, Ruslan Baratov wrote:
> One more note. Properties is a good abstraction and works great for
the native CMake project. But there is a tricky scenario about them -
when we need to create ExternalProject_Add for the non-CMake project.
> E.g. when I have CMAKE_POSITION_INDEPENDENT_CODE variable set to
`YES` I need to add `-fPIC` to the flags manually, or check
`CXX_STANDARD 11` and add `-std=c++11`. I guess I can handle such simple
cases but I can predict that for warnings it will be a huge pain.
> How CMake can help me avoid violating DRY?
Would be nice to have this one. Like 'expand_compiler_flags(cxxflags
LANGUAGE CXX CONFIGURATION Debug)' => add 'CXXFLAGS=${cxxflags}' to
ExternalProject_Add step of autotools based project.
On 31-Mar-16 04:31, Simon Richter wrote:
>
> With my Linux distro hat on: please don't force warning levels from
> inside projects.
>
> Packages are often automatically compiled on different platforms, and we
> do want to know about third party modules generating warnings on the
> more obscure ones where sizeof(long) < sizeof(void *), because no human
> will ever have more than a casual look at the build logs unless there
> are warnings there that do not appear on other platforms.
Is it possible in general to control warnings globally? Imagine I have
target that should ignore all warnings for any reason. If you able to
control warnings globally this target will generate tons of useless
messages. How to enable warnings for all targets except this one?
Ruslo
More information about the cmake-developers
mailing list