CMake:How To Write Platform Checks: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
No edit summary
No edit summary
Line 29: Line 29:
CMake is able to do the same, and I'll show you how to do it.
CMake is able to do the same, and I'll show you how to do it.


Addtionally to the builtin commands (see http://www.cmake.org/HTML/Documentation.html ), cmake offers more commands implemented by cmake script files, called modules. These files are located in the cmake module directory, on UNIX systems is this by default <tt>/usr/local/share/CMake/Modules </tt>.
Additionally to the builtin commands (see http://www.cmake.org/HTML/Documentation.html ), cmake offers more commands implemented by cmake script files, called modules. These files are located in the cmake module directory, on UNIX systems is this by default <tt>/usr/local/share/CMake/Modules </tt>.


To use commands from these modules, they have to be included in the CMakeLists.txt. CMake comes with several modules for checking the system, they all follow the same style, as an example here CHECK_INCLUDE_FILES:
To use commands from these modules, they have to be included in the CMakeLists.txt. CMake comes with several modules for checking the system, they all follow the same style, as an example here CHECK_INCLUDE_FILES:
Line 42: Line 42:


The CMake module CheckIncludeFiles offers the command, well, CHECK_INCLUDE_FILES(). The first argument to this command is the header you want to check for. The second argument is the variable which will contain the result. If the given header was found, it is set to 1, otherwise it is empty.
The CMake module CheckIncludeFiles offers the command, well, CHECK_INCLUDE_FILES(). The first argument to this command is the header you want to check for. The second argument is the variable which will contain the result. If the given header was found, it is set to 1, otherwise it is empty.
If another header is required to use the header you are looking for, you have to list the header files separated by semicolons, as you can see above. To see what CHECK_INCLUDE_FILES() exactly does, have a look at the implementation: <tt>/usr/local/share/CMake/Modules/CheckIncludeFiles.cmake</tt> .
If another header is required to use the header you are looking for, you have to list the header files separated by semicolons, as you can see above. To see what CHECK_INCLUDE_FILES() exactly does, have a look at the implementation: <tt>/usr/local/share/CMake/Modules/CheckIncludeFiles.cmake</tt> .  
The results are stored in the file CMakeCache.txt, so to check later whether the test succeeded or not look in the CMakeCache.txt file :
There you'll see that it tries to compile a simple source file which includes the specified header files. The results of the tests are stored in the file CMakeCache.txt, so if you want to check later whether the test succeeded or not look in the CMakeCache.txt file :
<pre>
<pre>
//Have include HAVE_MALLOC_H
//Have include HAVE_MALLOC_H

Revision as of 22:03, 28 January 2006

If you want to write software which compiles and runs on different operating systems, you have to take care for the special properties of the different platforms. On different operating systems there are subtle differences, e.g. on FreeBSD you should not use malloc.h, while it is perfectly ok to use it on Linux. These differences are usually handled by providing a header file which contains a bunch of define-statements according to the platform properties, usually named config.h:

#define HAVE_MALLOC_H 1
/* #undef HAVE_SYS_MNTTAB_H 1 */
/* #undef HAVE_SYS_MNTENT_H 1 */
#define HAVE_SYS_MOUNT_H 1

This header file is then included in the source files and the handled appropriately:

foo.c:

#include "config.h"

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#else
#include <stdlib.h>
#endif

void bar() {
   void *buf=malloc(1024);
...
}

The contents of config.h depend on the platform where the sources are compiled, so there needs to be a way to generate this header file before the actual compilation process starts. If you are using autotools-based software, you probably know the ./configure step, which has to be executed before starting make. The ./configure script does some system introspection and generates from the gathered information the config.h header file. CMake is able to do the same, and I'll show you how to do it.

Additionally to the builtin commands (see http://www.cmake.org/HTML/Documentation.html ), cmake offers more commands implemented by cmake script files, called modules. These files are located in the cmake module directory, on UNIX systems is this by default /usr/local/share/CMake/Modules .

To use commands from these modules, they have to be included in the CMakeLists.txt. CMake comes with several modules for checking the system, they all follow the same style, as an example here CHECK_INCLUDE_FILES:

INCLUDE (CheckIncludeFiles)
# usage: CHECK_INCLUDE_FILES (<header> <RESULT_VARIABLE> )

CHECK_INCLUDE_FILES (strings.h HAVE_STRINGS_H)
CHECK_INCLUDE_FILES ("sys/param.h;sys/mount.h" HAVE_SYS_MOUNT_H)

The CMake module CheckIncludeFiles offers the command, well, CHECK_INCLUDE_FILES(). The first argument to this command is the header you want to check for. The second argument is the variable which will contain the result. If the given header was found, it is set to 1, otherwise it is empty. If another header is required to use the header you are looking for, you have to list the header files separated by semicolons, as you can see above. To see what CHECK_INCLUDE_FILES() exactly does, have a look at the implementation: /usr/local/share/CMake/Modules/CheckIncludeFiles.cmake . There you'll see that it tries to compile a simple source file which includes the specified header files. The results of the tests are stored in the file CMakeCache.txt, so if you want to check later whether the test succeeded or not look in the CMakeCache.txt file :

//Have include HAVE_MALLOC_H
HAVE_MALLOC_H:INTERNAL=1

As long as the result is in the cache, the test won't be executed again. If you want it to be executed again, either delete the file CMakeCache.txt, then all tests will be executed again, or just remove the entries for the variables you want to have tested again. This can save some time. If the test failed, and you want so find out why, open CMakeFiles/CMakeError.log and search for the header name (or function, etc.) you were testing for. There you should see the code which failed to compile or link, the compile command and the error message. Together with the implementation of the test in CheckIncludeFiles.cmake you should be able to figure out what went wrong.

INCLUDE (CheckIncludeFiles)
#the cmake module provides the command CHECK_INCLUDE_FILES
#CHECK_INCLUDE_FILES(header VARIABLE)

The usage should be obvious. The header you want to test for is given as the first argument. If it exists,

INCLUDE (CheckFunctionExists)
CHECK_FUNCTION_EXISTS(madvise  HAVE_MADVISE)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckLibraryExists)
INCLUDE (CheckTypeSize)
INCLUDE (CheckPrototypeExists)
INCLUDE (CheckCXXSourceCompiles)
INCLUDE (CheckCSourceCompiles)



CMake: [Welcome | Site Map]