This is a very important thing to be able to do when building large projects and using other 3rd party (e.g. from Github) projects in your own, as they often screw up the compile definitions and end up creating build-breaking problems that require you to selectively remove a definition, without editing the original project itself.
I haven't found a modern, per target way to do this sadly.
However, remove_definitiions is an old way to do it. It works in the sloppy old style of applying to the current subdirectory and below. This causes leakages to your other targets in the same directory frustratingly enough. But sometimes that might be exactly what you want.
One ugly solution is to break out part of your CMakeLists.txt into a separate CMakeLists.txt for the offending targets, and place remove_definitions only in that secondary CMakelists.txt in a subdirectory that quarantines those targets.
Hopefully CMake will add a target_remove_definitions() function.
Here is an example of where I needed this and how I solved it:
# main_directory/CMakeLists.txt
# Add subdir of the offending targets
add_subdirectory(evil_dependencies)
....
# main_directory/evil_dependencies/CMakeLists.txt
# This is required or else, there are headers in the repo
# that #define NOMINMAX which then causes a warning:
# macro redefinition, and warnings as errors = stop the build.
if(MSVC)
remove_definitions(/DNOMINMAX)
endif()
add_subdirectory(some_evil_dependency1)
add_subdirectory(some_evil_dependency2)
For GCC style problems it will look more like remove_definitions(-DSOMEDEFINE). Note, for this old style call, the /D or -D are required, unfortunately. This sadly requires you to write a bunch of extra if-then branches to see if you're in MSVC et. al. or GCC/Clang.
EDIT: See Remi's answer below. It's probably? better than mine, and how I think I'd do it now, mainly. My answer is still useful potentially for some situations where you actually want to remove definitions from a bunch of children folders as well, but Remi's answer is likely to be more elegant most of the time, esp. because of the regex that can make it easier to scan for -D and /D options.
As this is an open issue for CMake, it will likely be fixed any time, obsoleting these answers for newer versions of CMake. That hasn't happened yet (as of 2020-07-16). https://gitlab.kitware.com/cmake/cmake/-/issues/19796