453

I do cmake . && make all install. This works, but installs to /usr/local.

I need to install to a different prefix (for example, to /usr).

What is the cmake and make command line to install to /usr instead of /usr/local?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrei
  • 8,606
  • 10
  • 35
  • 43
  • 2
    This is a great question for changing the install directory on the fly, but why is this such an apparently common need? From my perspective, the answer should be DON'T use a command line option, instead edit the base ``CMakeLists.txt`` so you can set it and forget it. I'm not saying there isn't a common use case for changing the install directory on the fly -- clearly there is judging by the number of votes -- I'm just fairly new to CMake and curious when this problem comes up. – CivFan Oct 15 '15 at 22:32
  • 12
    @CivFan it's to cater to users who want to build & install the project to a particular location, but aren't the same people as the developers/maintainers of the project. – David Röthlisberger Mar 04 '16 at 12:33
  • 6
    @CivFan So as a maintainer, its not uncommon for me to test my `make install` to a temporary path to make sure everything that needs to be installed, got installed to the right location without messing up my development machine. Just one example. Another case is cross-compiling for another architecture. – Daniel Mar 06 '16 at 15:15
  • 8
    @CivFan: I need this because I want to build an RPM package. If I would need to change the `CMakeLists.txt`, then I need to patch the original source. Just having a command line option allows me to get the paths right in the Fedora `spec` file. – Martin Ueding Oct 28 '16 at 13:50
  • 4
    @CivFan (and others reading this) FYI, it's generally considered a bad idea to edit the `CMakeLists.txt` file if you're just building and installing software - overriding/setting variables from command line or initial cache file, etc. is the preferred "consumer" way of setting options. – Ryan Pavlik Jul 05 '18 at 14:27
  • @CivFan (yeah, 5 years too late) : On a big cluster (supercomputer) you may want to help the users with installing stuff locally. A command line option is way more convenient and easier to explain, or add to a snippet they can cut&paste. Not to mention that we are talking about a wide variety of software and users with very different level of knowledge (scientists are not necessarily IT experts) – runlevel0 Dec 10 '21 at 10:18

9 Answers9

514

You can pass in any CMake variable on the command line, or edit cached variables using ccmake/cmake-gui. On the command line,

cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr . && make all install

Would configure the project, build all targets and install to the /usr prefix. The type (PATH) is not strictly necessary, but would cause the Qt based cmake-gui to present the directory chooser dialog.

Some minor additions as comments make it clear that providing a simple equivalence is not enough for some. Best practice would be to use an external build directory, i.e. not the source directly. Also to use more generic CMake syntax abstracting the generator.

mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. && cmake --build . --target install --config Release

You can see it gets quite a bit longer, and isn't directly equivalent anymore, but is closer to best practices in a fairly concise form... The --config is only used by multi-configuration generators (i.e. MSVC), ignored by others.

Marcus D. Hanwell
  • 6,716
  • 1
  • 21
  • 20
  • Found this helpful building a package for Mydumper, which uses CMake. Thx! – astrostl Mar 26 '12 at 14:50
  • 25
    Wondering what :PATH is? It's useful for cmake-gui, helping to choose the widget for that variable. See doc in http://linux.die.net/man/1/cmake-gui (set section) – albfan Oct 26 '12 at 05:23
  • I think that the `:PATH` is necessary. – Hal Canary May 15 '13 at 13:35
  • 2
    They provide hints to the CMake GUI as stated, everything in CMake is effectively a string, but setting PATH, FILEPATH, STRING, BOOL etc help the GUI to present a more appropriate widget. – Marcus D. Hanwell May 22 '13 at 16:54
  • 15
    You can also use: "cmake --build --target install ." instead of make. – RobertJMaynard Dec 06 '13 at 20:44
  • That seems longer on Unix, but easier on Windows ;-) The all is not required above, but I left it in as the question asked for the closest equivalent... – Marcus D. Hanwell Dec 06 '13 at 20:47
  • Using @RobertJMaynard's suggestion is easier when building with Visual Studio 10 or more recent. – Pedro Lamarão Jul 30 '14 at 17:15
  • 2
    What is the dot for after /usr? `/usr .` – bodacydo Oct 25 '14 at 01:37
  • 7
    @bodacydo location of the folder with CMakeLists.txt we're generating from. – Kamiccolo Dec 16 '14 at 15:22
  • 1
    @MarcusD.Hanwell the real advantage is platform/generator independence – Joe Sep 24 '15 at 09:33
  • @Joe I couldn't agree more, but it can help people who come from other tools to see some simple equivalent commands too! – Marcus D. Hanwell Sep 28 '15 at 17:43
  • If I do this (using `/usr/local` instead actually), the files still get installed in `./install`. Has anything changed in newer `cmake` (2.18.12.2)? – Shahbaz Dec 10 '15 at 16:24
  • Nevermind, the project was overriding `CMAKE_INSTALL_PREFIX` in `CMakeLists.txt`! – Shahbaz Dec 10 '15 at 16:26
  • 1
    recipe for an in-source build with hardcoded `make' gets ~350 upvotes... Seriously?! – Slava Mar 22 '18 at 10:08
  • 1
    It was asking for equivalence as asked in the question, not best practices. These can be helpful in learning tools. If you read the question this is clearly a reasonable answer, but if I was asked for the best practice then I would certainly advise you to use a separate build directory and the longer/more portable cmake --build syntax... Seriously! – Marcus D. Hanwell Oct 13 '18 at 19:18
66

The ":PATH" part in the accepted answer can be omitted. This syntax may be more memorable:

cmake -DCMAKE_INSTALL_PREFIX=/usr . && make all install

...as used in the answers here.

Community
  • 1
  • 1
user2023370
  • 10,488
  • 6
  • 50
  • 83
  • 10
    [`:PATH` isn't a mistake](http://stackoverflow.com/questions/6003374/what-is-cmake-equivalent-of-configure-prefix-dir-make-all-install#comment17772293_6003937). – kirbyfan64sos Aug 07 '16 at 19:28
37

Note that in both CMake and Autotools you don't always have to set the installation path at configure time. You can use DESTDIR at install time (see also here) instead as in:

make DESTDIR=<installhere> install

See also this question which explains the subtle difference between DESTDIR and PREFIX.

This is intended for staged installs and to allow for storing programs in a different location from where they are run e.g. /etc/alternatives via symbolic links.

However, if your package is relocatable and doesn't need any hard-coded (prefix) paths set via the configure stage you may be able to skip it. So instead of:

cmake -DCMAKE_INSTALL_PREFIX=/usr . && make all install

you would run:

cmake . && make DESTDIR=/usr all install

Note that, as user7498341 points out, this is not appropriate for cases where you really should be using PREFIX.

Alexander
  • 23,432
  • 11
  • 63
  • 73
Bruce Adams
  • 4,953
  • 4
  • 48
  • 111
  • 11
    I like showing the use of `DESTDIR`. But actually this is wrong. You should refer to the cmake docs https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html ... `make DESTDIR=/home/john install` which will install the concerned software using the installation prefix, e.g. “/usr/local” prepended with the DESTDIR value which finally gives “/home/john/usr/local”. – Joakim Apr 01 '16 at 20:15
  • 3
    I don't think that's contradictory. If your package is relocatable you don't need CMAKE_INSTALL_PREFIX, or rather you can choose either method. If it isn't you do because CMAKE_INSTALL_PREFIX will be baked in somewhere at build time. – Bruce Adams Apr 02 '16 at 21:32
  • 1
    if you know that your generator is Makefile... I prefer `cmake --build build --target install -- DESTDIR=/usr` note: this should also work with Ninja generator (rules seems to contains `$ENV{DESTDIR}`) – Mizux Jan 30 '20 at 08:55
  • 1
    @Joakim as much as I'd like to use CMAKE_INSTALL_PREFIX, doing so embedded the install path in the compiled files. As it happens, I was merely building a .rpm package, so that wouldn't do. DESTDIR worked like a charm for getting things into buildroot. – Mr Redstoner Feb 11 '20 at 11:45
22

Starting with CMake 3.15, the correct way of achieving this would be using:

cmake --install <dir> --prefix "/usr"

Official Documentation

Pay attention that cmake --install does not call cmake --build for you.

malat
  • 12,152
  • 13
  • 89
  • 158
ExaltedBagel
  • 582
  • 5
  • 14
  • 2
    "supported" doesn't mean "correct" -- this has its uses but since building and installing happens more often than generating the build system, it's often safer to just set the env var when generating the build system. both are "correct" depending on use case. – Woodrow Barlow Jan 25 '21 at 15:19
19

The way I build CMake projects cross platform is the following:

/project-root> mkdir build
/project-root> cd build
/project-root/build> cmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
/project-root/build> cmake --build . --target=install --config=Release
  • The first two lines create the out-of-source build directory
  • The third line generates the build system specifying where to put the installation result (which I always place in ./project-root/build/stage - the path is always considered relative to the current directory if it is not absolute)
  • The fourth line builds the project configured in . with the buildsystem configured in the line before. It will execute the install target which also builds all necessary dependent targets if they need to be built and then copies the files into the CMAKE_INSTALL_PREFIX (which in this case is ./project-root/build/stage. For multi-configuration builds, like in Visual Studio, you can also specify the configuration with the optional --config <config> flag.
  • The good part when using the cmake --build command is that it works for all generators (i.e. makefiles and Visual Studio) without needing different commands.

Afterwards I use the installed files to create packages or include them in other projects...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
toeb
  • 481
  • 5
  • 9
  • Thanks for the step by step explanation! IMO this is the only way, otherwise the whole point of cmake (platform independence) is discarded... – helmesjo Jul 01 '17 at 05:39
  • 1
    did you forget to include path to sources (../) in line 3? BTW this should be the accepted answer. – Slava Mar 22 '18 at 10:10
  • 1
    LIne 3 should be `cmake -G "" -DCMAKE_INSTALL_PREFIX=stage ..` – codenamezero Mar 28 '18 at 18:58
  • 1
    As an additional note, pragmatically, people use `make -j $(nproc)`, to specify the number of build threads, do `cmake --build . --target=install --config=Release -- -j 8` for Makefile generator or `cmake --build . --target=install --config=Release -- /m:8` for Visual Studio generator with 8 threads. Actually, you can pass any commandline parameters after `--` – Cloud Apr 02 '19 at 09:48
  • @Cloud sadly -j is not available in all distributions for which Cmake is packaged. `-j` was added in 3.12, counting on pkgs.org I'm seeing 17 systems with cmake listed <3.12, for example Ubuntu 18.04 Busy Beaver has 3.10 only. – Mr Redstoner Feb 11 '20 at 11:50
  • 1
    @MrRedstoner `-j` is not a flag for cmake, all flags come after `--` is passing to the underlying build system... – Cloud Feb 11 '20 at 13:50
  • @Cloud wow neat! I though cmake would have such an option, then found the changelog for 3.12 which was newer than mine. Was kinda sad. Didn't realize you could sneak it past cmake in the earlier versions. I shall remember that. – Mr Redstoner Feb 11 '20 at 21:15
  • Nice! However, you can do more (at least today - I'm not going to check which feature was added when). Firstly, CMake can work "out of source" with `-S` and `-B` arguments on configuration and then `--build` / `--install` during those steps. So, no need to do any `cd`. Then a purist will add that `cmake -E make_directory ` replaces `mkdir` in platform independent way. Then add `-DCMAKE_BUILD_TYPE=Release` to configuration to support single config generators. Finally, skip `--target=install` and instead invoke `cmake --install`. – Adam Badura Sep 17 '21 at 21:07
11

Starting with CMake 3.21 you can use the --install-prefix option instead of manually setting CMAKE_INSTALL_PREFIX.

The modern equivalent of configure --prefix=DIR && make all install would now be:

cmake -B build --install-prefix=DIR
cmake --build build
cmake --install build
Tachi
  • 489
  • 8
  • 16
7

Regarding Bruce Adams answer:

Your answer creates dangerous confusion. DESTDIR is intended for installs out of the root tree. It allows one to see what would be installed in the root tree if one did not specify DESTDIR. PREFIX is the base directory upon which the real installation is based.

For example, PREFIX=/usr/local indicates that the final destination of a package is /usr/local. Using DESTDIR=$HOME will install the files as if $HOME was the root (/). If, say DESTDIR, was /tmp/destdir, one could see what 'make install' would affect. In that spirit, DESTDIR should never affect the built objects.

A makefile segment to explain it:

install:
    cp program $DESTDIR$PREFIX/bin/program

Programs must assume that PREFIX is the base directory of the final (i.e. production) directory. The possibility of symlinking a program installed in DESTDIR=/something only means that the program does not access files based upon PREFIX as it would simply not work. cat(1) is a program that (in its simplest form) can run from anywhere. Here is an example that won't:

prog.pseudo.in:
    open("@prefix@/share/prog.db")
    ...

prog:
    sed -e "s/@prefix@/$PREFIX/" prog.pseudo.in > prog.pseudo
    compile prog.pseudo

install:
    cp prog $DESTDIR$PREFIX/bin/prog
    cp prog.db $DESTDIR$PREFIX/share/prog.db

If you tried to run prog from elsewhere than $PREFIX/bin/prog, prog.db would never be found as it is not in its expected location.

Finally, /etc/alternatives really does not work this way. There are symlinks to programs installed in the root tree (e.g. vi -> /usr/bin/nvi, vi -> /usr/bin/vim, etc.).

user7498341
  • 71
  • 1
  • 1
  • 2
    This answer might be better placed as an answer to http://stackoverflow.com/questions/11307465/destdir-and-prefix-of-make – Bruce Adams Feb 20 '17 at 18:52
6

It is considered bad practice to invoke the actual build system (e.g. via the make command) if using CMake. It is highly recommended to do it like this:

  1. Configure + Generation stages:

     cmake -S foo -B _builds/foo/debug -G "Unix Makefiles" -D CMAKE_BUILD_TYPE:STRING=Debug -D CMAKE_DEBUG_POSTFIX:STRING=d -D CMAKE_INSTALL_PREFIX:PATH=/usr
    
  2. Build and Install stages:

     cmake --build _builds/foo/debug --config Debug --target install
    

When following this approach, the generator can be easily switched (e.g. -G Ninja for Ninja) without having to remember any generator-specific commands.

Note that the CMAKE_BUILD_TYPE variable is only used by single-config generators and the --config argument of the build command is only used by multi-config generators.

Florian Wolters
  • 3,820
  • 5
  • 35
  • 55
  • 4
    The answer could have been better if explanation was provided to all the arguments used and why they are used. Particularly, what is the point of the `--config` argument? – Dmitry Kabanov Feb 05 '19 at 08:04
  • 2
    Don't use the undocumented `-H` flag. The officially supported replacement is `-S` – Alex Reinking Jul 04 '21 at 19:42
  • 1
    @DmitryKabanov CMake supports many generators. However, there are two classes - single configuration ones (like Make and Ninja) and multi-configuration ones (like Visual Studio). The first class relies on `CMAKE_BUILD_TYPE` established during configuration. The second class relies on `--config` argument provided during building (and then also installing). This is because with multi-configuration generators, unsurprisingly, you can build many types out of single CMake configuration. – Adam Badura Sep 17 '21 at 21:01
  • I've improved my answer. Thanks for the feedback. – Florian Wolters Nov 03 '21 at 11:22
2

Lots of answer, but I figured I'd do a summary to properly group them and explain the differences.

First of all, you can define that prefix one of two ways: during configuration time, or when installing, and that's really up to your needs.

During configuration time

Two options:

cmake -S $src_dir -B $build_dir -D CMAKE_INSTALL_PREFIX=$install_dir
cmake -S $src_dir -B $build_dir --install-prefix=$install_dir # Since CMake 3.21

During install time

Advantage: no need to reconfigure if you want to change it.

Two options:

cmake DESTDIR=$install_dir --build $build_dir --target=install # Makefile only
cmake --install $build_dir --prefix=$install_dir 
agirault
  • 2,509
  • 20
  • 24