问题
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