[CMake] check_c_source_compiles caching pitfalls

Tyson Nottingham tgnottingham at gmail.com
Sat Apr 22 21:16:41 EDT 2017


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)

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.

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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20170422/b398a528/attachment.html>


More information about the CMake mailing list