CMake 无法检测不同静态库中的符号冲突

CMake cannot detect symbol conflicts in different static libraries

我创建了一个简单的 cmake 项目来重现它。

├── CMakeLists.txt
├── lib1
│   ├── CMakeLists.txt
│   ├── lib1.cpp
│   └── lib1.h
├── lib2
│   ├── CMakeLists.txt
│   ├── lib2.cpp
│   └── lib2.h
└── main.cpp

lib1/CMakeLists.txt:

add_library(lib1 "")
target_include_directories(lib1
  PUBLIC
      ${CMAKE_CURRENT_LIST_DIR}
)
target_sources(lib1
    PRIVATE
        lib1.cpp
        lib1.h
)

在lib1.cpp中有一个函数"void say()":

#include <stdio.h>

void say()
{
    printf("hello from lib1\n");
}

lib2/CMakeLists.txt:

add_library(lib2 "")
target_include_directories(lib2
  PUBLIC
      ${CMAKE_CURRENT_LIST_DIR}
)
target_sources(lib2
    PRIVATE
        lib2.cpp
        lib2.h
)

而在lib2/lib2.cpp中,有一个相同签名的函数:

#include <stdio.h>
void say()
{
    printf("hello from lib2\n");
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project(shell LANGUAGES CXX)
add_subdirectory(lib1)
add_subdirectory(lib2)
add_executable(test2
  main.cpp
)
target_link_libraries(test2
  PRIVATE
    lib1
    lib2
)

这里是 main.cpp:

void say();
int main()
{
    say();
    return 0;
} 

输出:

hello from lib1

没有编译或link错误,甚至没有警告。 linker 只是选择了一个而忽略了另一个。 我正在使用 cmake 3.16,并使用 msvc 2017/2019 和 g++ 7.5 对其进行了测试。

如何让linker在静态库中出现符号冲突时提示错误?

谢谢!

How to make the linker prompts errors when there are symbol conflicts in static libraries?

gcc 一起使用 --whole-archive 选项将每个目标文件包含在存档中,而不是在存档中搜索所需的符号。

由于据我所知没有 cmake 支持,我发现通常在链接可执行文件时完成:

target_link_libraries(test2 PRIVATE
    -Wl,--whole-archive
    lib1
    lib2
    -Wl,--no-whole-archive
)

"Symbol conflicts" 是一个相当模糊的术语。这只会检测多个符号定义。符号类型在编译后不会存储在任何地方。