Cmake链接共享库:“无此文件或目录";当包含库中的头文件时 [英] Cmake Linking Shared Library: "No such file or directory" when include a header file from library
问题描述
我正在学习使用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
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)
请注意,这意味着您不必在中添加
glob,因为编译器将能够从上述"include/iTest.hpp"
和"include/Test.hpp"
SRC_LIST 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屋!