英文:
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可用。
文件夹的结构
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'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'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 <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();
[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't want something that links to `lib1` to be able to include headers that are supposed to be for `lib2`, then don't put `lib1` and `lib2`'s headers under the same include directory- make it so that their headers are not reachable from the other's include directories.
Your libraries are static because you didn't specify whether they should be static or shared, and you didn'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're using C++ and you want something that'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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论