how include external library in c++ with cmake - c++

I got my directory like:
-lib
-- mylibrary.dll
-- mylibrary.lib
-- mylibrary.exp
-main.cpp
-cmakelist
and i want my cmake to include the library into the main project like following:
link_directories(${CMAKE_BINARY_DIR}/lib)
add_executable(test_app main.cpp)
target_link_libraries(testapp mylibrary)
but the the include do not find the header. I tried find_package but that did not work...
anyone can help me?

You need to use include_directories to point CMake to your header search folders.
Add the given directories to those the compiler uses to search for include files. Relative paths are interpreted as relative to the current source directory.

Related

CMake: Can we specify include directories for a specific set of files not forming an executable or lib?

If I have this source tree:
C:\app:
src:
CMakeLists.txt
main.cpp --> #include "acme/header_only_lib/api.h"
D:\3rdparty\acme\header_only_lib:
api.h --> #include "detail.h"
detail.h
Without using symlink tricks, and without adding files to the 3rdparty folders, if I must retain #include "acme/header_only_lib/api.h" in main.cpp, how should I specify the include directories in CMake such that api.h can see detail.h, without adding global include directory of D:\3rdparty\acme\header_only_lib? The header-only-lib is not an executable nor library target, and its code is not modifiable by me. I also don't want to pollute my global include directories by adding D:\3rdparty\acme\header_only_lib because the filenames inside there are too common and will easily clash with other libraries/future code.
Is there a CMake mechanism where I can say:
Only for D:\3rdparty\acme\header_only_lib\api.h, add D:\3rdparty\acme\header_only_lib as the include directory?
To add a directory to the global list of include directories, you use e.g.
include_directories( ${CMAKE_SOURCE_DIR}/3rdparty )
Note that you should not hardcode absolute paths (like D:\) into your CMakeLists.txt as that makes it impossible to build your project in any other location. CMake offers variables like ${CMAKE_SOURCE_DIR} and ${CMAKE_BINARY_DIR} for just that purpose.
If you want to add a directory to the list of include directories for a specific part of your build only, you use e.g.
target_include_directories( app PRIVATE ${CMAKE_SOURCE_DIR}/3rdparty )
This adds the directory only for the target (executable / library) app.
Note that, if your acme/header_only_lib is supposed to be installed alongside with the app binaries, this approach won't work, as your acme headers would need to "see" each other on the client's machine, which is unlikely if they reside in the acme/header_only_lib subdirectory but address each other without subdirs. That would require your client (who isn't using your CMakeLists.txt for his builds) to add acme/header_only_lib to the include paths for your header lib to work -- you should not do that.
Use include_directories or target_include_directories:
include_directories("D:\3rdparty")
OR with target_include_directories if you want to make this change only for the main target:
add_executable(main main.cpp)
target_include_directories(main PUBLIC "D:\3rdparty")
Then you can just #include "acme/header_only_lib/api.h" or #include <acme/header_only_lib/api.h>
Header only lib
If you want to do this for header-only-lib only, you need to do this in it's CMake file. First add the library as INTERFACE with no source files:
add_library(header-only INTERFACE)
Then include directories for it:
target_include_directories(header-only INTERFACE include-dir-for-header-only)
Then link it to the main target
find_library(HeaderOnly
NAMES header-only
HINTS "D:\3rdparty\path-to-lib"
)
target_link_libraries(main header-only)

Trying to use Boost with CMake in CLion [duplicate]

I am new to cmake and know this question has been asked before, but still cannot find what I am doing wrong. I have an external library with folders /include and lib. The /include folder contains all the headers (.h) and the /lib folder contains all the source (.c) files.
In my project I have this CMakeList.txt file:
cmake_minimum_required(VERSION 3.7)
project(FirstAttempt)
set(CMAKE_CXX_STANDARD 11)
set (EXTRA_LIBS "D:\\libtrading")
include_directories(${EXTRA_LIBS}/include)
link_directories(${EXTRA_LIBS}/include)
set(SOURCE_FILES main.cpp)
add_executable(FirstAttempt ${SOURCE_FILES})
target_link_libraries (FirstAttempt ${EXTRA_LIBS}/lib)
I know that I have to use target_link_libraries to link the source files of the library to my project, but certainly something is missing, but what? I am still receiving the error undefined reference to xxxxxx.
The library I am trying to include in my project is https://github.com/libtrading/libtrading.
Well, I'll try.
First, seems that you are calling link_directories() on the folder which contains header files, while it should be used in order to specify the path where to search libraries for.
Second, target_link_libraries() takes the absolute path of the shared/static library file as the second argument, while you are passing the directory path (well, it seems so).
target_link_libraries() doesn't link to the "source files of the library", - it links to the compiled shared/static library blob.
And, I would also recommend you to save the name of the executable to the variable so that you wouldn't be able to mistype the target name, like so:
set(TARGET FirstAttempt)
add_executable(${TARGET})
As you know, we need all source files to compile. So we need to point out Cmake know where/what are source files.
I think you should add all sources files like this
file(GLOB SOURCES_FILES "lib/*.c" main.cpp)
to add all .c files.
Or, you can add all lib/*.c files separately
file(SOURCES_FILES_LIBS "lib/*.c")
set(SOURCES_FILES main.cpp)
add_executable(FirstAttempt ${SOURCES_FILES_LIBS} ${SOURCES_FILES})

In CLion, header only library: file "does not belong to any project target, code insight features might not work properly"

I have a header-only library project set up with the cmake command:
add_library(my_library INTERFACE)
and I also added
target_sources(my_library INTERFACE ${MY_LIRBARY_HEADER_FILES})
but when I open a source file, I get the warning:
This file does not belong to any project target, code insight features might not work properly
and I lose a lot of the functionality on things like code completion.
What is the proper way to set this up so CLion provides its usual functionality on a header-only library?
Little background
I was having the same problem, albeit the project was not header-only, nevertheless, the open files from inc folder were throwing the aforementioned warning, even though the CMake file clearly marked that folder to be include_directory.
*.hpp files do not belong to ${SOURCE}
include_directories("${PROJECT_SOURCE_DIR}/inc/")
add_subdirectory(src)
add_executable(${EXECUTABLE_NAME} main.cpp ${SOURCE})
Since this is a perfectly valid CMake file and adding the include files to source files is not idiomatic, I did not want to amend the CMake file.
The solution
As described on the official JetBrains Forum, the CMake file is indeed valid and the warning is shown because of the inability of CLion to properly index header files. The suggested workaround extracted from the link is to right-click the folder and Mark directory as | Library Files/Project Sources and Headers.
So, this header isn't includes in executables and CLion notifies you that some code insight features might not work properly. As workaround you can use "Mark directory as" Library Files/Project Source and Headers for folder.
Clion takes information about source files from CMake build system. When you add any cpp file to sources list CMake automatically tell about header with same name. So if cpp/h names differs (or you don't have cpp file at all) you should include header manually.
set(Sources my_lib.cpp)
set(Headers header_of_my_lib.h)
add_executable(superlib ${Sources} ${Headers})
If you don't have any executable you can omit last line, CLion will still know about files
This warning is an IDE issue that Android Studio cannot recognise the current directory if it does not include any source files.
Workaround
Adding am empty source file, e.g empty_xxx.c under the directory in question and adding below line in your corresponding CMakeList.txt
add_library(${TARGET_NAME_XXX} SHARED ${SOME_DIR_HAVING_THIS_WARNING}/empty_xxx.c)
will help get rid of this warning.
You can add the header files to your project like this:
set(SOURCE_FILES main.cpp MyClass1.cpp MyClass1.h MyClass2.cpp MyClass2.h)
You can also set it in multiple steps like so:
set(SOURCE_FILES main.cpp)
set(SOURCE_FILES ${SOURCE_FILES} MyClass1.cpp MyClass1.h)
set(SOURCE_FILES ${SOURCE_FILES} MyClass2.cpp MyClass2.h)
Though as mentioned in the comments, you probably shouldn't be adding the header files to your project at all.

cmake - undefined reference to

I am new to cmake and know this question has been asked before, but still cannot find what I am doing wrong. I have an external library with folders /include and lib. The /include folder contains all the headers (.h) and the /lib folder contains all the source (.c) files.
In my project I have this CMakeList.txt file:
cmake_minimum_required(VERSION 3.7)
project(FirstAttempt)
set(CMAKE_CXX_STANDARD 11)
set (EXTRA_LIBS "D:\\libtrading")
include_directories(${EXTRA_LIBS}/include)
link_directories(${EXTRA_LIBS}/include)
set(SOURCE_FILES main.cpp)
add_executable(FirstAttempt ${SOURCE_FILES})
target_link_libraries (FirstAttempt ${EXTRA_LIBS}/lib)
I know that I have to use target_link_libraries to link the source files of the library to my project, but certainly something is missing, but what? I am still receiving the error undefined reference to xxxxxx.
The library I am trying to include in my project is https://github.com/libtrading/libtrading.
Well, I'll try.
First, seems that you are calling link_directories() on the folder which contains header files, while it should be used in order to specify the path where to search libraries for.
Second, target_link_libraries() takes the absolute path of the shared/static library file as the second argument, while you are passing the directory path (well, it seems so).
target_link_libraries() doesn't link to the "source files of the library", - it links to the compiled shared/static library blob.
And, I would also recommend you to save the name of the executable to the variable so that you wouldn't be able to mistype the target name, like so:
set(TARGET FirstAttempt)
add_executable(${TARGET})
As you know, we need all source files to compile. So we need to point out Cmake know where/what are source files.
I think you should add all sources files like this
file(GLOB SOURCES_FILES "lib/*.c" main.cpp)
to add all .c files.
Or, you can add all lib/*.c files separately
file(SOURCES_FILES_LIBS "lib/*.c")
set(SOURCES_FILES main.cpp)
add_executable(FirstAttempt ${SOURCES_FILES_LIBS} ${SOURCES_FILES})

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>