[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