CMAKE : How to put absolute path in include directories - cmake

First, I am sorry if the question has been answered but I couldn't find any solution.
I am trying to compile a simple program with cmake. But I can't seem to include absolute paths.
My project (located in C:/path/to/my/project for the understanding) is simple with an include directory with header files. However, I must include another directory completely somewhere else.
My include_directories looks like this:
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "C:/path/to/my/other/directory/include")
However when I do :
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
message(STATUS "dir='${dir}'")
endforeach()
To check my include directories I have the following answer:
-- dir='/c/path/to/my/project/include'
-- dir='/c/path/to/my/project/C:/path/to/my/other/directory/include'
So cmake interprets the paths as relative to my project folder.
How can I force cmake to interpret them as absolute ?
I am using cmake v3.17.3.
EDIT
I have tried doing so but it doesn't seem to work either since the path is not appended to the INCLUDE_DIRECTORIES property of my target.
add_executable(app src1.c src2.c)
target_include_directories(app BEFORE PRIVATE "C:/path/to/my/other/directory/include")
Thank you by advance.

So after some research the answer is :
add_executable(app src1.c src2.c)
target_include_directories(app BEFORE PRIVATE "/C/path/to/my/other/directory/include")
The path I was referring to was wrong since I am on msys. Therefore c:/ should become /c/.

You can also write the path as:
add_executable(app src1.c src2.c)
target_include_directories(app BEFORE PRIVATE "C:\\path\\to\\my\\other\\directory\\include")

Related

Relative paths not recognized with CMake

I'm new to C++ and I would like to use the Pytorch library in C++. The tutorial can be seen here https://pytorch.org/cppdocs/installing.html
I have an issue with my /home/local/CLionProjects/MachineAI/CMakeLists.txt file
cmake_minimum_required(VERSION 3.2)
project(MachineAI)
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/libtorch)
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}" )
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
This produces a lot of errors but they mostly seem to have the same problem. It's not able to find a specific file. Here's an example:
CMake Error at libtorch/share/cmake/Caffe2/Caffe2Config.cmake:14 (include):
include could not find requested file:
public/utils.cmake
The error is suggesting the wrong path is provided. If I take a look inside the libtorch/share/cmake/Caffe2/Caffe2Config.cmake, the problem line is:
include("public/utils.cmake")
It cannot find the file even though the file is located at the correct relative path libtorch/share/cmake/Caffe2/public/utils.cmake
If I replace the path with an absolute path, the error goes away:
include("/home/local/CLionProjects/MachineAI/libtorch/share/cmake/Caffe2/public/utils.cmake")
Here is the screenshot of relevant files for better orientation:
I would like to know if there's a way to fix the CMakeLists.txt file at the top so that Caffe2Config.cmake will be able to find the files through the relative path.

target_include_directories - INTERFACE doesn't export an include path

I have created a very simple cmake project for testing cmake features. The project directory contains two libraries. I would like to export MyLibA include path.
The main CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(TestProject)
add_subdirectory(MyLibA)
add_subdirectory(MyLibB)
MyLibA CMakeLists.txt:
add_library(MyLibA SHARED)
target_sources(MyLibA PRIVATE fileA.h fileA.cpp)
target_include_directories(MyLibA INTERFACE "${CMAKE_SOURCE_DIR}/MyLibA")
MyLibB CMakeLists.txt:
add_library(MyLibB SHARED)
target_sources(MyLibB PRIVATE fileB.h fileB.cpp)
target_link_libraries(MyLibB PRIVATE /home/user/MyProjects/CmakeTestProject/build/MyLibA/libMyLibA.so)
I have exported an include path using INTERFACE keyword but the following include in fileB.h:
#include "fileA.h"
is not found. What am I doing wrong ?
What am I doing wrong?
Several things:
Never put absolute paths in your CMakeLists.txt and always link to targets rather than library files.
# Linking to a target propagates usage requirements, like include paths.
target_link_libraries(MyLibB PRIVATE MyLibA)
CMAKE_SOURCE_DIR is not what you think. It refers always to the top-level build directory, which is a bad assumption if your project might be an add_subdirectory or FetchContent target. Your usage can be replaced by:
# Not optimal, see below.
target_include_directories(MyLibA INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
Missing $<BUILD_INTERFACE:...> on include path, if you intend to export your targets. When targets are exported, their properties are copied verbatim to the output. Not guarding the local include path with $<BUILD_INTERFACE:...> will break users of the exported target.
target_include_directories(
MyLibA
INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)
Instead of
target_link_libraries(MyLibB PRIVATE <path/to/MyLibA/file>)
use
target_link_libraries(MyLibB PRIVATE MyLibA)
This is how CMake is intended to be used: when link with the library target, CMake automatically transforms that into the path and actually propagates all interface properties of the target.

Providing include directory outside source folder for static library users

I am developing a simple static C library for learning purposes using cmake.
Some projects like GLFW provide an include folder on the root, so library users can copy it and use it as an include directory.
In my library, I want to have an include folder on the root, so when I use the library on other projects, I can just copy this folder and set it as an include directory.
Here is a simplified folder structure of my library:
include
+--mylib.h
src
+--myheader.h
+--mysource.c
+--CMakeLists.txt
CmakeLists.txt
The src folder has my headers and implementation files, and a CMakeLists.txt for building a static library out of mysource.c.
The CMakeLists on the root folder just sets the project and adds src as a subdirectory.
I want the mylib.h file to have a #include <myheader.h>.
Here's a detour to talk about how I want to use it when it's done.
The idea is that when using the lib on another project, I can have something like this:
deps
+--include
+--mylib.h
src
+--main.c
And in the main.c file, include mylib.h and use what's defined on myheader.h
Here the detour ends, and I'm talking about my actual lib project again.
How can I achieve this using cmake? As far as I know, the mylib.h file needs to know it's including files from the src diretory, but I see no way of setting that, as for exemple in GLFW this directory does not have a CMakeLists.txt.
I am gonna quess that this is a design issue since it would make sense to you if you would have installed the library to a system before you tried to use it. That is, not using add_subdirectory() but find_library() at usage.
First, if you are using a external library, but not installing it, you would include all files in you deps-folder. All files then include source-files and so on and will be compiled besides you main.c. This is done with add_subdirectory(deps/MyLib) and later also included in you main-project.
Example:
add_subdirectory(deps/MyLib EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE MyLib)
target_include_directories(${PROJECT_NAME} PRIVATE MyLib)
If you do not want to compile it all the time, then you must instruct cmake where it can find headers and library-files. Preferred way is to use find_library() which does some magic for you. Since you do not mention any installation i will assume that it does not exist and your only option is then to use add_subdirectory().
"I can just copy this folder and set it as an include directory."
CMake wants to handle these things for you so you should never copy headers around. You should either use add_subdirectory() to include a project/headers or make use of the find_library() which make sure you find where the headers are in the system.
I suggest that you push yourself to learn howto install a library into a system and how to utilize it later, but only by using find_library(). Then the library will be global for all projects and also not duplicated.
Adding some kind of psudo-code in hope it all makes more sense. Although it is around add_subdirectory() since the code for installing is quite large unfortunately.
CMakeLists.txt for main.c
cmake_minimum_required(VERSION 3.8)
project(MyLibTest)
add_executable(${PROJECT_NAME}
src/main.c
)
add_subdirectory(external/MyLib EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE MyLib)
target_include_directories(${PROJECT_NAME} PRIVATE MyLib)
CMakeLists.txt for library
cmake_minimum_required(VERSION 3.8)
project(MyLib)
add_library(${PROJECT_NAME} STATIC
src/MyLib.c
)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
The structure for the project would then be:
/
external/MyLib
external/MyLib/src
MyLib.c
external/MyLib/include
MyLib.h
src
main.c
CMakeLists.txt

CMake system include search path

I'm wondering how I would go about adding an include directory to the system search path for a CMake project. Particularly, I've some source that I'm trying to build a CMake project for.
The source is not mine, and so I don't really want to modify it.
The source has the following include directive:
#include <foo/bar.h>
So I need to add the directory containing foo to my search path. Is this something I can set within the CMakeLists.txt?
you can use include_directories(..) to set directories that will be used for all targets, or add include directories only to a specific target with target_include_directories or set_property:
set(foo_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/foo
${CMAKE_SOURCE_DIR}/whatever)
set_property(TARGET YourTarget PROPERTY INCLUDE_DIRECTORIES ${foo_INCLUDE_DIRS})
target_include_directories(<target> [SYSTEM] [BEFORE <INTERFACE|PUBLIC|PRIVATE> [items1...]
#or
include_directories([AFTER|BEFORE] [SYSTEM] ${foo_INCLUDE_DIRS})

Add executable from parent directory cmake

I'm trying to compile executable files in a subdirectory project/model/tests for testing and need to link my model files which reside at project/model. However, I can't get it to work. I've successfully added the parent directory but cmake keeps telling me no source file found for foo.cpp, which is in the parent directory, while bar.cpp, which is in the current directory, is added correctly.
cmake_minimum_required(VERSION 2.6)
# get parent directory
get_filename_component(MODEL_DIR ${CMAKE_CURRENT_SOURCE_DIR} PATH)
# Locate GTest
find_package(GTest REQUIRED)
# Add parent directory
include_directories(${GTEST_INCLUDE_DIRS} ${MODEL_DIR})
link_directories(${MODEL_DIR})
# all included directories are printed out correctly
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
message(STATUS "dir='${dir}'")
endforeach()
# foo.cpp, which is in the parent directory is not found
add_executable(runTests foo.cpp bar.cpp)
target_link_libraries(runTests ${GTEST_LIBRARIES} pthread)
Thank you.
When files listed in add_executable() and add_library() are given as relative paths (which they almost always are), they are interpretedd relative to CMAKE_CURRENT_SOURCE_DIR. In other words, you have to do one of these:
add_executable(runTests ../foo.cpp bar.cpp)
Or:
add_executable(runTests ${MODEL_DIR}/foo.cpp bar.cpp)
Side note: it's almost never a good idea to use link_directories(); that command is genrally more trouble than it's worth. The preferred alternative is to provide full paths to target_link_libraries() where necessary.