[CMake] CMake removing duplicated static libraries from target_link_libraries list?

Michael Hertling mhertling at online.de
Thu Feb 3 11:28:16 EST 2011


On 02/02/2011 06:45 PM, Marco wrote:
> Hi Michael,
> 
> here's the plain example. I have a package with its CMakeLists.txt file 
> like this:
> 
> #
> # Generate library
> #
> add_library(TrkBase ${Sources})
> target_link_libraries(TrkBase ${LIB_LINK_LIST})
> 
> #
> # Generate executable
> #
> add_executable(TrkExchangeDataTest bins/TrkExchangeDataTest.cc)
> target_link_libraries(TrkExchangeDataTest ${BIN_LINK_LIST})
> 
> Now my LIB_LINK_LIST is the following:
> 
> /usr/lib/libboost_regex.a;TrajGeom;PDT;CommonUtils;gfortran;ProbTools;Experiment;BField;BbrGeom;difAlgebra;m;AssocTools;AbsEvent;AbsEnv;ProxyDict;ErrLogger;BbrStdUtils;/usr/lib/libboost_regex.a;BaBar;CLHEP;CLHEP-2.0.3.2
> 
> while the BIN_LINK_LIST is:
> 
> TrkBase;BbrGeom;difAlgebra;m;ErrLogger;BbrStdUtils;/usr/lib/libboost_regex.a;BaBar;CLHEP;CLHEP-2.0.3.2
> 
> and this is the generated link.txt:
> 
> /usr/bin/c++ 
> CMakeFiles/TrkDifPieceTrajTest.dir/bins/TrkDifPieceTrajTest.cc.o  -o 
> TrkDifPieceTrajTest 
> -L/data/exp_software/superb/releases/FastSim/V0.2.7/lib/Linux26SL5_i386_gcc412 
> -L/data/exp_software/superb/cern/root/5.26/lib 
> -L/data/exp_software/superb/cern/clhep/2.0.3.2/lib 
> ../../../lib/Linux26SL5_i386_gcc412/libTrkBase.a 
> ../../../lib/Linux26SL5_i386_gcc412/libBbrGeom.a -ldifAlgebra -lm 
> -lErrLogger -lBbrStdUtils /usr/lib/libboost_regex.a -lBaBar -lCLHEP 
> -lCLHEP-2.0.3.2 -lTrajGeom -lPDT -lCommonUtils -lgfortran -lProbTools 
> -lExperiment -lBField -ldifAlgebra -lm -lAssocTools -lAbsEvent -lAbsEnv 
> -lProxyDict -lErrLogger -lBbrStdUtils /usr/lib/libboost_regex.a -lBaBar 
> -lCLHEP -lCLHEP-2.0.3.2
> 
> As I expected, CMake puts first the list of libraries from BIN_LINK_LIST 
> (maybe in the previous mail I misplaced them...) and then, since TrkBase 
> has itself too a list of dependencies (LIB_LINK_LIST), the libraries 
> from LIB_LINK_LIST. The point is that the second BbrGeom library 
> disappears from the link command, for, I suspect, it's been already 
> inserted by BIN_LINK_LIST. In fact, looking at the libraries, you see 
> that libboost_regex.a, shows up twice most likely because CMake 
> recognizes it as a static library, while BbrGeom, which is static too 
> but not "fully qualified" by its path/name, is dropped.
> 
> I also noticed that, for example, ErrLogger too is listed twice but is 
> always referred to as -lErrLogger, not with the full path/name. The same 
> happens to CLHEP. The one that disappears is just BbrGeom. I also made a 
> reverse check avoiding the build of BbrGeom package with cmake and 
> treating it as a "external" library. In this case the list is preserved 
> and BbrGeom shows up twice.
> 
> /usr/bin/c++ 
> CMakeFiles/TrkDifPieceTrajTest.dir/bins/TrkDifPieceTrajTest.cc.o  -o 
> TrkDifPieceTrajTest 
> -L/home/corvo/SuperB/FastSim/V0.2.7_RC6/lib/Linux26SL5_i386_gcc412 
> -L/data/exp_software/superb/releases/FastSim/V0.2.7/lib/Linux26SL5_i386_gcc412 
> -L/data/exp_software/superb/cern/root/5.26/lib 
> -L/data/exp_software/superb/cern/clhep/2.0.3.2/lib 
> ../../../lib/Linux26SL5_i386_gcc412/libTrkBase.a -lBbrGeom -ldifAlgebra 
> -lm -lErrLogger -lBbrStdUtils /usr/lib/libboost_regex.a -lBaBar -lCLHEP 
> -lCLHEP-2.0.3.2 -lTrajGeom -lPDT -lCommonUtils -lgfortran -lProbTools 
> -lExperiment -lBField -lBbrGeom -ldifAlgebra -lm -lAssocTools -lAbsEvent 
> -lAbsEnv -lProxyDict -lErrLogger -lBbrStdUtils /usr/lib/libboost_regex.a 
> -lBaBar -lCLHEP -lCLHEP-2.0.3.2
> 
> To sum up it looks to me as if CMake, when manages the build of a static 
> library directly and has to link it to an executable, then drops off all 
> other occurencies of that lib, if any is found along the list of linking 
> libraries, somehow treating them as dynamic libs. If otherwise the 
> library is out of its control, then the list of libraries passed to 
> target_link_libraries is preserved.
> The only way to keep also the other occurency, which I need as TrajGeom 
> depends on BbrGeom, is to declare BbrGeom with its full path/name, so 
> that CMake is forced to consider it static.
> 
> I tried to set CMAKE_EXE_LINKER_FLAGS -static and -Bstatic, but the 
> point is not with the linker, but in the way CMake itself considers 
> libraries internally when managing target_link_libraries lists.
> 
> Sorry for the very long mail. Hope that the problem I'm facing is clear.

Yes, I think it is. ;) AFAICS, your issue is caused by the dependency
of TrajGeom on BbrGeom. From the link command above, I conclude that
TrajGeom is an external library, i.e. it is not built as a target in
your project, but BbrGeom is such a target; the fact that the former
is mentioned with -l while BbrGeom is referred to by a relative path
indicates right that. Now, for a project's targets, CMake can track
their dependencies and, indeed, drops multiply apperaring libraries
from the link command if they aren't needed to resolve dependencies
known to CMake. The crucial moment is that CMake can not know that
the external TrajGeom depends on the, say, internal BbrGeom, so the
latter's second appearance in the link command is removed since it's
not necessary to resolve any known dependencies. An obvious solution
is to fill the gap in the dependency graph, either by including the
TrajGeom library as a target in your project or by treating it as an
imported target and declaring its dependencies by hand:

ADD_LIBRARY(TrajGeom STATIC IMPORTED)
SET_TARGET_PROPERTIES(TrajGeom PROPERTIES
    IMPORTED_LOCATION <full/path/to/libTrajGeom.a>
    IMPORTED_LINK_INTERFACE_LIBRARIES BbrGeom
)

After having done this, you'll probably see libBbrGeom.a reappear a
second time in the link command following the - now - libTrajGeom.a.

The other phenomena have different causes, IMO:

- libboost_regex.a is dropped once from LIB_LINK_LIST because only the
  second occurrence is necessary, so it finally appears twice in the
  link command, the first time from BIN_LINK_LIST and the second one
  is the remaining occurrence from LIB_LINK_LIST.
- ErrLogger, CLHEP etc. are external libraries which are mentioned with
  -l in the link command, and CMake can't know their interdependencies,
  so it doesn't drop any of them. OTOH, as discussed above, BbrGeom as
  one of the project's targets can be tracked w.r.t. its dependencies
  and, thus, is subject to CMake's optimization of the link command.

In conclusion, I don't think that CMake's behavior you've reported is a
bug or has anything to do with libraries treated as static or shared or
the like. Of course, feel free to ask further if I missed your issue.

Regards,

Michael

> On 2/2/11 4:13 PM, Michael Hertling wrote:
>> On 02/02/2011 03:04 PM, Marco wrote:
>>> Hi all,
>>>
>>> I'm wondering, if I understood correctly the behaviour of CMake, whether
>>> there'a a way to prevent CMake from deleting duplicated libraries in a
>>> target_link_libraries list.
>>>
>>> I have an executable which links against (all static) libraries A, B and
>>> C. A itself links against C,D,E... and so on. When CMake creates the
>>> link.txt file what I see is:
>>>
>>> c++ -o myExe -lA -lC -lD -lE -lB
>>>
>>> that is cmake links the executable against A followed by its dependents,
>>> then against B but not against C. The point is that B needs C to follow
>>> it as B depends on C. This is why I suspect that CMake removes the
>>> duplicated libraries listed in a target_link_libraries directive.
>>>
>>> Is it correct? And is there a way to force CMake to preserve exactly the
>>> list of libraries passed to target_link_libraries?
>>
>> If B depends on C without C appearing after B in the link command, this
>> probably means that CMake isn't aware of the B-on-C dependency, so how
>> do you establish the latter? Could you provide a minimal but complete
>> example which demonstrates this issue?
>>
>> AFAIK, CMake does not remove libraries from the link command if they
>> are necessary to resolve any dependencies and if these dependencies
>> are set up correctly, so the libraries' exact order - for library
>> targets - is nothing the user usually needs to worry about.
>>
>> Regards,
>>
>> Michael


More information about the CMake mailing list