Set installation prefix automatically to custom path if not explicitly specified on the command line

13,069

Solution 1

CMake sets the boolean variable CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT if CMAKE_INSTALL_PREFIX has not been explicitly specified and is initialized to its default setting. You can override it in the following way:

if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
    set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/installed"
           CACHE PATH "default install path" FORCE)
endif()

Solution 2

A few years ago, I wanted to attempt the same thing. Unfortunately I could never find a fully satisfactory solution. Instead, I chose to use a regex to check if CMAKE_INSTALL_PREFIX matches the default.

E.g. on windows I use the following to create the install dir in the build-directory:

if ( CMAKE_INSTALL_PREFIX MATCHES "^C:/Program Files" )
    # Override to an "Install" directory in the current build-dir
    message( STATUS "    Install-prefix was at default -> forcing it to the build-dir" )
    message( STATUS "        'set( CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install )'" )
    set( CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install )
endif ( CMAKE_INSTALL_PREFIX MATCHES "^C:/Program Files" )

The biggest problem with this construct is that you can specify manually that CMake should install into C:\Program Files. As I distribute my tool with an NSIS-installer this is not an issue (for me).

Perhaps you could try something similar on Unix.

Share:
13,069
Jeet
Author by

Jeet

Updated on June 14, 2022

Comments

  • Jeet
    Jeet almost 2 years

    For some internal tests, I would like the install prefix to default to a subdirectory of the build directory, unless explicitly overridden by the user. I know the user can specify a install prefix by:

    $ cmake -DCMAKE_INSTALL_PREFIX=/foo/bar ..
    

    But if the user does not specify this, it should default to, e.g. ${PWD}/installed.

    The variable CMAKE_INSTALL_PREFIX is already set to /usr/local, so I cannot just check to see if it unset/empty before setting it.

    My current solution is to add a custom switch that the user has to invoke to specify that the CMAKE_INSTALL_PREFIX variable gets respected:

    option(ENABLE_INSTALL_PREFIX "Install build targets to system (path given by '-DCMAKE_INSTALL_PREFIX' or '${CMAKE_INSTALL_PREFIX}' if not specified)." OFF)
    if ( ENABLE_INSTALL_PREFIX )
        set (CMAKE_INSTALL_PREFIX installed CACHE PATH "Installation root")
    else()
        set (CMAKE_INSTALL_PREFIX installed CACHE PATH "Installation root" FORCE)
    endif()
    

    My questions are:

    (a) Are there any issues with the above, beyond the annoyance of the extra flag needing to be passed to CMake to get CMAKE_INSTALL_PREFIX to have an effect?

    (b) Is there a better, cleaner, more robust, more idiomatic and/or less annoying way to achieve the above?

    Thanks.

  • KarateSnowMachine
    KarateSnowMachine over 9 years
    I wish I found this post a few days ago while I was pulling my hair out trying to get multiple ExternalProject dependencies to do the right thing. Thanks!
  • thiagowfx
    thiagowfx over 7 years
    On Unix one would use "^/usr/local" in the matching; or, even better, STREQUAL "/usr/local" instead of a regular expression matching.