I have a project that builds and runs fine with CMake. My project setup is like this:
├── CMakeLists.txt
|
├── include/
│ └── standalone/
│ └── x.hpp
|
├── src/
└── standalone/
└── main.cpp
The contents of my headers is like this:
// ------x.hpp--------
#pragma once
#include <iostream>
class X
{
public:
void hello()
{
std::cout << "Hello World!\n"; // needs <iostream>
}
};
// -------main.cpp-------
#include <standalone/x.hpp>
int main()
{
X x;
x.hello();
}
I use the following CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(standalone)
###############################################################
# Compiler settings
###############################################################
# use C++11 features
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# set warning level
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -pedantic -pedantic-errors -Wall -Wextra")
###############################################################
# header dependencies
###############################################################
# compile against project headers
include_directories(${PROJECT_SOURCE_DIR}/include)
# the header files
file(GLOB_RECURSE header_files FOLLOW_SYMLINKS "include/*.hpp")
# the source files
file(GLOB_RECURSE source_files FOLLOW_SYMLINKS "src/*.cpp")
###############################################################
# build target
###############################################################
# the program depends on the header files and the source files
add_executable(main ${header_files} ${source_files})
The sequence of commands mkdir build
, cd build
, cmake ..
, make
, and ./main
correctly prints "Hello World!" without warnings.
The above setup is correct. But suppose <iostream>
was not included in x.hpp
but in main.cpp
instead. Then the program would still have built correctly, but the x.hpp
would not be a standalone header. So I would like to test for self-sufficiency of my headers, i.e. for every header I would like to compile a small test program
#include "some_header.hpp"
int main() {}
However, if I add the following section to the CMakeList.txt
###############################################################
# header self-sufficiency
###############################################################
set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
message("REQUIRED_FLAGS=${CMAKE_REQUIRED_FLAGS}")
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR}/include)
message("REQUIRED_INCLUDES=${CMAKE_REQUIRED_INCLUDES}")
include(CheckIncludeFiles)
check_include_files("${header_files}" IS_STANDALONE)
The macro ${header_files}
correctly expands to the header x.hpp
, but the check_include_files()
command does not correctly compile it
REQUIRED_FLAGS= -std=c++11 -Werror -pedantic -pedantic-errors -Wall -Wextra
REQUIRED_INCLUDES=/home/rein/projects/standalone/include
-- Looking for include file /home/rein/projects/standalone/include/standalone/x.hpp
-- Looking for include file /home/rein/projects/standalone/include/standalone/x.hpp - not found.
Apparantly I am missing some configuration variable that lets CMake search in the right place. Even for correct headers, check_include_files()
does not work. What do I need to do to make this work? Only when correct headers are deemed correct, can I go on and test incorrect headers.
NOTE Unless it's
absolutey necessary, I am not interested in shell scripts or elaborate CMake for loops that directly call TRY_COMPILE
or something like that. AFAICS, that's what the CheckIncludeFiles
module is for, and I'd like to know how to correctly configure that, if at all possible.
For C++ headers rather than C headers, you need to use CheckIncludeFileCXX
. This module also differs from CheckIncludeFiles
in that you can only pass a single file at a time to this macro.
It could well also be that you need to set CMAKE_REQUIRED_INCLUDES
, or one of the other variables listed in the docs.
For example, if some of your headers refer to eachother (as in #include "h1.hpp"
), then you'll need:
set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR}/include)
include(CheckIncludeFileCXX)
foreach(project_header ${project_headers})
get_filename_component(header_name ${project_header} NAME_WE)
check_include_file_cxx("${project_header}" ${header_name}_IS_STANDALONE)
endforeach()
There's a little more info in the CMake wiki article How To Write Platform Checks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With