My Situation
I`m trying to set up a project structure and the build scripts using cmake
but I get an error
that my application is unable to find the header file that I try to include.
I hope that someone can guide me to a solution for this.
Current project
The project ist just an example reduced to one application and one library project. The goal is to have multiple clients and more than one library (some depending on each other).
clients/Desktop
e.g. is an application making use of the core/
library.
The image shows the project structure (screenshot from Visual Studio Code explorer)
Having a folder named like the project in the include folder is to change the includes from Core.h
to Core/Core.h
. Or at least this was the plan. Maybe this is the problem?
Okay, so now the code:
clients\Desktop\src\main.cpp
:
#include "Core/Core.h"
#include <iostream>
int main(int argc, char* argv[]) {
ProjectStructure::Core::Example ex;
ex.sayHello();
}
Core\include\Core\Core.h
:
#ifndef PROJECTSTRUCTURE_CORE_CORE_H
#define PROJECTSTRUCTURE_CORE_CORE_H
#include <iostream>
namespace ProjectStructure {
namespace Core {
class Example {
public:
void sayHello();
};
} // namespace Core
} // namespace ProjectStructure
#endif
Core\src\Core.cpp
:
#include "Core/Core.h"
namespace ProjectStructure {
namespace Core {
void Example::sayHello() {
std::cout << "Hello world.";
}
} // namespace Core
} // namespace ProjectStructure
clients\Desktop\include\CMakeLists.txt
:
ADD_SUBDIRECTORY("Desktop")
clients\Desktop\src\CMakeLists.txt
:
SET(APP_HEADERS
)
SET(APP_SOURCES
"main.cpp"
)
# Make executable
ADD_EXECUTABLE("${PROJECT_NAME}" "${APP_SOURCES}")
TARGET_LINK_LIBRARIES("${PROJECT_NAME}" "Core")
clients\Desktop\CMakeLists.txt
:
# Version check
cmake_minimum_required(VERSION 3.5)
# Project
PROJECT("Desktop" CXX)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include")
ADD_SUBDIRECTORY("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("test")
clients\CMakeLists.txt
:
# Executables
ADD_SUBDIRECTORY("${PROJECTSTRUCTURE_CLIENTS_DIR}/Desktop")
Core\include\CMakeLists.txt
:
ADD_SUBDIRECTORY("Core")
Core\src\CMakeLists.txt
:
SET(LIB_HEADERS
"../include/Core/Core.h"
)
SET(LIB_SOURCES
"Core.cpp"
)
# Make library
ADD_LIBRARY("${PROJECT_NAME}" STATIC "${LIB_SOURCES}")
SET_TARGET_PROPERTIES("${PROJECT_NAME}" PROPERTIES
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}"
)
INSTALL(TARGETS "${PROJECT_NAME}"
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION lib COMPONENT libs
RUNTIME DESTINATION bin COMPONENT libs
LIBRARY DESTINATION lib COMPONENT libs
PUBLIC_HEADER DESTINATION include/${PROJECT_NAME} COMPONENT devel
INCLUDES DESTINATION include
)
Core\CMakeLists.txt
:
# Version check
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
# Project
PROJECT("Core" CXX)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include")
ADD_SUBDIRECTORY("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("test")
And last but not least the top level CMakeLists.txt
:
# Version check
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
# Project
PROJECT("ProjectStructure" CXX)
# Status
MESSAGE(STATUS "Cmake running...")
MESSAGE(STATUS "System: ${CMAKE_SYSTEM}")
MESSAGE(STATUS "System: ${CMAKE_SYSTEM_PROCESSOR}")
MESSAGE(STATUS "Cmake-Version: ${CMAKE_VERSION}")
MESSAGE(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER}")
# Project structure
SET(CMAKE_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/include")
SET(CMAKE_BINARY_DIR "${CMAKE_SOURCE_DIR}/build")
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
SET(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
SET(PROJECTSTRUCTURE_CLIENTS_DIR "${CMAKE_SOURCE_DIR}/clients")
# Prohibit in source builds
IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
MESSAGE(SEND_ERROR "In-source builds are not allowed. Remove generated files.")
ENDIF()
# Output settings
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_COLOR_MAKEFILE ON)
# Build mode
SET(CMAKE_BUILD_TYPE Debug) # Dev
#SET(CMAKE_BUILD_TYPE RelWithDebInfo) # Test
#SET(CMAKE_BUILD_TYPE Release) # Release
# Used features
SET(CMAKE_CXX_STANDARD 14) # -std=c++14
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
# Compiler flags
SET(CMAKE_CXX_FLAGS "-Wall -Wextra")
SET(CMAKE_CXX_FLAGS_DEBUG "-g3 -O0") # Dev
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3") # Test
SET(CMAKE_CXX_FLAGS_RELEASE "-O3") # Release
# Libraries
ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
# Executables
ADD_SUBDIRECTORY("${PROJECTSTRUCTURE_CLIENTS_DIR}")
I'm using out of source builds using the following commands:
cd build
cmake .. -G "MSYS Makefiles"
And then run using:
make
Note: The real project is also containing directories for documentation and some other things.
Also files like .gitignore
and a .travis.yml
(but that is the next thing I have to get working).
The problem:
The cmake
command is working but the make
command tells me that the included file (Core.h
) could
not be found.
I think the problem is in the part where the library gets installed. But I was unable to find the
right way to do it. The solution I posted here is only one from many that I tried.
Additional questions:
1. The CMakeLists marked with an A are empty. They where just added so that every directory has a CMakeLists file. Should i remove them?
2. I would like to use google-test/mock in my projects with tests for each project in the
project/test
folder. I it enough to include google test in the top level CMakeLists to make this
work or do I have to include it in each sub project?
3. Is it good practice to list the source files or to automatically load them? I think listing
them is better even if it is more work. I think this has also advantages for cmake
when reloading
the project. Is this also true for tests? I am thinking about making a test file for each source
file.