I need help with write a good CMakeLists.txt for a C++ projects.
I looked for answer, but I found anything. This is Structure of my projects:
MainProj
| ProjLib/
| | include/
| | | proj_lib.h
| | src/
| | | proj_lib.cc
| | CMakeLists.txt
| ProjExec/
| | include/
| | | proj_exec.h
| | src/
| | | proj_exec.cc
| | CMakeLists.txt
| CMakeLists.txt
MainProj CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(MainProj CXX)
# enable C and C++ language
enable_language(C CXX)
# Add sub-directories
add_subdirectory(ProjLib)
add_subdirectory(ProjExec)
ProjLib CMakeLists.txt
set (PROJLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
set (PROJLIB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(PROJLIB_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/src/proj_lib.cc
)
include_directories("${PROJLIB_SOURCE_DIR}")
include_directories("${PROJLIB_INCLUDE_DIR}")
add_library(ProjLib SHARED ${PROJLIB_SRCS} ${PROJLIB_INCLUDE_DIR})
target_include_directories (ProjLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
ProjExec CMakeLists.txt
set (PROJEXEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set (PROJEXEC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(PROJEXEC_SRCS
${PROJEXEC_SOURCE_DIR}/proj_exec.cc
)
include_directories("${PROJEXEC_SOURCE_DIR}")
include_directories("${PROJEXEC_INCLUDE_DIR}")
add_executable(ProjExec ${PROJEXEC_SRCS})
target_link_libraries (ProjExec LINK_PUBLIC ProjLib)
proj_exec.cc
#include "proj_lib.h"
...
And it doesn't found proj_lib.h in proj_exec.cc file. If I need some additional entries in some cmake?
Any help would be appreciated. :)
Your cmake project template looks fine and self-contained. First, I'm going to assume
GAITPARAMS_SRCS
was supposed to bePROJEXEC_SRCS
which is currently pointing at proj_exec.cc contains a main() method. (If you're going to manage a SRCS list, be careful not to add source files at the top of the list, add_executable expects the main function to be in the first entry)Secondly, the problem is in your
ProjLib/CMakeLists.txt
. Try replacing yourtarget_include_directories
call with this:This will propagate the include directory information to the ProjExec when the
target_link_libraries
command is applied. If you don't wan't to do that, I guess you can access via#include <include/ProjLib.h>
but that's just confusing. My recommendation is to add another folder in the include folder (named exactly the same with the cmake folder) and add your headers in it. Like this:This lets you include your headers with a foldername (Not to mention preventing name collision.). Like this:
And to configure your CMakeLists.txt files to match the pattern.
You need to make use of the CMake targets and their properties:
MainProj/CMakeLists.txt:
ProjLib/CMakeLists.txt
ProjExec/CMakeLists.txt
target_link_libraries
makes sure that when building a target, its dependencies' PUBLIC and INTERFACE include directories will be used appropriately.All of the following are valid, but the best option is explained in rubenvb's answer.
You have at least 3 options:
1) Add the following line in ProjExec/CMakeLists.txt:
2) You can extend the visibility of the variable
PROJLIB_INCLUDE_DIR
, by adding theCACHE INTERNAL
keywordsand then use it in ProjExec/CMakeLists.txt:
See How to set the global variable in a function for cmake?
Of course ProjLib must come first in the
add_subdirectory
sequence in the main CMakeLists.txt file.3) I couldn't test this one. If you in ProjLib's CMakeLists.txt use this line:
Then in ProjExec's CMakeLists.txt you can extract the property
INTERFACE_INCLUDE_DIRECTORIES
, and use it:These 2 lines can be compacted in one, using cmake-generator-expressions (untested):
See also target_include_directories and get_target_property.
Other notes:
include_directories
ortarget_include_directories
, not both.include_directories("${PROJLIB_SOURCE_DIR}")
andinclude_directories("${PROJEXEC_SOURCE_DIR}")