Hey all,

I face a similar problem when constructing a correct (and predictable)
link order for Linux and Cygwin. It would be of great help, if there is
some documentation.

In particular, I would raise two question
    1) when does the link order change?
    2) when does a clean up happen and in which way?

I did also some experiments on linux with cmake 3.13.4 and ended up with
the appended (nearly) minimal example. The example consists of:

 * two "fake"-libraries A and B, whose paths are stored in two
   variables libA and libB respectively. (they serve just for
   demonstration, no real linking is required)
 * two interface libraries interfaceA and interfaceB. Each links to the
   corresponding fake library.
 * two imported libraries impA and impB, each has the location to the
   corresponding fake library.

Now I construct some combinations:

1. An interface library interfaceA_B_vA, which links against the
   interface libraries "interfaceA interfaceB ${libA}" and an
   executable, which links only against interfaceA_B_vA. For that
   executable, I get the link order "B A"
2. Suppose one tries to correct that and link explicitly against with
   the variable. Such an executable which links as "${libA}
   interfaceA_B_vA". In that case, I got the link order "A A B". So we
   have a changed order compared to the previous experiment.
3. If I use the imported libraries instead of the variables from
   experiment 1, I get the link order A B A, as expected.

From these experiments, I got the impression, that

1. linking through variables remains a nightmare. That is nothing new.
2. interface libraries might change their order
3. imported libraries lead to a more stable link order?

I hope somebody could shed some light in this behavior.

Best regards,
Andreas


Am 18.10.19 um 18:24 schrieb Fred Baksik:


On Fri, Oct 18, 2019, at 11:55 AM, Fred Baksik wrote:

In target_link_libraries it states that "The library dependency graph
is normally acyclic (a DAG)".  I recall from my own experience that
the DAG is not always created the same way when generating the
project.  It has to do with the way with this part of CMake is
implemented (C++ containers and that sort of thing) so while all the
inputs are the same the order is Not the same so it produces a
different DAG which changed the ordering of the components build
order which also altered the link order.

For the GHS Generator to ensure that the exact same project files are
output we sorted the components by name into a vector first (instead
of just using a set) before supplying it to this algorithm.  Then the
results were always the same.


Sorry, I wanted to clarify this a bit.  The DAG is correct. For
example lets say A depends on B and C and then C on D.  This DAG
always comes out the same.  But when you try to extract the dependents
of A it sometimes returns something that will give you B then C or C
then B when accessing them in a linear order. So there were
differences if you inspected these items with the debugger.

When I ran across these kinds of things with the GHS Generator we sort
things in lexicographical order to produce the same results every time.

Best regards,
Fred


project(testLinkOrder)
cmake_minimum_required(VERSION 3.5)

file(WRITE "simpleProg.cc" "int main() { return 0; }")
set(libA "${CMAKE_BINARY_DIR}/A.a")
file(WRITE "${libA}" "i am not a library")

set(libB "${CMAKE_BINARY_DIR}/B.a")
file(WRITE "${libB}" "i am not a library")

add_library(impA IMPORTED STATIC)
set_target_properties(impA PROPERTIES IMPORTED_LOCATION ${libA})

add_library(impB IMPORTED STATIC)
set_target_properties(impB PROPERTIES IMPORTED_LOCATION ${libB})

add_library(interfaceA INTERFACE)
target_link_libraries(interfaceA INTERFACE ${libA})

add_library(interfaceB INTERFACE)
target_link_libraries(interfaceB INTERFACE ${libB})
#target_link_libraries(interfaceA INTERFACE ${libB})

add_library(interface_A_B_vA INTERFACE)
target_link_libraries(interface_A_B_vA INTERFACE interfaceA interfaceB ${libA})

add_executable(linkInterface_A_B_vA simpleProg.cc)
target_link_libraries(linkInterface_A_B_vA interface_A_B_vA)

add_executable(linkvA_IABAVA simpleProg.cc)
target_link_libraries(linkvA_IABAVA ${libA} interface_A_B_vA)

add_library(interface_impA_impB_vA INTERFACE)
target_link_libraries(interface_impA_impB_vA INTERFACE impA impB ${libA})

add_executable(linkInterface_impA_impB_vA simpleProg.cc)
target_link_libraries(linkInterface_impA_impB_vA interface_impA_impB_vA)
-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake

Reply via email to