Fix for #16291 breaks try_compile() when CFLAGS specify include directory
Recently we've discovered that our project has stopped compiling with newer versions of CMake (newer than 3.13.3). The problem is caused by a combination of use of CFLAGS
env. var, set(CMAKE_C_FLAGS ...)
command and try_compile()
command when INCLUDE_DIRECTORIES
need to be specified.
Namely: we wish to try_compile()
a small source file to see if a header file is present and can be #included
. For the sake of the example let's call the header file hh.h
. This hh.h
file normally resides in a path that is not standard for the compiler, although the problem itself is more generic and can also be encountered when cross-compiling and specifying a non-standard list of include directories for everyday open-source libraries. But I digress.
Since this hh.h
is in a non-standard directory, we need to specify its expected location (let's call it <directory>
) in INCLUDE_DIRECTORIES
definition in try_compile()
. However, as we are compiling a larger project, we also have the same -I<directory>
specified in CFLAGS
environment variable so that it can be used elsewhere. Also, this larger project does some manipulations of CMAKE_C_FLAGS
variable in its web of CMakeLists.txt
.
I managed to bring it down to a minimal example that looks like this:
# This file is saved in /opt/cmake-cflags/src/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(BreakCmakeCflags)
set(CMAKE_C_FLAGS "") # <-- essential to reproduce
set(CMAKE_VERBOSE_MAKEFILE on)
try_compile(HAS_HH ${CMAKE_BINARY_DIR}
# src.c simply has #include <hh.h> and empty main()
"${CMAKE_SOURCE_DIR}/src.c"
# -DINCLUDE_DIRECTORIES works in CMake 3.13.3 regardless of CFLAGS but is ignored
# with commit 5990ecb74133e1a9c885fc0ea62896b501d37fef if both CFLAGS env. is set
# and CMAKE_C_FLAGS is manipulated.
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=/opt/cmake-cflags/src/lib"
OUTPUT_VARIABLE OUTPUT)
message(STATUS HAS_HH " ${HAS_HH}")
message(STATUS OUTPUT " ${OUTPUT}")
if (NOT HAS_HH)
message(FATAL_ERROR "FAIL!")
endif()
and run like this:
CFLAGS="-I/opt/cmake-cflags/src/lib" cmake /opt/cmake-cflags/src/
I bisected CMake's repo and found that 5990ecb7 is the commit that introduces this problem.
Minimal reproduce configuration: cmake-cflags.tar.gz
While this may be a case of "you're doing it wrong" on our side, the fact is that this example works in CMake 3.13.3 and doesn't when the aforementioned commit is applied. CMake 3.15.3 still exhibits this problem.
Extra info:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.