【问题标题】:Use CMake to enforce restriction "one of alternative libraries is needed to link executable"使用 CMake 强制执行限制“需要一个替代库来链接可执行文件”
【发布时间】:2020-07-03 18:41:11
【问题描述】:

我在 linux 上使用静态库。我有两个静态库(“实施者”)共享接口,这些接口被打包到第三个库(“common”)中。构建二进制文件需要其中的一个(实现者)。我需要同时构建两个版本的 exec(单独的目标)。但是我可以创建只使用公共部分的静态库。这样的人太多了

我希望 CMake 保护我免于创建缺少实现者的可执行文件。这是必需的,因为找出这一点需要很长时间(长时间编译,甚至更长的链接)。

Pseudo-c++ 和 cmake 如下所示(我通过忽略包含进行了简化,它们实际上是“通用”库的重要组成部分)。

// libFooBar - "common"
void foo(); // only declaration for includers. Is implemented by implementers
void bar() {
    foo();
}

// libFooBarPrintf - "implementer1"
void foo() {
    printf("Foo");
}

// libFooBarCout - "implementer2"
void foo() {
    std::cout<<"Foo";
}

// userlib - uses only common interface

void useBar() {
    bar();
}

// foobar_user.exe 
// needs "common" for compilation and one of "implementers" for linking
int main () {
    useBar();
    return 0;
}
add_library(foobar        STATIC foobar.cpp)
add_library(foobar_printf STATIC foobar_printf.cpp)
add_library(foobar_cout   STATIC foobar_cout.cpp)

add_library(          userlib STATIC userlib.cpp)
target_link_libraries(userlib PUBLIC foobar)

# this passes cmake, but fails to link with undefined ref to foo()
add_executable(       user_bad main.cpp)
target_link_libraries(user_bad userlib)

#those two are working as intended
add_executable(       user_printf main.cpp)
target_link_libraries(user_printf userlib foobar_printf)
add_executable(       user_cout   main.cpp)
target_link_libraries(user_cout   userlib foobar_cout)

我想在 user_bad 可执行文件上实现 cmake 错误,但不在 userlib 库上。我想它看起来像(非常伪 cmake):

set_target_properties(foobar_printf foobar_cout 
    PROPERTIES 
        provides_implementation_for_foobar    1)
set_target_properties(foobar 
    PROPERTIES 
    INTERFACE_FOR_EXECUTABLES_needs_property    provides_implementation_for_foobar)

这可能吗?

将 userlib 复制到两个版本(每个实施者 1 个)对于我的项目来说是不可扩展的。

【问题讨论】:

    标签: c++ cmake linker dependencies


    【解决方案1】:

    这是有问题的。您创建了一个依赖不完整的目标 (foobar),CMake 非常不希望您这样做,也没有义务正确处理。

    摆脱这种情况而不必到处复制库的一种方法是通过use of object libraries

    add_library(foobar OBJECT ...)
    
    add_library(foobar_printf STATIC foobar_printf.cpp $<TARGET_OBJECTS:foobar>)
    
    add_executable(user_printf main.cpp)
    target_link_libraries(user_printf userlib foobar_printf)
    

    请注意,构建树中的任何一点都不会以不完整的目标结束。

    例如,考虑到您的示例,其中foobar 被中间userlib 使用:在声明userlib 时,您需要决定使用哪个实现。否则,您最终会遇到与以前相同的问题,只是现在处于userlib 的级别。

    如果您绝对 100% 需要将此决定推迟到可执行文件的声明点,则应将其一直推送到运行时并改用动态库。

    请注意,虽然从技术上讲,对于某些构建生成器,您可能能够以不同的方式解决此问题,但如果您正在寻找一个干净且强大的解决方案,那么这些是我看到的唯一可行的选择。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2020-08-12
      • 2015-04-16
      • 2017-08-21
      • 1970-01-01
      相关资源
      最近更新 更多