Cmake链接共享库:“无此文件或目录";当包含库中的头文件时 [英] Cmake Linking Shared Library: "No such file or directory" when include a header file from library

查看:75
本文介绍了Cmake链接共享库:“无此文件或目录";当包含库中的头文件时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习使用Cmake构建一个库.构建库的代码结构如下:

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

在CMakeLists.txt中,我用来构建库的句子是:

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

然后,我编写了另一个测试文件(main.cpp),将库复制并粘贴到同一目录下,链接库并在库内调用函数.此CMakeLists.txt是

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")

如果我没有在库中包含头文件,则main.cpp会成功编译并运行:

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;
}

但是当我包含头文件 #include"ITest.hpp" 时,它会出现错误:

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.

我不明白为什么会发生.我想我已经成功链接了库,因为当我运行main.cpp而不包含头文件时,它没有给出任何链接"错误.而且我认为头文件显然在库中.为什么我不能包含它?谁能帮我解决这个问题?

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?

非常感谢!

推荐答案

您在这里遇到了几个问题.

You have a couple of issues here.

向目标用户传播标题:

在将包含文件添加到库目标后,您需要让库目标的消费者知道如何查找标头.

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.

这样,当您的应用程序 myapp 链接到库目标 test 时,您需要告诉cmake将 ./include 添加到 myapp的包含搜索路径.

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.

有一个特殊的cmake变量, $ {CMAKE_CURRENT_LIST_DIR} 解析为当前正在处理的 CMakeLists.txt 所在目录的路径.

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.

在您的实例中,这是 src include 的父文件夹.

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

为了告诉cmake在其包含搜索路径中添加路径,请使用

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

为此,路径将为 $ {CMAKE_CURRENT_LIST_DIR}/include

所以您要查找的语法是:

So the syntax you'd be looking for is:

target_include_directories(test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

请注意,这意味着您不必在中添加"include/iTest.hpp" "include/Test.hpp" SRC_LIST glob,因为编译器将能够从上述 target_include_directories

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

链接到您的测试库:

现在,您已经创建了库并添加了包含目录,要在应用中实际使用,您应该再次使用 target_link_libraries ,但不要指定生成的 .so 文件的路径,而是引用您创建的库目标的名称 test

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)

现在 myapp 将知道如何查找 Test.hpp ,因为它将从依赖关系"链接中获取该信息.您是在 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

这样,假设采用以下目录结构,则以下CMakeLists.txt文件可能会起作用

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

src/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(myapp)

add_subdirectory(library)
add_subdirectory(app)

src/library/CMakeLists.txt

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

src/app/CMakeLists.txt

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

这篇关于Cmake链接共享库:“无此文件或目录";当包含库中的头文件时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆