[CMake] Issue with check_include_file() and GL/glxproto.h

Michael Hertling mhertling at online.de
Sat Nov 12 21:39:38 EST 2011


On 11/11/2011 12:42 PM, GOUJON Alexandre wrote:
> On 11/11/2011 04:13 AM, Michael Hertling wrote:
>> On 11/10/2011 11:22 PM, Eric Noulard wrote:
>>> If this is the case then it is a "GL/glxproto.h" design mistake
>>> not CMake mistake.
>> Absolutely, try to compile the following program by hand; it's
>> the same the CHECK_INCLUDE_FILE() macro tries to compile, too:
>>
>> #include<GL/glxproto.h>
>> int main(void){return 0;}
>>
>> It will fail with the same error message, i.e. the GL/glxproto.h header
>> is not self-sufficient; if intentionally or accidentally, I don't know.
>> It's this failure that makes CHECK_INCLUDE_FILE() report the header as
>> non-existent, or better as "not compilable".
> I just sent them an e-mail so that they will be aware of the issue.

Is the GL/glxproto.h header a public one or is it private, i.e. is it
meant to be included explicitly by client code or not? In the latter
case, by convention, it usually needs not to be self-sufficient.

>>> This is true but the documentation tells you more about the macro
>>> cmake --help-module CheckIncludeFile
>>>
>>> says
>>> "an optional third argument is the CFlags to add to the compile line or
>>>         you can use CMAKE_REQUIRED_FLAGS"
>>>
>>> which clearly states that it does a compilation.
>> Indeed, CHECK_INCLUDE_FILE() means: Check if a header is *functional*.
> Ok, will use find_file instead.
>>> The thing you want is probably
>>>
>>> if(DEFINED VARIABLE)
>>>     message(FATAL_ERROR "VARIABLE already defined :<${VARIABLE}>  aborting")
>>> endif()
> Yeah, thanks.
>>> I think it's not the responsability of check_include_file to do such job
>>> but you can do that in your CMakeLists.txt
>> With FIND_FILE/PATH() looking for a header, the user must have the
>> possibility to make them no-ops by presetting the result variable,
>> so these functions must not overwrite a valid path. However, with
>> CHECK_INCLUDE_FILE(), the user can't "define" a header as working;
>> thus, there is no need to protect an already defined variable from
>> being overwritten, IMO. Moreover, the user must have the chance to
>> reuse the same variable for this purpose again without having the
>> configuration terminate. OTOH, one usually uses an individually
>> named variable for each header, e.g. HAVE_GL_GLXPROTO_H, as you
>> do, which is most certainly not reused for anything at all.
> Ok but as I didn't understand why check_include_file was failing, I 
> tried many things like simple then double quoting GL/glxproto.h and also 
> tried a different variable name. I took HAVE_UNISTDE_H because I knew 
> HAVE_UNISTD_H was working. With HAVE_UNISTDE_H, check_include_file 
> seemed to work (it wasn't true, this variable name was simply defined 
> before elsewhere) so in the end, I believed some variable names were 
> allowed and others not. So to avoid the same mistake, I thought a 
> message (at least a STATUS one) wouldn't hurt.
>>>> IF("${VARIABLE}" MATCHES "^${VARIABLE}$") fails : is it intended ?
>>> I do not understand
>>> In which case does it fail?
> Actually, every time.
> Here is the beginning of my modified CheckIncludeFile.cmake :
> 
> MACRO(CHECK_INCLUDE_FILE INCLUDE VARIABLE)
> message(STATUS "${VARIABLE}")
>    IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
> message(STATUS "${VARIABLE} matches ^${VARIABLE}$")
> 
> and I only have the following output
> -- HAVE_SYS_TIME_H
> -- HAVE_SYS_TYPES_H
> -- HAVE_SYS_RESOURCE_H
> -- HAVE_SYS_STAT_H
> -- HAVE_UNISTD_H
> -- HAVE_FCNTL_H
> -- HAVE_GL_GLXPROTO_H
> CMake Error at CMakeLists.txt:117 (message):
> [..]
> 
> So the first IF is failing, skipping the whole macro.
> If I add a # before this IF (and the corresponding ENDIF), 
> check_include_file does its jobs and even finds the other headers :
> [...]
> -- HAVE_FCNTL_H
> -- HAVE_FCNTL_H matches ^HAVE_FCNTL_H$
> -- Looking for fcntl.h
> -- Looking for fcntl.h - found
> -- HAVE_GL_GLXPROTO_H
> -- HAVE_GL_GLXPROTO_H matches ^HAVE_GL_GLXPROTO_H$
> -- Looking for GL/glxproto.h
> -- Looking for GL/glxproto.h - not found
> 
> Any idea ?

Sorry, I talked nonsense in my previous reply. Obviously, the line

IF("${VARIABLE}" MATCHES "^${VARIABLE}$")

serves to prevent the macro's re-execution if the result variable is
already defined, i.e. if the macro has most certainly been called
before with the same parameters. E.g., with VARIABLE equaling
"HAVE_XYZ_H", this line expands to

IF(HAVE_XYZ_H MATCHES ^HAVE_XYZ_H$)

and due to the implicit evaluation of variables on the left-hand
side of the IF() command's MATCHES clause, it finally looks like

IF(TRUE MATCHES ^HAVE_XYZ_H$)

or

IF(FALSE MATCHES ^HAVE_XYZ_H$)

provided the macro has been called before, i.e. HAVE_XYZ_H is either
TRUE or FALSE. Of course, these latter conditions are false, so the
macro isn't executed again. OTOH, if the variable HAVE_XYZ_H is un-
defined, i.e. the macro has not been called yet, the line remains

IF(HAVE_XYZ_H MATCHES ^HAVE_XYZ_H$)

which is true, so the macro is executed. Therefore, the macro is
skipped if the result variable indicates that there is already a
result. Thus, in contrast to what I erroneously said before, one
can indeed "define" a header as working by presetting the result
variable to TRUE, and one can not re-use the same result variable
for different calls to CHECK_INCLUDE_FILES(). In order to revisit
your question, a failing

IF("${VARIABLE}" MATCHES "^${VARIABLE}$")

means that VARIABLE denotes another variable which has already been
defined. If this doesn't explain your findings away, please come up
with a small but complete example which demonstrates the issue for
further investigation.

BTW, IF("${VARIABLE}" MATCHES "^${VARIABLE}$") is not bullet-proof,
IMO: If VARIABLE denotes another variable which has its own name as
value, the MATCHES condition always evaluates to true. Instead, one
should use IF(NOT DEFINED "${VARIABLE}") - with the quotes, this is
always evaluating to the intended result, AFAICS. Eric, what's your
opinion?

Regards,

Michael


More information about the CMake mailing list