[CMake] check_c_source_compiles caching pitfalls

Hendrik Sattler post at hendrik-sattler.de
Sun Apr 23 03:05:20 EDT 2017



Am 23. April 2017 03:16:41 MESZ schrieb Tyson Nottingham <tgnottingham at gmail.com>:
>The result of check_c_source_compiles and similar commands
>(check_c_source_runs, check_cxx_source_compiles, etc.) is cached by the
>variable name passed in. This caching makes those commands and ones
>that
>depend on them easy to misuse.
>
>For example,
>
>set(potential_flags -Wall -badflag)
>
>foreach(flag ${potential_flags})
>    check_cxx_compiler_flag(${flag} has_flag)
>    if(has_flag)
>        set(flags "${flags} ${flag}")
>    endif(has_flag)
>endforeach(flag)

Try to use variables with a better naming.  This will also solve your problem:
has_flag_${flag}

>Since the variable name "has_flag" is used on every loop iteration, the
>result of check_cxx_compiler_flag is the same on every iteration
>(because
>it uses check_cxx_source_compiles internally, which caches by variable
>name). Supposing -Wall is a valid flag, flags will be "-Wall -badflag",
>even if -badflag isn't valid.

Ask yourself WHY this is done! Rerunning cmake in a build tree should not repeat all those expensive tests. 

>The obvious workaround is to use different variable names for each
>check.
>For example:
>
>set(potential_flags -Wall -badflag)
>set(flag_test_counter 0)
>
>foreach(flag ${potential_flags})
>    math(EXPR flag_test_counter "${flag_test_counter} + 1")
>    set(flag_test "flag_test_${flag_test_counter}")
>    check_cxx_compiler_flag(${flag} ${flag_test})
>    if(${flag_test})
>        set(flags "${flags} ${flag}")
>    endif(${flag_test})
>endforeach(flag)
>
>But there is still a problem with this. If I run this once, flags will
>be
>"-Wall". If I change potential_flags to "-Wall -Werror" (supposing
>-Werror
>is valid) and run it again, flags will still be "-Wall" because of the
>caching. The test on -Werror will use the results for the test on
>-badflag.
>
>This problem can just as easily occur in simpler situations.
>
>check_cxx_compiler_flag(-Wall has_flag)
>
>if(has_flag)
>    message("yep")
>endif(has_flag)
>
>If I run this once, change -Wall to -badflag, and run it again, I'll
>still
>enter the if block.
>
>The obvious workaround is to delete the build files after changing
>potential_flags.
>
>However, all of this seems pretty error prone. I'm new to CMake, so I
>may
>be missing something obvious. Is there an obvious non-error-prone
>solution
>to this? In future versions, can these commands take arguments that say
>not
>to use the cached result (or something along those lines)? At the very
>least, the documentation for the commands and those that depend on them
>could mention these pitfalls.

-- 
Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet.


More information about the CMake mailing list