使用CMAKE在一个项目中包括并访问多个.SO文件和标题

发布于 2025-02-09 23:27:26 字数 2670 浏览 1 评论 0原文

我有一个简单的foobar项目,其目录布局如下:

.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── Foo
    │   ├── CMakeLists.txt
    │   ├── foo.cpp
    │   └── foo.h
    └── Bar
        ├── CMakeLists.txt
        ├── bar.cpp
        └── bar.h

其中foo是独立的,但bar取决于foo >并且应该能够#include< foo/foo.h>

我的顶级cmakelists.txt文件是:

# Specify cmake version
cmake_minimum_required(VERSION 3.10)

# Set the project name
project(foobar VERSION 0.1.0)

# Specify the C++ standard
set(CMAKE_CXX_COMPILER /usr/bin/g++)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")

# Set location for .so files
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")

# Set location for executables
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

# Add libraries
add_subdirectory(src)

# Install library
install(TARGETS Foo Bar LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

我的src celve是:

add_subdirectory(Foo)
add_subdirectory(Bar)

我的foo celver is:

add_library(Foo SHARED foo.cpp)

最后我的bar级别是:

add_library(Bar SHARED bar.cpp)
add_dependencies(Bar Foo)
target_link_libraries(Bar Foo)

调用cmake顺利进行,但是在make上,我得到以下内容:

Scanning dependencies of target Foo
[ 25%] Building CXX object src/Foo/CMakeFiles/Foo.dir/foo.cpp.o
[ 50%] Linking CXX shared library libFoo.so
[ 50%] Built target Foo
Scanning dependencies of target Bar
[ 75%] Building CXX object src/Bar/CMakeFiles/Bar.dir/bar.cpp.o
In file included from /home/drjrm3/code/cmake_app/src/Bar/bar.cpp:1:
/home/drjrm3/code/cmake_app/src/Bar/bar.h:3:10: fatal error: Foo/foo.h: No such file or directory
    3 | #include <Foo/foo.h>
      |          ^~~~~~~~~~~
compilation terminated.
make[2]: *** [src/Bar/CMakeFiles/Bar.dir/build.make:63: src/Bar/CMakeFiles/Bar.dir/bar.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:160: src/Bar/CMakeFiles/Bar.dir/all] Error 2
make: *** [Makefile:130: all] Error 2

这表明我没有正确地制作foo可见bar以我希望的方式。

需要更改的内容,以便每个人都可以将它们内置到孤立的共享对象库中,但是bar取决于foo和can &lt; foo/foo/foo.h&gt; 在该子组件中可以看到吗?

请注意,我制作这些共享对象的选择是因为这只是一个更大的项目的一个最小示例,在该项目中,我有多个组件和多个应用程序,但想为这个问题做一个最小的示例。实际上,我在 github 任何人都有兴趣。

I have a simple foobar project which has a directory layout as follows:

.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── Foo
    │   ├── CMakeLists.txt
    │   ├── foo.cpp
    │   └── foo.h
    └── Bar
        ├── CMakeLists.txt
        ├── bar.cpp
        └── bar.h

Where Foo is standalone but Bar depends on Foo and should be able to #include <Foo/foo.h>.

My top level CMakeLists.txt file is:

# Specify cmake version
cmake_minimum_required(VERSION 3.10)

# Set the project name
project(foobar VERSION 0.1.0)

# Specify the C++ standard
set(CMAKE_CXX_COMPILER /usr/bin/g++)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")

# Set location for .so files
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")

# Set location for executables
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

# Add libraries
add_subdirectory(src)

# Install library
install(TARGETS Foo Bar LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

my src level is:

add_subdirectory(Foo)
add_subdirectory(Bar)

my Foo level is:

add_library(Foo SHARED foo.cpp)

and finally my Bar level is:

add_library(Bar SHARED bar.cpp)
add_dependencies(Bar Foo)
target_link_libraries(Bar Foo)

Invoking cmake goes OK, but upon make I get the following:

Scanning dependencies of target Foo
[ 25%] Building CXX object src/Foo/CMakeFiles/Foo.dir/foo.cpp.o
[ 50%] Linking CXX shared library libFoo.so
[ 50%] Built target Foo
Scanning dependencies of target Bar
[ 75%] Building CXX object src/Bar/CMakeFiles/Bar.dir/bar.cpp.o
In file included from /home/drjrm3/code/cmake_app/src/Bar/bar.cpp:1:
/home/drjrm3/code/cmake_app/src/Bar/bar.h:3:10: fatal error: Foo/foo.h: No such file or directory
    3 | #include <Foo/foo.h>
      |          ^~~~~~~~~~~
compilation terminated.
make[2]: *** [src/Bar/CMakeFiles/Bar.dir/build.make:63: src/Bar/CMakeFiles/Bar.dir/bar.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:160: src/Bar/CMakeFiles/Bar.dir/all] Error 2
make: *** [Makefile:130: all] Error 2

which shows me that I am not properly making Foo visible to Bar in the way that I'm hoping to.

What needs to change so that these can each be built into isolated shared object libraries but Bar depends upon Foo and can <Foo/foo.h> can be visible from within that subcomponent?

Note that my choices for making these shared objects is because this is just a minimal example of a bigger project where I have multiple components and multiple apps but wanted to make a minimal example for this question. In fact I have this example up on Github is anyone is interested.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谈场末日恋爱 2025-02-16 23:27:26

这里的关键概念是属性可见性。 Cmake中有两种类型:

  1. 私有:属性会影响正在构建的目标。
  2. 接口:该属性会直接或通过target_link_libraries(... interface ...)直接或过渡地链接到的目标。

public可见性只是两个 的速记。


所以。酒吧的构建应该看起来像:

add_library(Bar SHARED bar.cpp)
target_link_libraries(Bar PUBLIC Foo)

我们在此处使用public可见性,因为酒吧的标题包括foo的标头。也就是说,链接到Bar的库也需要了解FOO。

现在,我们像这样构建foo:

add_library(Foo SHARED foo.cpp)
target_include_directories(Foo PUBLIC "
lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>")

魔术的主要位是$&lt; build_interface:...&gt; Generator Expression。这样可以防止当您最终使用install(导出)创建find_package -compatible cmake时,可以防止包含目录(这是通往构建计算机某个地方的绝对路径)。这些库的包装。

否则,我们只是依靠$ {cmake_current_source_dir}/..将从foo bar (以及任何东西)传播。链接到bar),因为此路径位于接口 foo的接口中。

The key concept here is property visibility. There are two types in CMake:

  1. PRIVATE: the property affects the target being built.
  2. INTERFACE: the property affects targets that link to this one directly, or transitively through target_link_libraries(... INTERFACE ...).

The PUBLIC visibility is simply a shorthand for both.


Therefore. the build for Bar should look like so:

add_library(Bar SHARED bar.cpp)
target_link_libraries(Bar PUBLIC Foo)

We use PUBLIC visibility here because Bar's headers include Foo's headers. That is, libraries linking to Bar need to know about Foo as well.

Now we build Foo like so:

add_library(Foo SHARED foo.cpp)
target_include_directories(Foo PUBLIC "
lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>")

The main bit of magic here is the $<BUILD_INTERFACE:...> generator expression. This prevents the include directory (which is an absolute path to somewhere on your build machine) from being exported when you eventually use install(EXPORT) to create a find_package-compatible CMake package for these libraries.

Otherwise, we're just relying on the fact that ${CMAKE_CURRENT_SOURCE_DIR}/.. will be propagated from Foo to Bar (and anything that links to Bar) because this path is in the INTERFACE of Foo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文