I have an interface library cxx_opts
in cmake that defines a bunch of flags and a binary main
that uses the cxx_opts
library.
cmake_minimum_required(VERSION 3.16)
project(test LANGUAGES CXX)
add_library(cxx_opts INTERFACE)
target_compile_options(cxx_opts INTERFACE
-Wall -Wpedantic -Wextra -Werror
)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE cxx_opts)
target_compile_options(main PRIVATE -Wno-unused-variable)
For completeness, my main.cpp
is super simple:
int main() {
int unused_variable{};
}
I then configure this project and generate a compilation database with this command:
cmake -D CMAKE_EXPORT_COMPILE_COMMANDS=ON -S . -B build
If I now build this code, I'm getting an error:
cmake --build build
main.cpp:2:9: error: unused variable 'unused_variable' [-Werror,-Wunused-variable]
2 | int unused_variable{};
| ^~~~~~~~~~~~~~~
I expect that because I'm adding a -Wno-unused-variable
flag to the main
target the warning should not trigger, and yet it does and is treated as an error.
If I now inspect the compilation database generated as a result of the configuration step (cleaned up from unimportant stuff), I'm seeing that the order of the flags is wrong:
[
{
"directory": "test_project/build",
"command": "c++ -Wno-unused-variable -Wall -Wpedantic -Wextra -Werror -o CMakeFiles/main.dir/main.cpp.o -c test_project/main.cpp",
"file": "test_project/main.cpp"
}
]
Note how the -Wno-unused-variable
appears before the -Werror
flag, which causes the behavior I'm seeing.
Now with all of the above in mind, I do not understand why CMake is ordering these flags like it does. I also am an avid CMake user and was under the impression that this should not ever happen. From here, the CMake docs seem to say the following:
If BEFORE is specified, the content will be prepended to the property instead of being appended.
Repeated calls for the same append items in the order called.
To test the above statement I actively added the -Wno-unused-variable
flag to the cxx_opts
target directly with the same results, it still appears before the rest. So something actively reorders flags in the resulting command.
target_compile_options(cxx_opts INTERFACE
-Wall -Wpedantic -Wextra -Werror
)
target_compile_options(cxx_opts INTERFACE -Wno-unused-variable)
The error here happens on my Mac, so maybe it is Mac-related? Does anyone know what is happening here and what I can do to correct the order of the flags?
UPD: After the comments by @Tsyvarev it seems that we can do this instead that should guarantee the order of the flags (I'm not 100% sure of this yet):
cmake_minimum_required(VERSION 3.16)
project(test LANGUAGES CXX)
add_library(cxx_opts INTERFACE)
target_compile_options(cxx_opts INTERFACE
-Wall -Wpedantic -Wextra -Werror
)
add_library(custom_flags INTERFACE)
target_compile_options(custom_flags INTERFACE -Wno-unused-variable)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE cxx_opts custom_flags)
Note how we have to create another target custom_flags
and link it after the cxx_opts
for the flags from custom_flags
target to appear after the ones from cxx_opts
target. Is there a better (more idiomatic) way?