I would like to use a global set of flags for compiling a project, meaning that at my top-level CMakeLists.txt file I have specified:
ADD_DEFINITIONS ( -Wall -Weffc++ -pedantic -std=c++0x )
However, for a specific file (let’s say “foo.cpp”) in a subdirectory, I want to switch the
compile flags to not apply -Weffc++ (included commercial library I cannot change). To simplify the situation to use only -Wall, I tried:
SET_SOURCE_FILES_PROPERTIES( foo.cpp PROPERTIES COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )
, which did not work.
I also tried
SET_PROPERTY( SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )
and
ADD_EXECUTABLE( foo foo.cpp )
SET_TARGET_PROPERTIES( foo PROPERTIES COMPILE_FLAGS -Wall )
, in which neither worked.
Finally, I tried removing this defintion:
REMOVE_DEFINITIONS( -Weffc++ )
ADD_EXECUTABLE( foo foo.cpp )
ADD_DEFINITIONS( -Weffc++ )
, which also did not work (meaning, I get a lot of style warnings about the commercial library).
(**Note: The warnings ARE suppressed if I DO NOT re-include the -Weffc++ directive after the executable is built.)
I also tried temporarily removing the compile flags:
http://www.cmake.org/pipermail/cmake/2007-June/014614.html
, but that didn’t help.
Is there not an elegant solution to this?
Your attempts above are adding further flags to your file/target rather than overwriting as you seem to expect. For example, from the docs for Properties on Source Files – COMPILE_FLAGS:
You should be able to countermand the
-Weffc++flag for foo.cpp by doingThis should have the effect of adding
-Wno-effc++after-Weffc++in the compiler command, and the latter setting wins. To see the full command and check that this is indeed the case, you can doAs an aside, one of the maintainers of the GNU C++ Standard Library presents a pretty negative opinion on
-Weffc++in this answer.Another point is that you’re misusing
add_definitionsin the sense that you’re using this for compiler flags rather than the intended preprocessor definitions.It would be preferable to use
add_compile_optionsor for CMake versions < 3.0 to do something more like:
In response to further questions in the comments below, I believe it’s impossible to reliably remove a flag on a single file. The reason is that for any given source file, it has the
COMPILE_OPTIONSandCOMPILE_FLAGS1 of its target applied, but these don’t show up in any of the properties for that source file.You could look at stripping the problem flag from the target’s
COMPILE_OPTIONS, then applying it to each of the target’s sources individually, omitting it from the specific source file as required.However, while this could work in many scenarios, it has a couple of problems.
First – source files’ properties don’t include
COMPILE_OPTIONS, onlyCOMPILE_FLAGS. This is a problem because theCOMPILE_OPTIONSof a target can include generator expressions, butCOMPILE_FLAGSdoesn’t support them. So you’d have to accommodate generator expressions while searching for your flag, and indeed you’d maybe even have to "parse" generator expressions if your flag was contained in one or more to see whether it should be re-applied to the remaining source files.Second – since CMake v3.0, targets can specify
INTERFACE_COMPILE_OPTIONS. This means that a dependency of your target can add or override your target’sCOMPILE_OPTIONSvia itsINTERFACE_COMPILE_OPTIONS. So you’d further have to recursively iterate through all your target’s dependencies (not a particularly easy task since the list ofLINK_LIBRARIESfor the target can also contain generator expressions) to find any which are applying the problem flag, and try and remove it from those targets’INTERFACE_COMPILE_OPTIONStoo.At this stage of complexity, I’d be looking to submit a patch to CMake to provide the functionality to remove a specific flag unconditionally from a source file.
1: Note that unlike the
COMPILE_FLAGSproperty on source files, theCOMPILE_FLAGSproperty on targets is deprecated.