Why does CMake repeat link libraries across link flags?

Viewed 76

I'm using a third party project that provides dependencies to link against via a pkg-config file, which I pass to my target via target_link_libraries. The final result looks something like this example:

$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(main)

add_executable(main main.c)
target_link_libraries(
  main
  PRIVATE -lfoo
          -Wl,--whole-archive
          -lbar
          -Wl,--no-whole-archive
          -lfoo
          -Wl,-Bdynamic
          -lbaz)

Where main.c is a trivial C source file:

$ cat main.c
int main() { return 0; }

When I run CMake's configure step and inspect the generated compile commands, I see some libraries duplicated across link flags:

$ cmake -S . -B build -GNinja
$ ninja -C build -t commands
/usr/bin/cc    -MD -MT CMakeFiles/main.dir/main.c.o -MF CMakeFiles/main.dir/main.c.o.d -o CMakeFiles/main.dir/main.c.o -c /home/ja/toy/main.c
: && /usr/bin/cc   CMakeFiles/main.dir/main.c.o -o main  -lfoo  -Wl,--whole-archive  -lbar  -Wl,--no-whole-archive  -lfoo  -Wl,-Bdynamic  -lbaz  -lbar  -lbaz && :

Clearly, -lbar was repeated across --no-whole-archive and -Bdynamic. Is this equivalent to the original target_link_libraries call? Why does CMake do this?

Additionally, I tried experimenting without the link flags, and noticed that CMake transforms -lfoo -lbar -lfoo -lbaz into -lfoo -lbar -lfoo -lbaz -lbar -lbaz. I suspect it might have something to do with the behavior described at LINK_INTERFACE_MULTIPLICITY but I do not understand the rationale behind doing this across link flags.

Edit: I'm using CMake version 3.23.0.

0 Answers
Related