[CMake] DESTDIR behaviour with different variable name

Michael Hertling mhertling at online.de
Wed Apr 13 23:57:34 EDT 2011


On 04/12/2011 04:36 PM, Tomasz Grobelny wrote:
> On Tue, 12 Apr 2011 03:44:04 +0200, Michael Hertling <mhertling at online.de>
> wrote:
>> On 04/11/2011 10:42 PM, Tomasz Grobelny wrote:
>>> On Monday 11 April 2011 21:55:48 Alexander Neundorf wrote:
>>>> On Monday 11 April 2011, Tomasz Grobelny wrote:
>>>>> On Mon, 11 Apr 2011 09:01:09 -0700, Tyler <tyler at cryptio.net> wrote:
>>>>>> On Mon, Apr 11, 2011 at 8:54 AM, Tomasz Grobelny
>>>>>>
>>>>>> <tomasz at grobelny.oswiecenia.net> wrote:
>>>>>>> Ok, but is there a way to achieve the same effect so that the user
>>>>>>> can
>>>>>>> type just "make install" and not know anything about DESTDIR
>>>>> environment
>>>>>>> variable (provided he knows about MYDESTDIR)? Maybe it is possible
> to
>>>>>>> put this "DESTDIR=$MYDESTDIR" in the generated Makefiles somehow...
>>>>>>
>>>>>> If I understand your use case right (which I might not as you
> haven't
>>>>>> described what you're trying to do, just how you're trying to do
> it),
>>>>>> maybe you can just override CMAKE_INSTALL_PREFIX.
>>>>>>
>>>>>> If you go this route, check the archives because of the whole
>>>>>> _INITIALIZED_TO_DEFAULT aspect of that particular cache variable.
>>>>>
>>>>> I already tried playing with CMAKE_INSTALL_PREFIX but the problem was
>>>>> that value of MYDESTDIR was read (and saved to CMAKE_INSTALL_PREFIX)
>>>>> only when configuring first time. That's why DESTDIR mechanism comes
>>>>> closer to what I'm trying to achieve. My use case is something like
>>>>> that:
>>>>> 1. User has some default MYDESTDIR to non writable location.
>>>>> 2. User executes "cmake . && make install".
>>>>> 3. The installation fails because user has no rights to $MYDESTDIR.
>>>>> 4. User changes MYDESTDIR to another location (writable this time).
>>>>> 5. User executes "make install" once again and it should succeed.
>>>>>
>>>>> Of course the user could set MYDESTDIR to correct location before
>>>>> building but people often forget that. Now the tricky part is that
>>>>> users
>>>>> are already used to this mechanism (for particular variable name,
>>>>> called
>>>>> MYDESTDIR here). So taking different environment variable instead of
>>>>> DESTDIR would allow me to minimize confusion among users. Otherwise
>>>>> I'll
>>>>> just tell them to set yet another variable (DESTDIR). But I would
> like
>>>>> to avoid that if at all possible.
>>>>
>>>> DESTDIR has a different purpose.
>>>> Installing to DESTDIR does not necessarily lead to a working and
> correct
>>>> installation, mainly when paths are involved, like e.g. RPATH
> settings.
>>>> Assuming that CMAKE_INSTALL_PREFIX would be /opt/foo, your executable
>>>> might
>>>> get /opt/foo/lib as RPATH, also when installed to $DESTDIR/opt/foo.
>>>> So they will not have a correct RPATH.
>>>> You really should set CMAKE_INSTALL_PREFIX.
>>>>
>>> I'd like to. But CMAKE_INSTALL_PREFIX does not get recomputed when I
>>> change
>>> MYDESTDIR and try to do "make install" again. Or at least I don't know
>>> how to
>>> make it behave this way.
>>> Besides, I don't use RPATH (at least not explicitely, hopefully cmake
> is
>>> not
>>> doing anything nasty behind the scenes).
>>
>> But some day, you might want to use RPATH features as they are very
>> convenient in certain situations, or you might want to incorporate
>> the installation prefix or derivatives like CMAKE_INSTALL_PREFIX/lib
>> /${PROJECT_NAME} in your binaries which can be quite convenient, too.
>> Moreover, you can hardly prevent your project's users to use RPATH on
>> their own, see the CMAKE_INSTALL_RPATH/CMAKE_BUILD_WITH_INSTALL_RPATH
>> variables, e.g. In this regard, using the DESTDIR Makefile/environment
>> variable bears the risk of subtle failures and isn't worth the effort,
>> IMO. Thus, you should take Alex's warning absolutely seriously, or in
>> other words: Changing the installation prefix does invalidate your
>> already built targets, so you do need to reconfigure and rebuild.
>>
>> Anyway, see [1] for a chance to add "DESTDIR=$MYDESTDIR" to the
>> generated Makefiles, provided that you are using GNU Make, but
>> even this won't work as expected since DESTDIR is hard-coded
>> in CMake, AFAIK, and due to other reasons.
>>
>> [1] http://www.mail-archive.com/cmake@cmake.org/msg34344.html
>>
> Somewhat hackish (especially this \$\(firstword \$\(MAKEFILE_LIST\)\)

Hackish, ugly, non-portable and absolutely inadvisable. ;-)

> part). I've just come up with another solution (probably not less hackish,
> but simpler and working):
> set(CMAKE_INSTALL_PREFIX "\$ENV{MYDESTDIR}")

That's not hackish, IMO, but even quite elegant, indeed. Nevertheless,
the limitations and risks mentioned earlier in this thread still hold.
A rather obvious example for the shortcomings of that approach is the
installation of a configuration file for the concerned package; see
the following CMakeLists.txt for a highly rudimentary realisation:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(MYDESTDIR C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_INSTALL_PREFIX "\$ENV{MYDESTDIR}")
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
ADD_LIBRARY(f SHARED f.c)
FILE(WRITE ${CMAKE_BINARY_DIR}/f-config.cmake "FIND_LIBRARY(
    F_LIBRARY f PATHS ${CMAKE_INSTALL_PREFIX}/lib NO_DEFAULT_PATH
)\n")
INSTALL(TARGETS f LIBRARY DESTINATION lib)
INSTALL(FILES ${CMAKE_BINARY_DIR}/f-config.cmake DESTINATION share)

Here, $ENV{MYDESTDIR} will end up as the installation prefix in the
config file, so another project that calls FIND_PACKAGE(f) to learn
about libf.so's location would need to have MYDESTDIR defined in its
environment. Thus, you extend the need for this environment variable
from your project to your project's users, i.e. you're about to shoot
yourself in the foot, and even worse, you're about to shoot in another
one's foot. OK, you might do some last-minute-modifications during the
installation with INSTALL(CODE/SCRIPT ...), or you might try to use the
CMAKE_CURRENT_LIST_FILE variable to find a way from the config file to
the library as it is done in the export files from INSTALL(EXPORT ...),
but I wonder if this can be set up in a bullet-proof way. To summarize,
delaying the expansion of CMAKE_INSTALL_PREFIX up to the installation
is most inconvenient for projects which install configuration files.

Regarding this and the already mentioned issues in this respect, for
what reason should one bank on an installation prefix evaluated at
installation time? Just because the users are accustomed to "make
install MYDESTDIR=..."? As I said before, I think that this is
worth neither the effort nor the limitations nor the risks.

Regards,

Michael


More information about the CMake mailing list