Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use CHECK_INCLUDE_FILES macro in cmake?

Tags:

cmake

I need link my program against Kerberos authentication library (gssapi_krb5) with the corresponding headers gssapi/gssapi.h and gssapi/gssapi_krb5.h included in the source file.

Currently, the compilation will continue if headers are absent and stop with a compile time error saying header files not found. What I want to implement in the cmake file is to check the existence of the header file and stop compiling if not found.

I add the following code into my CMakeList.txt file.

INCLUDE(CheckIncludeFiles)

CHECK_INCLUDE_FILES(gssapi/gssapi.h;gssapi/gssapi_krb5.h HAVE_KRB_HEADERS)
IF (NOT HAVE_KRB_HEADERS)
    RETURN()
ENDIF (NOT HAVE_KRB_HEADERS)

But it still does not act as I expected. I would like the following lines:

-- Looking for gssapi/gssapi.h - found
-- Looking for gssapi/gssapi_krb5.h - not found

but fail. Also, the variable HAVE_KRB_HEADERS is empty when output with message macro. Compile continues until the error described above occurs.

I read somewhere on the Web, this may be because CMake cache. I'm very new to CMake and not quite clear with that concept. My CMake version is 2.6. How could I make this code work? Thank you!

like image 884
Summer_More_More_Tea Avatar asked Sep 15 '13 03:09

Summer_More_More_Tea


1 Answers

I can't say I'm a huge fan of CheckIncludeFiles because of its difficulty to get right. In principal it's good - it actually creates tiny c files which #include the requested headers and tries to compile them, but it seems to be too easy to get wrong.

I generally prefer just using find_path and/or find_file for this job. This doesn't check the contents of any files found, but usually if you find the required header, its contents are good!

I would use find_path if I needed to know the folder where the header lived. This would usually be because I need to check for other files in the same folder (as in your case), or more commonly because I need to add the folder to an include_directories call.

find_file yields the full path to the file (if found). For headers, normally I don't need the path elsewhere in the CMakeLists - it's just used immediately after the find_file to check the file was actually found.

So, here's how I'd go about checking for "gssapi/gssapi.h" and "gssapi/gssapi_krb5.h"

find_path(GssApiIncludes gssapi.h PATHS <list of folders you'd expect to find it in>)
if(NOT GssApiIncludes)
  message(FATAL_ERROR "Can't find folder containing gssapi.h")
endif()

find_file(GssKrb gssapi_krb5.h PATHS ${GssApiIncludes} NO_DEFAULT_PATH)
if(NOT GssKrb)
  message(FATAL_ERROR "Can't find gssapi_krb5.h in ${GssApiIncludes}")
endif()

If you do this, then if required you could add

include_directories(${GssApiIncludes})

so that in your source code you can do

#include "gssapi.h"
#include "gssapi_krb5.h"
like image 64
Fraser Avatar answered Oct 18 '22 06:10

Fraser