At the moment I have a shared library with around ~30 classes. My idea is to group them into subdirectories, means a subdirectory contains classes that are more or less equals/have the same content (ui, utils, backend etc).
But I ran into a typical problem: I have some export defines/constants that are shared across the project and my first question was: How to include this header from a header in a subdirectory ?
I often see the #include ../Header.h
solution but my personal opinion is, that this is quite ugly.
So what I did:
Application/
main.cpp
MyLibrary/
Header.h
foo/
Foo.h (#include <Header.h>
bar/
Bar.h (#include <Header.h> #include <foo/Foo.h>)
And in my library CMakeList I add and include_directory
with the root directory of the MyLibrary directory.
My application executable CMakeLists.txt looks something like this (pseudo CMake)
project(application)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)
add_executable(application main.cpp)
target_link_libraries(application mylibrary)
And in the main.cpp
I include like this:
#include <MyLibrary/Header.h>
#include <MyLibrary/bar/Bar.h>
The problem now is, that the compiler doesn't know where to look for the included <> INSIDE the library, for example the Header.h includation inside foo.bar points to ${CMAKE_CURRENT_SOURCE_DIR}/Header.h
- but CMAKE_CURRENT_SOURCE_DIR
is the path of the application and NOT of the library
So I have to add the directory of the library that the compiler can found the other headers of the library (Header in the library that includes another Header in the library via <> and not "")
So I end up with something like this:
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../MyLibrary)
And now Bar.h can find foo/Foo.h, otherwise something goes wrong. And this is even more ugly
So my question: Is there a good/tricky way to solve this problem in CMake ? Or can someone give me tipps about a better project structure ? The solution has to run under MSVC, GCC and clang.
If you think about how your library will look after install you may get some hints about structure. So for example:
<install-prefix>/Foo/foo.hpp -> has `#include <Boo/boo.hpp>`
<install-prefix>/Boo/boo.hpp -> has `#include <Bar/bar.hpp>`
<install-prefix>/Bar/bar.hpp -> has `#include <Bar/details/utils.hpp>`
<install-prefix>/Bar/details/utils.hpp
this is possible layout before install done:
<source-dir>/Sources/Foo/foo.hpp
<source-dir>/Sources/Boo/boo.hpp
<source-dir>/3rdParty/Bar/bar.hpp
<source-dir>/3rdParty/Bar/details/utils.hpp
hence CMakeLists.txt
must contains (or better target_include_directories):
include_directories(<source-dir>/Sources)
include_directories(<source-dir>/3rdParty)
so for your case, IMHO it must be something like that:
Application/
main.cpp
MyLibrary/
Header.h
foo/
Foo.h (#include <MyLibrary/Header.h>
bar/
Bar.h (#include <MyLibrary/Header.h> #include <MyLibrary/foo/Foo.h>)