Why isn't PRIVATE working as I expect when linking my executable against a library that links privately to another library?

huangapple go评论53阅读模式
英文:

Why isn't PRIVATE working as I expect when linking my executable against a library that links privately to another library?

问题

以下是您要翻译的内容:

"我编写了一个小型测试项目,以了解在CMake的target_link_libraries()函数中PRIVATE关键字的工作原理。我们有一个名为main的目标,它链接到第一个名为lib1的库,而这个第一个库又链接到第二个库lib2。在每种情况下,依赖项的传递都是PRIVATE,因此我期望main只能访问lib1的函数,类似地lib1只能访问lib2的函数(请参见下面的图表和代码)。但是,现在在main中,我们直接调用了lib2的函数。然而,项目可以正常链接和执行,所以我不太明白。

更详细地说,我认为target_link_libraries(lib1 PRIVATE lib2)会将lib1的属性设置为LINK_LIBRARIES=lib2,而target_link_libraries(main PRIVATE lib1)会将main的属性设置为LINK_LIBRARIES=lib1,但是lib1的INTERFACE_LINK_LIBRARY属性没有设置为lib2,因此将main链接到lib1不会使lib2对main可用。

Why isn't PRIVATE working as I expect when linking my executable against a library that links privately to another library?

文件夹的结构

project(dependency_propagation)
cmake_minimum_required(VERSION 3.0)

add_library(lib1 src1.cpp)
add_library(lib2 src2.cpp)

target_include_directories(lib1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includes)
target_include_directories(lib2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includes)

target_link_libraries(lib1 PRIVATE lib2)

add_executable(main main.cpp)

target_link_libraries(main PRIVATE lib1)

main.cpp

#include <iostream>
#include <function2.hpp>

using namespace std;

int main() {
    cout << function2() << endl;
    return 0;
}

src1.cpp

int function1() {
    return 1;
}

src2.cpp

int function2() {
    return 2;
}

function1.hpp

int function1();

function2.hpp

int function2();

<details>
<summary>英文:</summary>

I wrote a small test project in order to to understand how the `PRIVATE` keyword works in cmake&#39;s `target_link_libraries()` function. We have a **main** target which links against a first library called **lib1**, and this first library in turn links against a second library **lib2**. The transitive handling of dependencies is in every case `PRIVATE`, so I expected **main** only to be able to access the function of **lib1** and similarly **lib1** only to be able to access the function of **lib2** (see graph and code below). Now in main we call a function from **lib2** directly. However, the project links and executes normally so I don&#39;t get it.

More in details, I thought that `target_link_libraries(lib1 PRIVATE lib2)` was populating the property of lib1 as `LINK_LIBRARIES=lib2` and `target_link_libraries(main PRIVATE lib1)` was populationg the property of main as `LINK_LIBRARIES=lib1` but the `INTERFACE_LINK_LIBRARY` property of lib1 is not set to lib2 and so linking main against lib1 would not make lib2 accessible to main.

[![enter image description here][1]][1]

structure of folder


    project(dependency_propagation) cmake_minimum_required(VERSION 3.0)
    
    add_library(lib1 src1.cpp) add_library(lib2 src2.cpp)
    
    target_include_directories(lib1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includes) target_include_directories(lib2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includes)
    
    target_link_libraries(lib1 PRIVATE lib2)
    
    add_executable(main main.cpp)

    target_link_libraries(main PRIVATE lib1)

**main.cpp**

    #include &lt;iostream&gt;
    #include &lt;function2.hpp&gt;
    
    using namespace std;
    
    int main() {
        cout &lt;&lt; function2() &lt;&lt; endl;
        return 0; }

**src1.cpp**

    int function1() {
        return 1; }

**src2.cpp**

    int function2() {
        return 2; }

**function1.hpp**

    int function1();

**function2.hpp**

    int function2();


  [1]: https://i.stack.imgur.com/W3P4B.png



</details>


# 答案1
**得分**: 1

你将两个库都放在相同的公共包含目录下(即,两个库共享一个包含头文件的目录)。如果你不希望与 `lib1` 关联的内容能够包含本应该供 `lib2` 使用的头文件,那么请不要将 `lib1` 和 `lib2` 的头文件放在相同的包含目录下,而是确保它们的头文件不可从其他包含目录访问。

你的库是静态的,因为你没有指定它们应该是静态的还是共享的,并且你没有将 [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html#variable:BUILD_SHARED_LIBS) 设置为真值。在指定与静态库的链接时,CMake 会构建 `lib1` 静态库和 `lib2` 静态库,然后构建可执行文件,告诉链接器将这两个静态库链接到可执行文件上。如果你正在使用C++,并且希望某些内容不是静态库的接口的一部分,你可以在无名称命名空间(unnamed namespace)中的非头文件中声明和定义它,使其更加私有。

<details>
<summary>英文:</summary>

You made both your libs have the same public include directory (I.e. both libs are sharing an include directory for their headers). If you don&#39;t want something that links to `lib1` to be able to include headers that are supposed to be for `lib2`, then don&#39;t put `lib1` and `lib2`&#39;s headers under the same include directory- make it so that their headers are not reachable from the other&#39;s include directories.

Your libraries are static because you didn&#39;t specify whether they should be static or shared, and you didn&#39;t set [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html#variable:BUILD_SHARED_LIBS) to a truthy value. When specifying linkage against static libraries, CMake builds the `lib1` static library and the `lib1` static library, and then builds the executable telling the linker to link both those static libraries to the executable. If you&#39;re using C++ and you want something that&#39;s _not part of the interface_ of a static library to be more private, you can declare and define it only in a non-header file inside an [unnamed namespace](https://en.cppreference.com/w/cpp/language/namespace#Unnamed_namespaces).

</details>



huangapple
  • 本文由 发表于 2023年3月10日 00:12:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687236.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定