CMake how to include headers without sources? - c++

This is probably a dummy question but I have literally looked at the two first pages of google without success.
I'm writing a header only library and I'm unable to set up correctly the CMake configuration in order that when I build my solution a given main.cpp finds the proper includes.
How can this be accomplished?
EDIT
So I probably should give a little more detailed explanation.
Lets say I have a ./src folder with: ./src/core and ./src/wrappers. Inside each folder I have .h files that needs to be included in a main.cpp file:
#include <src/core/reader.h>
Still when I put in CMakeList.txt something like:
include_directories(src/core)
add_executable(main main.cpp)
I receive a message like: src/core/reader.h no such file or directory.

To be able to use that path, you should refer to the parent directory of src.
Assuming the top level CMakeLists.txt is at the same level of src, you can use this instead:
include_directories(${CMAKE_SOURCE_DIR})
As from the documentation of CMAKE_SOURCE_DIR:
The path to the top level of the source tree.
If src is directly in the top level directory, this should let you use something like:
#include <src/whatever/you/want.h>
That said, a couple of suggestions:
I would rather add this:
include_directories(${CMAKE_SOURCE_DIR}/src)
And use this:
#include <whatever/you/want.h>
No longer src in your paths and restricted search area.
I would probably use target_include_directories instead of include_directories and specify the target to be used for that rules:
target_include_directories(main ${CMAKE_SOURCE_DIR}/src)
This must be put after the add_executable, otherwise the target is not visible.

Another option which might make sense in some situations would be to create a dedicated target for the header-only library:
add_library(headerlib INTERFACE)
target_include_directories(headerlib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
And then to use it:
target_link_libraries(mytarget headerlib)
This has the advantage that if you want to use it in multiple targets, it's easy to do so.

Just add a include_directories() directive in order to find where your header only library can be found by the target project.
According to your edit. To find
#include <src/core/reader.h>
You need to add
include_directories(/full_parent_path_of_src)

If I understand your question correctly then in your CMakeLists.txt you need to add include_directories(<DIRECTORY>) for every directory of your header library.

Related

CMake/make apply -D flags on header files

I'm (cross-)compiling a shared C library with support for many different platforms which is handled by an hierarchy of CMakeLists files. In those files, several platform specific compiler flags are conditionally produced (with add_definitions()). I can successfully compile and link the source code leading to an appropriate .so file.
But to use the library in any project, I need to provide the right header files, too. The following install command of CMake selects the right header files to copy but does not apply the replacement of preprocessor defines/includes:
install(FILES ${headers} DESTINATION include/mylibrary)
So how can I generate/install the "post-compiled" header files?
What I thought of so far:
As add_definitions() should stack my -D's in the COMPILE_DEFINITIONS variable, maybe running a foreach loop on the copied raw headers and replace the define/include placeholders?
Using add_custom_command() to apply some logic before copying?
Edit: As pointed out by Tsyvarev, there is an answer quite near to my needs here, but unfortunately not quite it. In summary, the answer gives 2 options:
Include a special 'config' header in all of the library's headers and leverage the cmakedefine command to call configure_file() on this header. I can't use this approach because I don't want to alter the library headers.
Create a target-specific .cmake file which helps external projects in including the right headers together with all necessary -D defines. I can't use this approach either, because my external projects do not use cmake for building. Plus, I wish to create a library that is as easy to include as possible.
Any other thoughts?
Edit 2: I may have to elaborate on my statement, that the install command of CMake is not replacing defines. Take the following example:
//sampleheader.hpp
#ifndef SAMPLEHEADER_HPP_
#define SAMPLEHEADER_HPP_
#include OS_SPECIFIC_HEADER
//...
Now I have a CMakeLists.txt file that does something like this:
# ...
if (${OS} MATCHES "arm-emblinux")
add_definitions(-DOS_SPECIFIC_HEADER="emblinuxHeader.hpp")
elseif (${OS} MATCHES "linux")
add_definitions(-DOS_SPECIFIC_HEADER="linuxHeader.hpp")
endif()
# ...
Everything compiles fine, but when the install command above gets called, I have a header file in my ../include/ directory still with OS_SPECIFIC_HEADER placeholder in it. And of course, this cannot be properly included in any development project.

CMake: Include vs add_subdirectory: Relative header file path

I have a c++ project with several subdirectories, e.g.
src/
CMakeLists.txt
main.cpp
module1/
CMakeLists.txt
code.cpp
code.h
module2/
CMakeLists.txt
code2.cpp
It seems that the two ways to deal with this in cmake is to either use add_subdirectory(module1) or include(module1) in my src/CMakeLists.txt. Somewhere I read, that the include use is regarded legacy/deprecated. My src/module1/CMakeLists.txt looks like this:
include_directories(${CMAKE_CURRENT_LIST_DIR})
set( SRCS
${SRCS}
${CMAKE_CURRENT_LIST_DIR}/code.cpp
)
set( QT_FILE_HEADERS
${QT_FILE_HEADERS} code.h
)
If I try to use the add_subdirectory method and want to usecode.h in main.cpp I have to write #include "module1/code.h". If I do the include method of adding module1, I can simply write #include "code.h". I would prefer not to specify the relative path of the include files when I use them somewhere else, is there a way to achieve this using the add_subdirectory method? I thought the include_directories line should have taken care of that.
This is not how you should make modules -- sure you can do it this way, it works, but it is not very useful. Given your layout, simply reference module1/code.cpp in the main CMakeLists.txt file.
However, if you want to use modules, make each one a separate static library. This will really simplify things!
In src/CMakeLists.txt write:
add_subdirectory(module1)
add_executable(myprogram main.cpp)
target_link_libraries(myprogram module1)
In src/module1/CMakeLists.txt write:
add_library(module1 STATIC code.cpp)
target_include_directories(module1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
This way, you are only passing one single thing back from the module1 CMake script: the module1 target. Your main doesn't need to know anything about what happens inside there. If the code in module1 requires specific external libraries, link them there, the main CMake script won't need to know about it. Simply by linking to module1, all the magic will happen behind the scenes, your program will be compiled with the right include directories and linked to the right libraries.

How to set a single root for all CLion includes?

My CLion project is organized as follows:
main.cpp
foo/bar.h
foo/blah.h
main.cpp has the line #include "foo/bar.h" and the latter is located all right.
But foo/bar.h has the line #include "foo/blah.h" (note the directory name is not omitted, even though both files happen to be in the same directory).
The FAQ suggests that a solution to "CLion fails to find some of my headers. Where does it search for them?" is to add the line
set(INCLUDE_DIRECTORIES .)
to CMakeLists.txt. This vibes as just the right answer since it matches what we'd do on the command line (add the flag -I.), but that doesn't help.
How do I tell CLion that I would like all includes to be relative to a single root?
Related question(s):
Tell CLion to use header include path with prefix
the simple way to do it is this:
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
If you want to dictate include paths for interfaces or installations (e.g. you're writing a library to be imported by other projects) then have a look at the documentation for
target_include_directories(...)

CMake adding a library

I am currently simply trying to add a library to one of the example for VTK.
So let's imagine we have this scenario in which I want to redefine the behavior or the trackball. What I did in that is to create my own trackball (based on the model provided by vtkInteractorStyleTrackballCamera). So I created two files: InteractorStyleTrackballCamera.cpp and InteractorStyleTrackballCamera.h
When I CMake, everything is just fine. However when I open the solution with Visual Studio 2013 and try to build the all_build target I get an error stating:
InteractorStyleTrackballCamera.h no such file or directory.
I know of course what it means, however I cannot understand why I get this error. It may be that my CMakeLists.txt is kind of broken (it is the only thing I can think of), so here it is:
cmake_minimum_required(VERSION 2.8)
PROJECT(TrackballCamera)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(TrackballCamera MACOSX_BUNDLE TrackballCamera)
add_library(InteractorStyleTrackballCamera InteractorStyleTrackballCamera.cpp InteractorStyleTrackballCamera.h)
if(VTK_LIBRARIES)
target_link_libraries(TrackballCamera ${VTK_LIBRARIES})
else()
target_link_libraries(TrackballCamera vtkHybrid vtkWidgets InteractorStyleTrackballCamera)
endif()
When I look at my solution explorer in VS13 I can clearly see 4 solutions, ALL_BUILD, InteractorStyleTrackballCamera (with the header and cpp) TrackballCamera and ZERO_CHECK. So that's what is puzzling me. Isn't it right that if the header is included in my solution explorer it should be found when I try to build ?
Oh and if you wonder what's inside my InteractorStyleTrackballCamera (not sure this is really relevant for that problem) I simply copied/pasted the content of vtkInteractorStyleTrackballCamera and replaced all the vtkInteractorStyleTrackballCamera by InteractorStyleTrackballCamera
Thanks in advance for the help.
EDIT: The error does not come from the file InteractorStyleTrackballCamera.cpp but from the file TrackballCamera.cxx when I try to include my header.
Basically the line is:
#include <InteractorStyleTrackballCamera.h>
I see the question has been answered. In addition, have a read of the documentation of
target_include_directories
https://cmake.org/cmake/help/v3.3/command/target_include_directories.html#command:target_include_directories
In CMAKE, you can imbue a target with properties that it carries forward into targets that depend on it. One such properties is the "include directories". This property is different in the following 3 scenarios:
Your target is itself being built
Your target is in the same project as the dependency
Your target has been installed and is being picked up with find_package
target_include_directories allows you to set the correct paths in all 3 cases.
see also target_link_libraries which can be used to ensure that libraries that your library depends on are pulled into any dependent target.
Confused yet? It took me months to get my head around this. Once I did, I realised how incredibly powerful CMAKE is.
#include <...> should only be used for including library headers. If you want to include a header file from your source directory, use #include "...".
With most compilers, the difference is that #include "..." also searches the source file's directory for the file to include, while #include <...> only searches include directories specified on the compiler's command-line (plus possibly some default ones).
Unrelated to the original question, but it seems to me you should link InteractorStyleTrackballCamera even when VTK_LIBRARIES is defined:
if(VTK_LIBRARIES)
target_link_libraries(TrackballCamera InteractorStyleTrackballCamera ${VTK_LIBRARIES})
else()
target_link_libraries(TrackballCamera vtkHybrid vtkWidgets InteractorStyleTrackballCamera)
endif()

Using cmake's automoc on external header files without knowing their filenames

In essence I want to be able to moc header files that are not part of any target in cmake with the additional difficulty that I don't know the filenames of those headers.
The actual project is quite complex and part of an automated build system. The following is an easy example.
Consider a project structured like this:
CMakeLists.txt
src/lib/source.cpp
src/lib/CMakeLists.txt
src/include/some_header.hpp # which is included in source.cpp
Content of main CMakeLists.txt:
cmake_mimimum_required(VERSION 2.8.6)
project("automoctest")
add_subdirectory(src/lib)
Content of src/lib/CMakeLists.txt:
include_directories(${CMAKE_HOME_DIRECTORY}/src/include)
find_package(Qt4 4.8 REQUIRED QtCore)
include(UseQt4)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_library(foo SHARED source.cpp)
target_link_libraries(foo ${QT_LIBRARIES})
set_target_properties(foo PROPERTIES AUTOMOC true)
Inside source.cpp the file some_header.hpp is included like this:
#include "some_header.hpp"
The Problem:
The file some_header.hpp includes a Q_OBJECT and has some signals, so moc needs to work its magic. But as the header is not inside the actual project the header will not get mocked. I don't even know the filename of some_header.hpp so I can't add it specifically to be mocked. Obviously AUTOMOC does not check the include_directories for mockable files even when a source file includes one of them.
What I tried (unsuccessfully):
use #include moc_some_header.cpp in source.cpp as it is described in the cmake documentation. This leads to an error in which cmake complains that it could not find some_header{.h,.hpp,.hxx,.H}
setting CMAKE_AUTOMOC_RELAXED_MODE to true. Even though it's not clear from the doc what this actually does. Made no difference anyway.
setting AUTOMOC_MOC_OPTIONS to -Isrc/include or -I/path/to/project/src/include or -I${CMAKE_HOME_DIRECTORY}/src/include Doesn't do anything that I could see.
The great thing about AUTOMOC is that I don't need to know which files actually need to be mocked. In this case however I would need to know all the headers that might have a Q_OBJECT inside, that are included by my source files.
Is there a way to tell AUTOMOC where exactly to look for mockable files?
Did you truly set AUTOMOC_MOC_OPTIONS to -Isrc/include, or to -I/path/to/myproject/src/include? The former probably doesn't exist.
I have always used the MOC macros; it looks like AUTOMOC is something new that is built into CMake.
I usually include all headers when creating a library or executable - i.e.
add_library(foo SHARED source.cpp ../include/some_header.hpp )
I assume that this will allow AUTOMOC to work. It will have the added benefit of causing make to work as expected - rebuilding your library when the header changes.
If you are truly unable to add the file to the add_library command ahead of time, then I think you'll have to write a cmake function to search for #include statements within source.cpp, locate those files, and search them for Q_OBJECT. If they match, add them to a variable - perhaps EXTRA_MOCS. Then, the add_library line becomes
add_library(foo SHARED source.cpp ${EXTRA_MOCS} )