在可执行文件中设置静态库

发布于 2025-01-31 20:55:31 字数 693 浏览 3 评论 0 原文

我为我的CMAKE项目设置了以下设置:

add_executable(exeA ${SOURCES})
target_link_libraries(exeA PRIVATE libB)

libb 是A static 库在另一个项目中分别构建,并取决于共享 libraries LIBC libd 提供等效的API,但以不同的方式实现并具有不同的性能配置文件。

exea 的构建中,我希望能够根据条件链接 libc libd 。

从阅读,看来我可以使用 rpath 相关的cmake属性,但是我是否可以使用这些属性来设置现有静态库的rpath

不幸的是,没有简单而快速的方法来改变一个 现有可执行文件或共享库。

在Cmake中可以做类似的事情吗?

感谢任何解决此用例的建议。

I have the following setup for my CMake project:

add_executable(exeA ${SOURCES})
target_link_libraries(exeA PRIVATE libB)

libB is a static library built separately in a different project and depends on shared libraries libC OR libD which provide equivalent API's but implemented differently and have different performance profiles.

In exeA's build I want to be able to link against either of libC or libD depending on a condition.

From reading RPATH handling, it seems I could use RPATH related CMake properties, however its unclear if I can use these properties to set the RPATH of an existing static library

Unfortunately there is no easy and fast way to change the RPATH of an
existing executable or shared library.

Is something like this possible to do in CMake?

Appreciate any recommendations to handle this use case.

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

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

发布评论

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

评论(1

祁梦 2025-02-07 20:55:31

libb 共享导入共享导入 libc libd libd libd libd libd libd libd libd 。将相关的一个放在 Interface_link_libraries libb 的属性中。构建 EXEA 时,Cmake将正确设置RPATH。

cmake_minimum_required(VERSION 3.23)
project(test)

# --------------------------------------------------
# The following code should probably be factored out
# into a proper Find module.

find_library(LIBB_LIBRARY NAMES B REQUIRED)
find_library(LIBC_LIBRARY NAMES C REQUIRED)
find_library(LIBD_LIBRARY NAMES D REQUIRED)

add_library(third-party::libC SHARED IMPORTED)
set_target_properties(
  third-party::libC
  PROPERTIES
  IMPORTED_LOCATION "${LIBC_LIBRARY}"
)

add_library(third-party::libD SHARED IMPORTED)
set_target_properties(
  third-party::libD
  PROPERTIES
  IMPORTED_LOCATION "${LIBD_LIBRARY}"
)

add_library(third-party::libB STATIC IMPORTED)
set_target_properties(
  third-party::libB
  PROPERTIES
  IMPORTED_LOCATION "${LIBB_LIBRARY}"
)

option(LIBB_USES_LIBC "dummy option for demo" ON)
if (LIBB_USES_LIBC)
  target_link_libraries(third-party::libB INTERFACE third-party::libC)
else ()
  target_link_libraries(third-party::libB INTERFACE third-party::libD)
endif ()

# --------------------------------------------------

# --------------------------------------------------
# Project code

add_executable(exeA main.cpp)
target_link_libraries(exeA PRIVATE third-party::libB)

您可以使用类似虚拟文件进行测试:

$ ls
CMakeLists.txt
$ mkdir -p prefix{1,2}/lib
$ touch prefix1/lib/lib{C,D}.so prefix2/lib/libB.a main.cpp
$ cmake -G Ninja -S . -B build "-DCMAKE_PREFIX_PATH=$PWD/prefix1;$PWD/prefix2"
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/build
$ cmake --build build -- -nv  # dry run (n), verbose (v)
[1/2] /usr/bin/c++    -MD -MT CMakeFiles/exeA.dir/main.cpp.o -MF CMakeFiles/exeA.dir/main.cpp.o.d -o CMakeFiles/exeA.dir/main.cpp.o -c /home/alex/test/main.cpp
[2/2] : && /usr/bin/c++   CMakeFiles/exeA.dir/main.cpp.o -o exeA  -Wl,-rpath,/home/alex/test/prefix1/lib  ../prefix2/lib/libB.a  ../prefix1/lib/libC.so && :

如您所见, rpath 已正确设置为包含 libc.so 的目录。

Create a STATIC IMPORTED library for libB and SHARED IMPORTED libraries for libC and libD. Put the relevant one in the INTERFACE_LINK_LIBRARIES property of libB. CMake will set the RPATH correctly when exeA is built.

cmake_minimum_required(VERSION 3.23)
project(test)

# --------------------------------------------------
# The following code should probably be factored out
# into a proper Find module.

find_library(LIBB_LIBRARY NAMES B REQUIRED)
find_library(LIBC_LIBRARY NAMES C REQUIRED)
find_library(LIBD_LIBRARY NAMES D REQUIRED)

add_library(third-party::libC SHARED IMPORTED)
set_target_properties(
  third-party::libC
  PROPERTIES
  IMPORTED_LOCATION "${LIBC_LIBRARY}"
)

add_library(third-party::libD SHARED IMPORTED)
set_target_properties(
  third-party::libD
  PROPERTIES
  IMPORTED_LOCATION "${LIBD_LIBRARY}"
)

add_library(third-party::libB STATIC IMPORTED)
set_target_properties(
  third-party::libB
  PROPERTIES
  IMPORTED_LOCATION "${LIBB_LIBRARY}"
)

option(LIBB_USES_LIBC "dummy option for demo" ON)
if (LIBB_USES_LIBC)
  target_link_libraries(third-party::libB INTERFACE third-party::libC)
else ()
  target_link_libraries(third-party::libB INTERFACE third-party::libD)
endif ()

# --------------------------------------------------

# --------------------------------------------------
# Project code

add_executable(exeA main.cpp)
target_link_libraries(exeA PRIVATE third-party::libB)

You can test this out with dummy files like so:

$ ls
CMakeLists.txt
$ mkdir -p prefix{1,2}/lib
$ touch prefix1/lib/lib{C,D}.so prefix2/lib/libB.a main.cpp
$ cmake -G Ninja -S . -B build "-DCMAKE_PREFIX_PATH=$PWD/prefix1;$PWD/prefix2"
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/build
$ cmake --build build -- -nv  # dry run (n), verbose (v)
[1/2] /usr/bin/c++    -MD -MT CMakeFiles/exeA.dir/main.cpp.o -MF CMakeFiles/exeA.dir/main.cpp.o.d -o CMakeFiles/exeA.dir/main.cpp.o -c /home/alex/test/main.cpp
[2/2] : && /usr/bin/c++   CMakeFiles/exeA.dir/main.cpp.o -o exeA  -Wl,-rpath,/home/alex/test/prefix1/lib  ../prefix2/lib/libB.a  ../prefix1/lib/libC.so && :

As you can see, the RPATH is set correctly to the directory containing libC.so.

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