简体   繁体   English

使用CMake和C ++处理共享库依赖关系

[英]Handling Shared Library Dependencies with CMake and C++

I have a c++ project that utilizes shared libraries, some of which have dependencies of their own. 我有一个利用共享库的c ++项目,其中一些具有自己的依赖性。 However, I am being forced to include the header files for the shared library dependencies within my main.cpp file. 但是,我被迫在main.cpp文件中包括共享库依赖项的头文件。 I'm assuming that this is an issue with how I have structured my project, but I'm not sure. 我假设这与我的项目结构有关,但我不确定。

Project Structure: 项目结构:

- myproject
|-> foo1
  |-> include
    |-> foo1_stuff.hpp
  |-> src
    |-> main.cpp
  |-> build
  |-> CMakeLists.txt
|-> foo2
  |-> include
    |-> foo2_stuff.hpp
  |-> src
    |-> main.cpp
  |-> build
  |-> CMakeLists.txt
|-> lib
  |-> bar
    |-> include
      |-> bar.hpp
    |-> src
      |-> bar.cpp
  |-> bar_tool
    |-> include
      |-> bar_tool.hpp
    |-> src
      |-> bar_tool.cpp
  |-> CmakeLists.txt

foo1's main.cpp: foo1的main.cpp:

#include <bar_tool.hpp>

int main()
{
    bar_tool tool;
    tool.doStuff();

    return 0;
}

bar_tool.hpp: bar_tool.hpp:

#include <bar.hpp>

class bar_tool
{
public:
    bar_tool();
    ~bar_tool();
    int var;
    void doStuff();
};

bar_tool.cpp: bar_tool.cpp:

#include <iostream>
#include <bar_tool.hpp>

bar_tool::bar_tool() : var(0) {}
bar_tool::~bar_tool() {}

void bar_tool::doStuff()
{
    std::cout << barFunction(var) << std::endl;
}

bar.cpp: bar.cpp:

int barFunction(int value)
{
    return value + 2;
}

Foo1 CMakeLists: Foo1 CMake列表:

cmake_minimum_required(VERSION 3.10.2)
project(foo)

set(PROJECT_ROOT ~/myproject/)
set(
    CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_ROOT}/bin/
)

link_directories(
    /usr/local/lib
    /usr/lib
    ${PROJECT_ROOT}/lib
)

include_directories(
    include
    ${PROJECT_ROOT}/lib/bar_tool/include
)

file(GLOB SOURCES "src/*.cpp")

add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(
    ${PROJECT_NAME}
    bar_tool
)

Shared Libraries CMakeLists: 共享库CMakeLists:

cmake_minimum_required(VERSION 3.10.2)
project(myproject)

set(PROJECT_ROOT ~/myproject/)
set(
    CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${PROJECT_ROOT}/lib/
)

link_directories(
    /usr/local/lib
    /usr/lib
    ${PROJECT_ROOT}/lib
)

include_directories(
    include
    ${PROJECT_ROOT}/lib/bar/include
    ${PROJECT_ROOT}/lib/bar_tool/include
)

# bar library
set(LIB_NAME "bar")
file(GLOB LIB_SRC "${LIB_NAME}/src/*.cpp")
add_library(${LIB_NAME} SHARED ${LIB_SRC})

# bar_tool library
set(LIB_NAME "bar_tool")
file(GLOB LIB_SRC "${LIB_NAME}/src/*.cpp")
add_library(${LIB_NAME} SHARED ${LIB_SRC})
target_link_libraries(
    ${LIB_NAME}
        bar
)

I would expect that using the compiled bar_tool shared library ( libbar_tool.so ) would not require having to include bar.hpp in the include_directories section of foo1's CMakeLists. 我希望使用已编译的bar_tool共享库( libbar_tool.so )不需要在foo1的CMakeLists的include_directories部分中包含bar.hpp However, I get following error if I don't: 但是,如果没有,则会出现以下错误:

In file included from /home/mrd/Development/compile_test/foo/src/main.cpp:1:0:
/home/mrd/Development/compile_test/lib/bar_tool/include/bar_tool.hpp:1:10: fatal error: bar.hpp: No such file or directory
 #include <bar.hpp>
          ^~~~~~~~~
compilation terminated.

Am I not using shared libraries or CMake (or both) correctly? 我没有正确使用共享库或CMake(或两者)吗?

FIX: 固定:

UPDATED Shared Libraries CMakeLists: 更新的共享库CMakeLists:

cmake_minimum_required(VERSION 3.10.2)
project(myproject)

set(PROJECT_ROOT ~/myproject/)
set(
    CMAKE_LIBRARY_OUTPUT_DIRECTORY
    ${PROJECT_ROOT}/lib/
)

# bar library
set(LIB_NAME "bar")
file(GLOB LIB_SRC "${LIB_NAME}/src/*.cpp")
add_library(${LIB_NAME} SHARED ${LIB_SRC})
target_include_directories(
    ${LIB_NAME} PUBLIC
    ${PROJECT_ROOT}/lib/bar/include
)

# bar_tool library
set(LIB_NAME "bar_tool")
file(GLOB LIB_SRC "${LIB_NAME}/src/*.cpp")
add_library(${LIB_NAME} SHARED ${LIB_SRC})
target_include_directories(
    ${LIB_NAME} PUBLIC
    ${PROJECT_ROOT}/lib/bar_tool/include
)
target_link_libraries(
    ${LIB_NAME} PUBLIC
    bar
)

Not sure if this had any effect, but I changed this also: 不知道这是否有效果,但是我也更改了它:

UPDATED Foo1 CMakeLists: 更新的 Foo1 CMakeLists:

cmake_minimum_required(VERSION 3.10.2)
project(foo)

set(PROJECT_ROOT /home/mrd/Development/compile_test)
set(
    CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_ROOT}/bin/
)

add_subdirectory(${PROJECT_ROOT}/lib/ bin)

file(GLOB SOURCES "src/*.cpp")

add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(
    ${PROJECT_NAME}
    bar_tool
)

Any other suggestions are more than welcome! 任何其他建议都值得欢迎!

Since you have the compiled library you do not need to add the paths of the source files. 由于您具有已编译的库,因此无需添加源文件的路径。 All the function calls, external variable access etc will be linked to this precompiled library. 所有函数调用,外部变量访问等都将链接到此预编译的库。

Whereas when you include header file this is not the case. 而当您包含头文件时,情况并非如此。 Make creates a list of dependencies before compilation where it tries to locate all the headers. Make会在编译之前尝试创建所有依赖项的列表,以查找所有标头。 Hence paths of all the headers which are included directly or indirectly must be provided. 因此,必须提供直接或间接包括的所有标题的路径。

In your Shared Libraries CMakeLists.txt file, consider adding the PUBLIC keyword to ensure that the transitive dependencies (ie the bar library) can be propagated to the final target. 在您的共享库CMakeLists.txt文件中,考虑添加PUBLIC关键字以确保可传递依赖项(即bar库)可以传播到最终目标。 Also, modern CMake encourages the use of target_include_directories() instead of include_directories() . 另外,现代CMake鼓励使用target_include_directories()而不是include_directories() Similarly, you should add the PUBLIC keyword here also: 同样,您还应该在此处添加PUBLIC关键字:

target_include_directories(bar PUBLIC
    ${PROJECT_ROOT}/lib/bar/include
)
target_include_directories(bar_tool PUBLIC
    ${PROJECT_ROOT}/lib/bar_tool/include
)

target_link_libraries(
    ${LIB_NAME} PUBLIC
        bar
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM