Cmake Linking Shared Library: “No such file or directory” when include a header file from library

怎甘沉沦 提交于 2021-02-07 18:41:44

问题


I am learning to build a library using Cmake. The code structure for building library is like below:

include:  
   Test.hpp       
   ITest.hpp     // interface
src:
   Test.cpp
   ITest.cpp

In CMakeLists.txt, the sentences I used to build library is :

file(GLOB SRC_LIST "src/iTest.cpp" "src/Test.cpp" "include/Test.hpp"
        "include/iTest.hpp"  "include/deadreckoning.hpp")
add_library(test SHARED ${SRC_LIST})
target_link_libraries( test ${OpenCV_LIBS})  // link opencv libs to libtest.so

Then I wrote another test file (main.cpp), copy and paste the library under the same directory, link library and call functions inside the library. This CMakeLists.txt is

cmake_minimum_required(VERSION 2.8)
project(myapp)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -O3 -Wall -ftree-vectorize -ffast-math -funroll-loops")

add_executable(myapp main.cpp)
target_link_libraries(myapp "/home/labUser/test_lib/libtest.so")

The main.cpp compiles and runs succussfully if I don't include the header files inside the library:

#include <iostream>
using namespace std;

int main(){
    cout << "hello world" << endl;
    return -1;
}

But when I include the header file #include "ITest.hpp", it has error:

fatal error: iTest.hpp: No such file or directory
  #include "iTest.hpp"   
compilation terminated.

I don't understand why it happens.I think I have already linked the library successfully because when I run main.cpp without including header file, it doesn't give any "linking" error. And I think apparently the header files are inside the library. Why I can't include it? Can anyone help me figure this out?

Big thanks!


回答1:


You have a couple of issues here.

Propagating headers to users of your target:

Whilst you've added the include file to your library target, you need to let consumers of your library target know how to find the header.

As such, when your app myapp links against your library target test, you need to tell cmake to add ./include to myapp's include search path.

There is a special cmake variable, ${CMAKE_CURRENT_LIST_DIR} which resolves to the path to the directory in which the current CMakeLists.txt being processed is.

In your instance, that is the parent folder of both src and include.

./                    <-- ${CMAKE_CURRENT_LIST_DIR} is this directory
+--- CMakeLists.txt
+--- src/
|    +---Test.cpp
|    +---ITest.cpp
+--- include/
     +---Test.hpp
     +---ITest.hpp

In order to tell cmake to add a path to its include search path you use target_include_directories

For this the path will then be ${CMAKE_CURRENT_LIST_DIR}/include

So the syntax you'd be looking for is:

target_include_directories(test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

Note that this means you don't have to add "include/iTest.hpp" and "include/Test.hpp" to your SRC_LIST glob, as the compiler will be able to find them from the above target_include_directories

Linking to your test library:

Now that you've created your library and added the include directories, to actually use it in your app, you should again use target_link_libraries, but don't specify the path to the generated .so file, instead refer to the name of the library target you created, test

target_link_libraries(myapp test)

Now myapp will know how to find Test.hpp because it will get that information from the "dependency link" you've created between myapp and test

As such, assuming the following directory structure, the following CMakeLists.txt files may work

src/
+--- library/
|    +--- < sources for your shared library >
+--- app/
     +--- < sources for your application >

src/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(myapp)

add_subdirectory(library)
add_subdirectory(app)

src/library/CMakeLists.txt

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} 
    -std=c++11 
    -pthread 
    -O3 
    -Wall 
    -ftree-vectorize 
    -ffast-math 
    -funroll-loops")

find_package(OpenCV REQUIRED)

add_library(test SHARED "src/iTest.cpp src/Test.cpp")
target_link_libraries(test ${OpenCV_LIBS})  // link opencv libs to libtest.so
target_include_directories(test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

src/app/CMakeLists.txt

add_executable(myapp main.cpp)
target_link_libraries(myapp test)


来源:https://stackoverflow.com/questions/47060164/cmake-linking-shared-library-no-such-file-or-directory-when-include-a-header

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!