[CMake] Changing installation prefix triggers re-linking of all libraries

Michael Hertling mhertling at online.de
Tue May 3 12:16:22 EDT 2011


On 05/03/2011 11:17 AM, Pere Mato Vila wrote:
> 
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
>> PROJECT(PREFIX C)
>> SET(CMAKE_VERBOSE_MAKEFILE ON)
>> ADD_LIBRARY(f SHARED f.c)
>> INSTALL(TARGETS f
>>    RUNTIME DESTINATION bin
>>    LIBRARY DESTINATION lib
>>    ARCHIVE DESTINATION lib)
>>
>> with ${CMAKE_SOURCE_DIR}/f.c containing just "void f(void){}". After
>> configuring/building/installing, a reconfiguration with a modified
>> CMAKE_INSTALL_PREFIX does not result in recompiling or relinking.
> 
> 
> Hi Michael,
> 
> In you simple example adding SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") before ADD_LIBRARY(...) does trigger a re-build of the library when changing the length of CMAKE_INSTALL_PREFIX. The reason for this behavior was given by Alex Neundorf:
>  
>> Then you set the install RPATH once to "/build/mato/ROOT/install/lib" and then 
>> to "/build/mato/ROOT/install2/lib", which is one byte longer. So the binary 
>> has to be created again with one byte more room for the install RPATH.

Yes, that's true, indeed, but one must distinguish two factors:

1. Basically, it's the incorporation of the CMAKE_INSTALL_PREFIX in the
library via CMAKE_INSTALL_RPATH that causes the library to be relinked
when CMAKE_INSTALL_PREFIX changes. This is why I have said that solely
changing the latter doesn't cause any recompilation or relinking; one
rather needs further interconnections for this to happen.

2. The, say, placeholder mechanism described by Alex is the reason why
the library is relinked in the *build tree* when CMAKE_INSTALL_RPATH's
length changes although the latter isn't incorporated in the library's
build-tree-instance due to CMAKE_BUILD_WITH_INSTALL_RPATH being FALSE.

If I understand correctly, it's this second point which causes your
astonishment, but it already happens during the build phase in the
build tree, not just when installing with "make install", right?

> The fact that the build is re-done because I change the length of the installation destination I would call this a bug and not really a feature.

IMO, it's not a bug, but even quite clever. The placeholder mechanism
allows to avoid a complete relink operation at installation time when
the final RPATH must be written to the installed binaries. Look at the
cmake_install.cmake script for the above-noted project with the line
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") you mentioned.
You will find a FILE(INSTALL ...) followed by a FILE(RPATH_CHANGE ...)
which operates on the already installed library. The latter command is
implemented by cmSystemTools::ChangeRPath() and probably much cheaper
than a full-featured invocation of the linker involving fork()/exec(),
the compiler's front-end, object files, libraries, LTO, recompilation
of automatically generated source code etc. In other words: Linking
might be expensive, but patching binaries is not.

Now, with the placeholder mechanism, you currently have two (re)link
operations: One for each CMAKE_INSTALL_PREFIX in the build tree, but
none during the two installations. Without the placeholder mechanism,
you'd need three operations: One in the build tree without the final
RPATHs or placeholders and one during each of the two installations.
Therefore, the placeholder mechanism is highly useful - despite the
potentially surprising relink operations within the build tree.

Regards,

Michael


More information about the CMake mailing list