Visual Studio + CMake's GLOB_RECURSE - c++

I'm browsing a project which has a src directory similar to:
src/
|-- A.cpp
|-- dir/
|-- |-- B.h
|-- |-- B.cpp
In A.cpp they include B.h as such:
// In A.cpp:
#include "B.h"
In the visual studio 2010 solution generated with CMake this compiles just fine, and there exists no conflict. However, if I make a new project (not from CMake, but manually) and do the include as above, VS will not find B.h. I.e.:
// In A.cpp (non-CMake project version)
#include "B.h" // Error: File not found (VS does not search the
//sub-directory when name is surrounded by "").
#include "dir/B.h" // Works: sub-directory specified.
The CMake file uses GLOB_RECURSE (which I assume is the reason the above works, please correct me if I'm wrong), and simplified it looks something like this:
cmake_minimum_required (VERSION 2.6)
project (cmake_test)
file(GLOB_RECURSE lib_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp *.h)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/dir
)
add_library(lib STATIC
${lib_SRCS}
)
target_link_libraries(lib)
I've been examining the difference of the solution generated by CMake and the one I manually created, but I can't seem to find it.
My question is, in other words, how I could accomplish having VS find my B.h without the relative path included as the solution generated with CMake displays, without actually using CMake (such as by some option or configuration in my Visual Studio Project).

The part that makes it work is
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/dir
)
Your dir/ directory is added to the include directories. In Visual Studio you need to go to project properties at C/C++->General->Additional Include Directories and add dir/.

Related

Cmake include directories

I have a folder structure like this: Project/Libraries/Math, Project/Libraries/Math2.
In the Project folder I have the main.cpp, and the CMakeLists.txt with the following content:
cmake_minimum_required (VERSION 2.6)
project (CppMain)
add_executable(CppMain main.cpp)
include_directories(${CMAKE_CURRENT_SOURCE_DIR))
In the Math folder I have the header MyVectors.h and in the Math2 folder I have MyMatrices.h, that I would like to include in the main.cpp file, and this works as:
#include "Libraries/Math/MyVectors.h"
#include "Libraries/Math2/MyMatrices.h"
The problem is that also the header MyVectors.h includes the header MyMatrices.h at the same way, but the linker doesn't find it. What can I modify in the CMakeLists to fix this problem?
This seems to be a classical case of relative paths. You have done this to include the files in main.cpp
#include "Libraries/Math/MyVectors.h"
#include "Libraries/Math2/MyMatrices.h"
In order for a file to access is parent directory you can use ../ The following lines should be introduced to MyVectors.h:
#include "../Math2/MyMatrices.h"
What does it signify? Well your file MyVectors.h is in Math folder when you use ../ it takes you to the parent directory of Math which is Libraries. From there you can simply follow the path to your required directory.
More detail can be found on this answer by me on another question: https://stackoverflow.com/a/35910234/2555668

Directory Structure for Library CMake Projects

I've an Application project Demo which depends on my Shared library Hello. Library Hello should be redistributable. So I need to distribute the headers of Hello as well as use it in my Demo projects. What directory structure and CMake configuration should I use ? I previously had a flat structure and Hello was a header only subdirectory with no CMakeLists.txt. Now I am planning this directory structure.
Demo
main.cpp
app.h
app.cpp
CMakeLists.txt
Hello
includes
matrix.hpp // header only
diagonal.hpp
point.hpp
store.h
analyzer.h
sources
store.cpp
alanyzer.cpp
CMakeLists.txt
Previously the analyzer was header-only which is now splited in header and source. I am mixing header-only things. Is this a good structure ? But I prefer to use the nice #include <Hallo/matrix.hpp> not the ugly one #include "Hallo/includes/matrix.hpp" or just #include "matrix.hpp". I expect this library Hello will be used for other applications and libraries as well.
Demo/CMakeList.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(Demo)
ADD_SUBDIRECTORY(Demo)
SET(Demo_HEADERS
app.h
)
SET(Demo_SOURCES
app.cpp
main.cpp
)
INCLUDE_DIRECTORIES(${Hello_INCLUDE_DIRS})
# ^^^^ Is this how I need to access the headers ? or just ADD_SUBDIRECTORY() will work
ADD_EXECUTABLE(Demo ${Demo_SOURCES} ${Demo_HEADERS})
TARGET_LINK_LIBRARIES(Demo Hello)
Hello/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(Hello)
FIND_PACKAGE(Boost COMPONENTS filesystem program_options thread system serialization date_time chrono REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
SET(Hello_SOURCES
store.cpp
analyzer.cpp
)
INCLUDE_DIRECTORIES((${HELLO_SOURCE_DIR}/includes)
# ^^^^ Is this how I need to access the headers ?
ADD_LIBRARY(Hello ${Hello_SOURCES})
TARGET_LINK_LIBRARIES(Hello ${Boost_LIBRARIES})
I am kind of confused with all this as there is no one specific way to do these all.
--- EDIT ---
Should I have this structure ? or Do some other libraries generally use this structure ? or what are the structures generally practiced ?
hallo
includes
hallo
sources
If you want to access your headers like this:
#include <matrix.hpp>
then you need to include directories. I suggest you the next:
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Hello/includes)
Your mistake is that you never defines Hello_INCLUDE_DIRS variable in global scope, only in local. So your include do nothing. CMAKE_SOURCE_DIR is always defined and safe to use for includes. Thus you need either define Hello_INCLUDE_DIRS in global scope or use INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Hello/includes).
Usage is up to the developer as always. I prefer the structure:
+ Project Root
+-> Build
+-> Documentation
+-> Include
+-> Source
+-> Test
+ CMakeLists.txt
Then I can preset in root CMakeLists.txt next useful variables:
SET(Project_Include_Dir "${CMAKE_SOURCE_DIR}/Include")
SET(Project_Source_Dir "${CMAKE_SOURCE_DIR}/Source")

How to order/design a shared library with CMake that use higher includes

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>)
What I've done to solve this problem is have a top level CMakeLists.txt that sets variables that will point to the top of the project directory. In your case this will be the directory containing Application and MyLibrary.
ProjectRoot
CMakeLists.txt // top
Application/
CMakeLists.txt
main.cpp
MyLibrary/
CMakeLists.txt
Header.h
foo/
Foo.h (#include <Header.h>
bar/
Bar.h (#include <Header.h> #include <foo/Foo.h>)
# Top level cmakelists
project (myproject)
set (my_app_src_top "${CMAKE_CURRENT_SOURCE_DIR}" )
set (my_app_build_top "${CMAKE_CURRENT_BINARY_DIR}" )
add_subdirectory( MyLibrary )
add_subdirectory( Application )
Then in your subdirectory CmakeLists, you can add include paths like this:
include_directories( ${my_app_src_top}/MyLibrary )
I also just define a project at the top level CMakeLists.txt. In this case you may be able to reference ${PROJECT_SOURCE_DIR}, but if you define projects in sub directories, then I think this will get reset based on the last sub directory you built.
I think with this structure you should be able to
#include <foo/Foo.h>
#include <bar/Bar.h>
Plus you may want to add ./ to the include_directories for each sub dir.

Can't include an external library in another header with Cmake

I have a project setup with the following folder structure:
External
Boost
Poco
Libraries
Lib1
src
lib1.cpp
CMakeLists.txt
Lib2
src
CMakeLists.txt
Projects
Project1
src
CMakeLists.txt
Project
src
CMakeLists.txt
Public
Lib1
lib1.h
Lib2
Basically I have a folder for external libraries like Poco or Boost. Next to that I have a projects folder. Each project has it own independent source files and have the possibility to include/link one or more of the libs in the Libraries folder. Each library has also a private src folder and a public header folder.
The CMakeLists.txt file of a library looks something like this (${PUBLIC_DIRECTORY} is set to the correct public folder)
set(Sources
"${PUBLIC_DIRECTORY}/lib1.h"
"src/lib1.cpp"
)
include_directories("../../External/Boost")
add_library(Lib1 ${Sources})
link_directories("${CMAKE_CURRENT_BINARY_DIR}/Lib1")
The problem happens when I try to include a boost header like boost/lexical_cast.hpp.
When I include this in lib1.cpp, everything compiles. But when I do the same in lib1.h, I get the error: boost/lexical_cast.hpp: No such file or directory.
Does anyone know how to fix this problem?
thanks in advance
Turning my comments into an answer
When you #include "boost/..." in a .h file, make sure that all projects which use that .h file are correctly configured to use Boost. Bear in mind that from a compiler's point of view, .h files don't really exist - their content is textually pasted into the .cpp file, so only the .cpp file's settings (such as include paths) apply.

CMake and handling subfolder header files

I'm trying to set up my project to build several dynamic libraries that encompass its complete functionality. There are subfolders for each library. The subfolder libraries are dependent on each other, so they must reference functions from each other. I seem to have managed to get CMake to run without errors on the project, but when I go to build, I have trouble with my headers finding each other. It seems at build time, the include path isn't set up correctly. How can I fix this? Are there additional steps I need to take to set up the include path correctly?
The structure looks something like this
root
CMakeLists.txt
bin
lib
lib0
CMakeLists.txt
lib0.h
lib0.cpp
lib1
CMakeLists.txt
lib1.h
lib1.cpp
...
In the CMakeLists.txt for the root directory I have declarations like this:
set(ROOT /blah/blah/root)
include_directories(${ROOT}/lib0)
include_directories(${ROOT}/lib1)
add_subdirectory(lib0)
add_subdirectory(lib1)
In the CMakeLists.txt for the subfolders, I have:
set(lib0_SOURCES "")
list(APPEND lib0_SOURCES lib0.cpp)
add_library(lib0_lib ${lib0_SOURCES})
And my headers for the libraries look like (suppose this is lib0.h):
#include "lib1/lib1.h"
...
CMake runs fine with no errors, but when I go to compile, I get an error like:
In file included from /blah/blah/root/lib0/lib0.cpp:1:0:
/blah/blah/root/lib0/lib0.h:1:30: fatal error: lib1/lib1.h: No such file or directory
You told GCC to #include the file "lib1/lib1.h". When you build, CMake will ask to look for extra headers in "${ROOT}/lib0" and "${ROOT}/lib1"
So, GCC is trying "${ROOT}/lib0/lib1/lib1.h" and "${ROOT}/lib1/lib1/lib1.h" Yup, cant work.
To fix it:
you can use in your root CMakeLists.txt : include_directories(".")
keep your CMakeLists but #include the file "lib1.h"
remove the include_directories in CMakeLists and #include the file "../lib1/lib1.h"
IMO, I'd go for the first option!
You need to use the double naming scheme or specify the base directory as the include path:
root
CMakeLists.txt
bin
lib
lib0
CMakeLists.txt
lib0.cpp
lib0
lib0.h
lib1
CMakeLists.txt
lib1.cpp
lib1
lib1.h
...
I would ask CMake to just consider the ROOT directory for C/C++ include look-ups:
set(ROOT /blah/blah/root)
include_directories(${ROOT})
add_subdirectory(lib0)
add_subdirectory(lib1)
Then, in C/C++, use angle braquets ('<' and '>') rather than double quotes ('"'):
#include <lib1/lib1.h>