In the codebase in which I’m currently working, there are two scenarios where I might want to remove compile flags from a target:
Some targets want almost all the compile flags given by CMAKE_CXX_FLAGS and friends. However, I need to remove or disable certain flags for those targets,
Some targets require their own entirely custom set of build flags, and don’t want to use CMAKE_CXX_FLAGS (and friends) at all.
For (1), the best idea I have is to get CMAKE_CXX_FLAGS and friends, manually remove the flags I don’t want, and re-set those variables on a directory level. This is cumbersome, because the number of flags that need to be changed increases linearly with the number of CMAKE_BUILD_TYPEs. It’s also prone to break in future when new build types are added. Is there a cleaner way to achieve this?
(Side note - the scoping rules are also not clear to me. If I set CMAKE_CXX_FLAGS as a non-cache variable, does it apply to all targets in the current directory and below? If I have two targets in the same directory, declare one, then change CMAKE_CXX_FLAGS and declare the other, are my new CMAKE_CXX_FLAGS applied to just the second target?).
For (2) the same work-around applies, but I wonder if there’s some way to entirely exclude a target from CMAKE_CXX_FLAGS, CMAKE_BUILD_TYPE, etc.?
CMAKE_CXX_FLAGS apply to all targets. What it sounds like might work better for you is to have CMAKE_CXX_FLAGS be as small as possible and then you add flags through something like this:
I’m not sure how well whitelisting flags like that will work for me. If I’ve understood correctly, the process for removing a flag “foo” from the “frobnicator” target would be something like this:
Remove foo from the flags that are applied to all targets (CMAKE_CXX_FLAGS at the moment, or the myflags INTERFACE in your example),
Add the above generator expression for the foo flag,
Add the needs_foo property to every target apart from frobnicator.
The trouble is my code base is very large, so step (3) would involve adding a property to thousands of targets. If we then ever wanted to re-instate the foo flag, we’d have to remove that property from thousands of targets.
Is there no blacklisting solution available? I’ve got a vague idea that we could write a function a bit like this, but it seems inelegant… I’m also not sure that CMAKE_CXX_FLAGS would actually populate those target properties.
function(remove_compiler_flag target flag)
foreach(property IN COMPILE_DEFINITIONS COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS etc)
# Get the target property
# If the specified flag is in that list, remove it and re-set the target property
endforeach()
endfunction()
You can use $<NOT> around the property (might need $<NOT:$<BOOL:…>>) to negate it if that makes more sense.
When you encounter a genex, you have no idea what to do in this loop; you’ll never get “just a flag” with such things in this loop. Also note that flags can be added to targets later than this loop too.