I'm trying to introduce -Werror flag to rather big legacy project. As expected, it breaks the compilation completely. Therefore I've decided to introduce it gradually, and for the new code first of all. My original approach was to compile new features as separate static targets and link them to the project, which works kind of good both in terms of project structure and readability. The problem which persist are pre-existing tangled includes. Basically, even after fixing all warnings in new code I'm left with chain of includes introducing new warnings. Is there any way to limit warning flags usage to given source files strictly? I do understand that include means basically copy/pasting headers into cpps, so it does not seem possible with just cmake settings. Then pragmas, perhaps?
CodePudding user response:
You can use the set_source_files_properties
command to set the COMPILE_OPTIONS
property on the files you need.
Something like this:
set_source_files_properties(bad.cpp PROPERTIES COMPILE_OPTIONS -Werror)
CodePudding user response:
I don't know about any compiler flags that allow you to apply flags to only some of the files included, so cmake cannot do better for you. Therefore pragmas are the way to go.
Basically what you effectively want in your cpp files is something like this:
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wall"
#include "updated_lib/header1.hpp"
#include "updated_lib/header2.hpp"
...
#pragma GCC diagnostic pop
#include "non_updated_lib/header1.hpp"
#include "non_updated_lib/header2.hpp"
Note that this would require this logic to be repeated in multiple translation units which you may want to avoid, if you're updating the headers gradually over time.
As an alternative you could duplicate the header file subdirectories, and make the non-updated versions available via one path and updated headers via another, e.g. for a header foo/bar/baz.hpp
either make the header available via path old/foo/bar/baz.hpp
or new/foo/bar/baz.hpp
and create a new header available via foo/bar/baz.hpp
that looks like this:
#if __has_include("new/foo/bar/baz.hpp")
# pragma GCC diagnostic push
# pragma GCC diagnostic error "-Wall"
# include "new/foo/bar/baz.hpp"
# pragma GCC diagnostic pop
#else
# pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wall"
# include "old/foo/bar/baz.hpp"
# pragma GCC diagnostic pop
#endif
Note that you'll probably need to write these kind of headers for you. You could even generate the actual includes via cmake during the generation of the project which which would shorten the headers to 3 pragmas plus one include; this would have the additional benefit of working with compiler versions not supporting __has_include
.
function(my_generate_include OUT_LIST DESTINATION_DIR FIRST_HEADER)
set(GENERATED_HEADERS ${${OUT_LIST}})
foreach(HEADER IN ITEMS ${FIRST_HEADER} ${ARGN})
if (HEADER MATCHES "^old/(.*)$")
configure_file(old_include.hpp.in "${DESTINATION_DIR}/${CMAKE_MATCH_1}")
list(APPEND GENERATED_HEADERS "${DESTINATION_DIR}/${CMAKE_MATCH_1}")
elseif (HEADER MATCHES "^new/(.*)$")
configure_file(new_include.hpp.in "${DESTINATION_DIR}/${CMAKE_MATCH_1}")
list(APPEND GENERATED_HEADERS "${DESTINATION_DIR}/${CMAKE_MATCH_1}")
else()
message(FATAL_ERROR "Header '${HEADER}' doesn't start with 'new/' or 'old/'")
endif()
endforeach()
set(${OUT_LIST} ${GENERATED_HEADERS} PARENT_SCOPE)
endfunction()
...
set(HEADERS)
my_generate_include(HEADERS ${CMAKE_CURRENT_BINARY_DIR}/generated_includes
old/a/b/c.hpp
new/d/e/f.hpp
)