[cmake-developers] Duplicated linking flags are removed when linking final executable

Sergio Checa Sergio.Checa at bmw-carit.de
Tue Mar 15 05:58:57 EDT 2016


Hi,
Thanks for the suggestion about OBJECT libraries, I've learnt one more way to design my build process.
Nevertheless, the effect also appears when linking dynamic libraries. For example, a slightly modified CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)

file(WRITE a.cpp "")
file(WRITE b.cpp "")
file(WRITE lib.cpp "")
file(WRITE main.cpp "int main(){return 0;}")

add_library(A SHARED a.cpp)
add_library(B SHARED b.cpp)

add_library(L SHARED lib.cpp)

target_link_libraries(L
    -Wl,-as-needed A -Wl,-no-as-needed
    -Wl,-as-needed B -Wl,-no-as-needed
)

add_executable(main main.cpp)
target_link_libraries(main L)
In this example, I only want libA and libB linked into the main executable iff their symbols are used somewhere in the linking chain (-as-needed). However, libB appears as a needed library because the -Wl,-as-needed flag has no effect on it (it's not in front of libB in CMakeFiles/main.dir/link.txt)

$> objdump -p main | grep NEEDED
    ...
    NEEDED               libL.so
    NEEDED               libB.so
    ...

Furthermore, if I link 'main' manually from the command line, then 'main' doesn't link libB anymore:

$> g++ -o main ../main.cpp -lL -L.
$> objdump -p main | grep NEEDED
    ...
    NEEDED               libL.so
    ...


The reason why I think it's a bug is that the linkage behaves differently between cmake and raw command line, due to some conflicts between flags when constructing the linking command.

Here is yet another weird scenario:

             .--->  X  --->  -as-needed A -no-as-needed
             |
    main ----|
             |
             '--->  Y  --->  -as-needed B -no-as-needed

CMakeLists.txt to reproduce it:
cmake_minimum_required(VERSION 3.5)

file(WRITE a.cpp "")
file(WRITE b.cpp "")
file(WRITE x.cpp "")
file(WRITE y.cpp "")
file(WRITE main.cpp "int main(){return 0;}")

add_library(A SHARED a.cpp)
add_library(B SHARED b.cpp)

add_library(X SHARED x.cpp)
add_library(Y SHARED y.cpp)


target_link_libraries(X
    -Wl,-as-needed A -Wl,-no-as-needed
)
target_link_libraries(Y
    -Wl,-as-needed B -Wl,-no-as-needed
)

add_executable(main main.cpp)
target_link_libraries(main X Y)
The result if that both libA and libB are linked in the final executable 'main'. The content of CMakeFiles/main.d/link.txt:

/usr/bin/c++       CMakeFiles/main.dir/main.cpp.o  -o main -rdynamic libX.so libY.so libA.so -Wl,-as-needed -Wl,-no-as-needed libB.so -Wl,-rpath,/tmp/build


Best regards,
Sergio


On 14/03/16 15:58, Brad King wrote:

On 03/14/2016 09:33 AM, Sergio Checa wrote:


    target_link_libraries(L
        -Wl,-whole-archive A -Wl,-no-whole-archive
        -Wl,-whole-archive B -Wl,-no-whole-archive
    )

    add_executable(main main.cpp)
    target_link_libraries(main L)



Specifying flags anywhere except the final executable's target_link_libraries
is not very well defined.  I'd rather not try to define behavior different
than has been there for a long time.

It looks like you're trying to achieve what OBJECT libraries are for:

  https://cmake.org/cmake/help/v3.5/command/add_library.html#object-libraries

Please try that approach instead.

-Brad


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake-developers/attachments/20160315/e291d3e3/attachment.html>


More information about the cmake-developers mailing list