icktoofay
icktoofay

Reputation: 129109

Why does CMake split arguments differently for add_compile_options and target_compile_options?

I'm trying to enable warnings in a CMake project. Using target_compile_options similar to what is suggested in this answer works fine:

target_compile_options(mytarget PRIVATE $<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -pedantic>)

I have many targets, and I would like to apply these settings to all of them. So, I tried using add_compile_options instead:

add_compile_options($<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -pedantic>)

However, when I use this, I see that the compiler is passed "\$<1:-Wall" -Wextra "-pedantic>", as if space-splitting occurred before expanding the generator expression. This confuses the compiler and the build fails.

I tried quoting the argument to add_compile_commands:

add_compile_options("$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -pedantic>")

But when I do this, the compiler is passed a single "-Wall -Wextra -pedantic" argument, which also confuses it and causes the build to fail.

I can "distribute" out the generator expressions like this:

add_compile_options(
    $<$<CXX_COMPILER_ID:GNU,Clang>:-Wall>
    $<$<CXX_COMPILER_ID:GNU,Clang>:-Wextra>
    $<$<CXX_COMPILER_ID:GNU,Clang>:-pedantic>
)

This works fine, and solves my immediate problem…

…but, the question remains: what is causing add_compile_options to work differently from target_compile_options here? Shouldn't their string-splitting semantics be identical?

Upvotes: 6

Views: 691

Answers (1)

MaxC
MaxC

Reputation: 580

That is, because add_compile_options is used to add compile options to the COMPILE_OPTIONS list, a semicolon seperated list, whereas add_target_options adds options to the INTERFACE_COMPILE_OPTIONS of datatype property.

You were so close! Your code works as soon as you replace spaces with semicolons:

add_compile_options("$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall;-Wextra;-pedantic>")

And yes! I also think, that this behavior is inconsistent and that add_compile_options should work more similar to target_compile_options. Maybe somebody else can elaborate the history of that further, but my curiosity was satisfied when I found out, that [^_]COMPILE_OPTIONS[^_] appears much more frequently in the code, than [^_]INTERFACE_COMPILE_OPTIONS[^_] does: That means 121/40 at d231f429f10e9! From that I assume, that it has been there for longer and changing the way how it is implemented would very likely break existing build chains for some users and nobody wants that.

Upvotes: 3

Related Questions