CMake link order

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

CMake link order

Bon, William
Hello,

we are facing an issue while using cmake and we have no idea how to solve or debug it.
We have a complex and huge project (about 50 subdirectories and dependencies everywhere), and we are facing issue regarding the link order.
There is a lot of dependencies between those projects, and to summarize, we have two libraries A and B
A is an imported library from headers and shared lib .so declared like this
```
add_library(A SHARED IMPORTED GLOBAL)
set_target_properties(A PROPERTIES
        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
        IMPORTED_LOCATION ${A_LIBRARY})
```

B is a system library part of a package.

We need to link A before B in every case.

In every project, we include A before B using
```
find_package(B)
target_link_libraries(${library_produced} PUBLIC A)
target_link_libraries(${library_produced} PUBLIC B)
```

but from time to time, we don't know why, the library produced link in the wrong order (checked with ldd and make VERBOSE=1).
it links B before A.

Is there a way to find out what happens and why cmake change the link order for some project and not all projects ?

Best regards,

Bill

--

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 | Threaded
Open this post in threaded view
|

Re: CMake link order

fdk17


On Fri, Oct 18, 2019, at 6:24 AM, Bon, William wrote:
Hello,

we are facing an issue while using cmake and we have no idea how to solve or debug it.
We have a complex and huge project (about 50 subdirectories and dependencies everywhere), and we are facing issue regarding the link order.
There is a lot of dependencies between those projects, and to summarize, we have two libraries A and B
A is an imported library from headers and shared lib .so declared like this
```
add_library(A SHARED IMPORTED GLOBAL)
set_target_properties(A PROPERTIES
        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
        IMPORTED_LOCATION ${A_LIBRARY})
```

B is a system library part of a package.

We need to link A before B in every case.

In every project, we include A before B using
```
find_package(B)
target_link_libraries(${library_produced} PUBLIC A)
target_link_libraries(${library_produced} PUBLIC B)
```

but from time to time, we don't know why, the library produced link in the wrong order (checked with ldd and make VERBOSE=1).
it links B before A.

Is there a way to find out what happens and why cmake change the link order for some project and not all projects ?

Best regards,

Bill


I'm going by memory when I saw something similar when updating the GHS Generator in CMake.

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.

But  if I remember correctly an "add_dependency( B A )" or otherwise make B dependent on A does forces a dependency between the two libraries which forces the DAG to always put A before B.

I would bet that if you just did the project generation over and over again into different build directories you'll notice these kinds of differences in the different Makefiles (or whatever output that is expected by the generator).

This is how I noticed the issue with the GHS Generator because the ordering of some items were just changing in an unexpected fashion and I was always comparing what it generated against what I was expecting it to generate.

I never asked the main developers about this; and again this is just my own observations.

Best regards,
Fred

--

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 | Threaded
Open this post in threaded view
|

Re: CMake link order

fdk17


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

--

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 | Threaded
Open this post in threaded view
|

Re: CMake link order

Andreas Naumann
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
>

--

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

CMakeLists.txt (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: CMake link order

Juan Sanchez
In reply to this post by Bon, William
Hello,

I have always used all of the libraries at once to the TARGET_LINK_LIBRARIES command.

In the following example, the link line order appears the same as the libraries are listed on the line.

TARGET_LINK_LIBRARIES(devsim_tcl ${LIBRARIES} ${TCL_ARCHIVE} ${SUPERLU_ARCHIVE} ${BLAS_ARCHIVE} ${SQLITE3_ARCHIVE} ${SYMDIFF_ARCHIVE} ${OPTIONAL_LIBS} ${PTHREAD_LIB} ${DLOPEN_LIB})

This is important because my LIBRARIES need to all be on the link line before the other libraries I am using.

Another option is to explicitly us ADD_DEPENDENCY to add dependencies between the libraries:
https://cmake.org/cmake/help/latest/command/add_dependencies.html

If I had multiple libraries hopelessly intertwined, I would list them multiple times:
A B A C

or force the linker to do multiple passes:

 -Wl,--start-group A B C  -Wl,--end-group

This is by using the start-group and end-group flags in your TARGET_LINK_LIBRARIES line.
https://cmake.org/pipermail/cmake/2011-May/044478.html

Regards,

Juan






On Fri, Oct 18, 2019 at 9:56 AM Bon, William <[hidden email]> wrote:
Hello,

we are facing an issue while using cmake and we have no idea how to solve or debug it.
We have a complex and huge project (about 50 subdirectories and dependencies everywhere), and we are facing issue regarding the link order.
There is a lot of dependencies between those projects, and to summarize, we have two libraries A and B
A is an imported library from headers and shared lib .so declared like this
```
add_library(A SHARED IMPORTED GLOBAL)
set_target_properties(A PROPERTIES
        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
        IMPORTED_LOCATION ${A_LIBRARY})
```

B is a system library part of a package.

We need to link A before B in every case.

In every project, we include A before B using
```
find_package(B)
target_link_libraries(${library_produced} PUBLIC A)
target_link_libraries(${library_produced} PUBLIC B)
```

but from time to time, we don't know why, the library produced link in the wrong order (checked with ldd and make VERBOSE=1).
it links B before A.

Is there a way to find out what happens and why cmake change the link order for some project and not all projects ?

Best regards,

Bill
--

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

--

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