CMake adding a library - c++

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()

Related

In CLion, header only library: file "does not belong to any project target, code insight features might not work properly"

I have a header-only library project set up with the cmake command:
add_library(my_library INTERFACE)
and I also added
target_sources(my_library INTERFACE ${MY_LIRBARY_HEADER_FILES})
but when I open a source file, I get the warning:
This file does not belong to any project target, code insight features might not work properly
and I lose a lot of the functionality on things like code completion.
What is the proper way to set this up so CLion provides its usual functionality on a header-only library?
Little background
I was having the same problem, albeit the project was not header-only, nevertheless, the open files from inc folder were throwing the aforementioned warning, even though the CMake file clearly marked that folder to be include_directory.
*.hpp files do not belong to ${SOURCE}
include_directories("${PROJECT_SOURCE_DIR}/inc/")
add_subdirectory(src)
add_executable(${EXECUTABLE_NAME} main.cpp ${SOURCE})
Since this is a perfectly valid CMake file and adding the include files to source files is not idiomatic, I did not want to amend the CMake file.
The solution
As described on the official JetBrains Forum, the CMake file is indeed valid and the warning is shown because of the inability of CLion to properly index header files. The suggested workaround extracted from the link is to right-click the folder and Mark directory as | Library Files/Project Sources and Headers.
So, this header isn't includes in executables and CLion notifies you that some code insight features might not work properly. As workaround you can use "Mark directory as" Library Files/Project Source and Headers for folder.
Clion takes information about source files from CMake build system. When you add any cpp file to sources list CMake automatically tell about header with same name. So if cpp/h names differs (or you don't have cpp file at all) you should include header manually.
set(Sources my_lib.cpp)
set(Headers header_of_my_lib.h)
add_executable(superlib ${Sources} ${Headers})
If you don't have any executable you can omit last line, CLion will still know about files
This warning is an IDE issue that Android Studio cannot recognise the current directory if it does not include any source files.
Workaround
Adding am empty source file, e.g empty_xxx.c under the directory in question and adding below line in your corresponding CMakeList.txt
add_library(${TARGET_NAME_XXX} SHARED ${SOME_DIR_HAVING_THIS_WARNING}/empty_xxx.c)
will help get rid of this warning.
You can add the header files to your project like this:
set(SOURCE_FILES main.cpp MyClass1.cpp MyClass1.h MyClass2.cpp MyClass2.h)
You can also set it in multiple steps like so:
set(SOURCE_FILES main.cpp)
set(SOURCE_FILES ${SOURCE_FILES} MyClass1.cpp MyClass1.h)
set(SOURCE_FILES ${SOURCE_FILES} MyClass2.cpp MyClass2.h)
Though as mentioned in the comments, you probably shouldn't be adding the header files to your project at all.

CMake how to include headers without sources?

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.

CMake's equivalent to Visual Studio's Property Sheets (.vsprops)

I'm trying to migrate from Visual Studio towards Jetbrains' (awesome) CLion IDE which uses CMake to organize the projects.
Until now, the transition has been smooth: creating CMake projects and importing them into CLion is easy, and I can begin coding on one plateform then continue on another one without problems.
However, one aspect of Visual Studio that I couldn't find an equivalent to in CMake is property sheets: I use them mainly for holding the include directories' paths and the linking libs for libraries (i.e. one .vsprops file for each library, e.g. OpenCV.vsprops, Boost.vsprops, etc.).
This way, in VS, I could share a library's .vsprops file between different projects without having to configure the paths/libs each time.
Does CMake have a similar mechanism to Visual Studio's property sheets ? How is it possible to store a library's includes/libs in a CMake-parsable file then "import" it in CMakeLists.txt in order to link against the library ?
Basically, what I want to do is:
Create a "cmake property sheet" (for lack of a better name) for a given library.
Then, in CMakeLists.txt, write something like link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...) .
In CMake, libraries can export a package with IMPORTED targets which other buildsystems import using find_package:
http://www.cmake.org/cmake/help/v3.1/manual/cmake-packages.7.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#imported-targets
Instead of 'linking to property sheets', you link to the IMPORTED targets.
target_link_libraries(myTarget Dep1::Dep1 Dep2::Dep2)
Not all libraries create IMPORTED targets, and not all provide cmake config-file packages. In those cases (including OpenCV and Boost), CMake provides find modules:
http://www.cmake.org/cmake/help/v3.0/manual/cmake-developer.7.html#find-modules
which you use with find_package and link to the contents of variables.
Since I really want to make the libraries' inclusion/linking into a one-line command, and as far as my (basic) knowledge of CMake goes, I think that some compromise should be made -- mainly sharing the target name's variable between CMakeLists.txt and the "property sheets". So this is my solution... until someone proposes a simpler/cleaner one:
A CMake property sheet is a .cmake text file,
A well-known variable name --TARGET-- designates the target (i.e. the first argument of add_executable()),
Aside from library-specific commands, a .cmake file contains a call to target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR}) and target_link_libraries(${TARGET} ${LIST_OF_LIBS}),
In order to use/link against a library, call include("path/to/.cmake") in CMakeLists.txt.
I have successfully built and executed a simple program that uses X11 and OpenCV with the following files:
x11.cmake
target_include_directories(${TARGET} PRIVATE "/usr/include/X11")
target_link_libraries(${TARGET} "/usr/lib/x86_64-linux-gnu/libX11.so")
opencv.cmake
# OpenCV-specific stuff
set(OpenCV_DIR "/PATH/TO/OPENCV/INSTALL/DIR/share/OpenCV") # path to OpenCVConfig.cmake
find_package(OpenCV REQUIRED)
# include path
target_include_directories(${TARGET} PRIVATE ${OpenCV_INCLUDE_DIRS})
# linking libs
target_link_libraries(${TARGET} opencv_world opencv_ts)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.4)
project(hello_clion)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
## hello-clion ##############################
# make a new target name
set(TARGET hello-clion)
# find sources
file(GLOB_RECURSE SOURCE_FILES "src/*.cpp" "src/*.hpp")
# declare a target
add_executable(${TARGET} ${SOURCE_FILES})
# link the libraries (to the last-declared ${TARGET}, which should be the last-added executable)
include("x11.cmake")
include("opencv.cmake")
#############################################
main.cpp
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>
#include <opencv2/opencv.hpp>
#include <Xlib.h>
int main_x11()
{
// adapted from: http://rosettacode.org/wiki/Window_creation/X11#Xlib
}
int main_ocv()
{
// adapted from: http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html#source-code
}
int main()
{
using namespace std;
thread tocv(main_ocv);
thread tx11(main_x11);
tocv.join();
tx11.join();
return 0;
}
Now, each time I want to use OpenCV in a project/program, I just have to put include("opencv.cmake") in the corresponding CMakeLists.txt.
This seems to work great, but there could certainly be problems I haven't discovered. (I was worried multiple macros adding the same target_link_libraries would cause "already defined" linking errors , but at least g++ 5.1.0 handles being given the same library name multiple times without error.)
In root CMakeLists.txt, BEFORE add_subdirectory() calls or globs, include:
macro(USES_WX)
include_directories(SYSTEM /usr/local/include/wx-3.0)
include_directories(SYSTEM /usr/local/lib/wx/include/gtk3-unicode-3.0)
link_directories(/usr/local/lib)
add_definitions(-D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread)
target_link_libraries(${TARGET} pthread wx_gtk3u_xrc-3.0 wx_gtk3u_html-3.0 wx_gtk3u_qa-3.0 wx_gtk3u_adv-3.0 wx_gtk3u_core-3.0 wx_baseu_xml-3.0 wx_baseu_net-3.0 wx_baseu-3.0)
endmacro()
(You can make the macro more fancy, like checking for if CMAKE_BUILD_TYPE is "Debug" or "Release" to link to the appropriate libraries, vary preprocessor definitions, etc. See http://www.cmake.org/cmake/help/v3.0/command/if.html)
And have your project's CMakeLists.txt be like this:
set(TARGET myProgramName)
add_executable(${TARGET} myProgramName.cpp)
USES_WX()
^^ The macro call MUST be after add_executable()
And, if you want multiple target support, modify the line in the root CMakeLists.txt section shown above to:
...
target_link_libraries(${ARGV0} pthread wx_gtk3u_xrc-3.0 ...)
...
And have your project's CMakeLists.txt be like this (less lines, but more chance for error):
add_executable(myProgramName myProgramName.cpp)
USES_WX(myProgramName)

Cmake: link openscenegraph to my shared library

I'm new in using CMake, and I need to link openscenegraph library to my shared library.
Part of code responsible for it looks like this:
add_library (MyLib SHARED ${${PROJECT_NAME}_sources})
target_link_libraries(MyLib ${OPENSCENEGRAPH_LIBRARIES})
Im finding osg like this:
find_package(OpenSceneGraph REQUIRED osgDB osgUtil osg osgViewer osgGA osgShadow)
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
add_definitions(${OPENSCENEGRAPH_DEFINITIONS})
And everything looks like it is linking, CMake isn't giving me any errors, but during building with Visual Studio 2010 I got errors like:
fatal error C1083: Cannot open include file: 'osg/Node': No such file or directory
Usually I was finding answers to all my questions without asking them (this is my first question here).
This may be trivial, but can someone tell me what am I doing wrong, and how can I make it work?
This doesn't seems related to linking, but to compile. The error says that MSVC doesn't find the file 'osg/Node' in the list of included directories.
Somewhere in your source code, you probably have an include like
#include "osg/Node"
so compiler will search for a file called 'Node' in the directory called 'osg' in one of the 'include directories'.
In CMake, print the list of include dirs for OpenSceneGraph (after find_package(OpenSceneGraph ...)
message(STATUS "OSG Incl dirs: ${OPENSCENEGRAPH_INCLUDE_DIRS}")
then check this list. If it contains something like C:/path/to/openscenegraph/include then you should import Node using
#include "osg/Node"
If instead you have a folder for each module (ex: C:/path/to/openscenegraph/include/osg) so you must use
#include "Node"
If you don't want to modify includes in your code, then you have to add C:/path/to/openscenegraph/include in your include directories (from CMake script)
include_directories(C:/path/to/openscenegraph/include)

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} )