1
votes

I created a simple cmake project to reproduct it.

├── 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
)

In lib1.cpp, there is a function "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
)

And in lib2/lib2.cpp, there is a function of the same signature:

#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
)

Here is the main.cpp:

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

The output:

hello from lib1

There is no compile or link error, not even a warning. The linker just picked one and symply ignored the other one. I'm using cmake 3.16, and tested it with msvc 2017/2019 and g++ 7.5.

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

Thanks!

1
Can you show the CMakeLists.txt? Linking only happens when you actually link everything into an executable. But you should specify that in your CMakeLists.txt for the application, something like: add_executable( main ); target_link_libraries( main lib1 lib2 )André
@André, updated with the CMakeLists.txt.youwenti
It doesn't have to do with CMake. See Why C++ linker is silent about ODR violation?Joel Filho
This is just how compilers (linkers) work.KamilCuk
It may be not to do with CMake, but there should be a way to make it work in CMake No, this has nothing to do with cmake. Cmake doesn't compile your code.KamilCuk

1 Answers

3
votes

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

With gcc use the --whole-archive option to include every object file in the archive rather then search the archives for the required symbol.

As there is no cmake support that I know of, I find it's typically done when linking the executable:

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

"Symbol conflicts" is rather vague term. This will only detect multiple symbol definitions. Types of symbols are not stored anywhere after compilation.