CMake中与'configure --prefix = DIR && make all install'相当的是什么?

456
我执行了"cmake . && make all install"命令,它可以正常工作,但会安装到/usr/local目录。
我需要将其安装到其他前缀目录(例如/usr)。
请问如何修改cmakemake的命令行参数以将其安装到/usr而不是/usr/local

2
这是一个很好的问题,可以在安装过程中动态更改安装目录,但为什么这似乎是一个常见需求呢?从我的角度来看,答案应该是不要使用命令行选项,而是编辑基本的“CMakeLists.txt”,这样您就可以设置并忘记它。我并不是说在安装过程中动态更改安装目录没有常见用例 - 根据投票数量显然有 - 我只是相对较新于CMake,并且好奇这个问题何时出现。 - CivFan
12
这是为了迎合想要将项目构建和安装到特定位置的用户,但这些用户并非项目的开发人员/维护者。 - David Röthlisberger
6
作为一个维护者,经常会测试我的 make install 命令以确保所有需要安装的东西都被正确地安装到了指定位置,而不会破坏我的开发机器。这只是一个例子。另一个情况是为另一个架构进行交叉编译。 - Daniel
8
@CivFan:我需要这个因为我想要构建一个RPM包。如果我需要改变CMakeLists.txt文件,那么我就需要打补丁来修改原始源代码。只需使用一个命令行选项,就可以让我在Fedora的spec文件中正确获取路径信息。 - Martin Ueding
4
@CivFan(以及其他阅读此内容的人)FYI,如果您只是构建和安装软件,则通常认为编辑“ CMakeLists.txt”文件是一个不好的主意 - 从命令行或初始缓存文件覆盖/设置变量等方式是设置选项的首选“消费者”方式。 - Ryan Pavlik
@CivFan(是的,晚了5年):在一个大型集群(超级计算机)上,您可能希望帮助用户在本地安装软件。命令行选项更方便,更容易解释,或者添加到他们可以剪切和粘贴的代码片段中。更不用说我们正在谈论各种各样的软件和具有非常不同知识水平的用户(科学家不一定是IT专家)。 - runlevel0
9个回答

516
您可以在命令行中传递任何CMake变量,或使用ccmake/cmake-gui编辑缓存的变量。在命令行中,
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr . && make all install
将配置该项目,构建所有目标并安装到/usr前缀。类型(PATH)不是绝对必要的,但会导致基于Qt的cmake-gui呈现目录选择器对话框。
一些小的补充说明使得简单的等价提供对某些人来说是不够的。最佳做法是使用外部构建目录,即不是源直接使用。还要使用更通用的CMake语法抽象生成器。
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. && cmake --build . --target install --config Release 您会发现命令变得相当冗长,并且不再直接等价,但它更接近最佳实践,并且形式相当简明... --config仅由多配置生成器(例如MSVC)使用,其他生成器忽略它。

25
想知道 :PATH 是什么吗?它对于 cmake-gui 非常有用,可以帮助选择变量的小部件。请参阅 http://linux.die.net/man/1/cmake-gui 中的文档(set 部分)。 - albfan
2
正如所述,它们为CMake GUI提供提示。在CMake中,所有内容都有效地是字符串,但设置PATH、FILEPATH、STRING、BOOL等有助于GUI呈现更合适的小部件。 - Marcus D. Hanwell
15
你也可以使用 "cmake --build --target install ." 代替 make。 - RobertJMaynard
2
在 /usr 后面的点是什么意思?/usr . - bodacydo
7
CMakeLists.txt所在的文件夹位置,我们正在从中生成代码。 - Kamiccolo
显示剩余10条评论

68

在被接受的答案中,":PATH" 这部分可以省略。以下语法可能更易记:

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

...如此处中的答案所述。


10
:PATH 不是错误。 - kirbyfan64sos

37

请注意,在CMake和Autotools中,您不必总是在配置时设置安装路径。您可以在安装时使用 DESTDIR(也可参见此处):

make DESTDIR=<installhere> install

请参考这个问题,它解释了DESTDIRPREFIX之间微妙的区别。

这是为分阶段安装而设计的,可以允许程序存储在与运行位置不同的位置,例如通过符号链接到/etc/alternatives等位置。

然而,如果您的软件包可重定位并且不需要通过配置阶段设置任何硬编码(前缀)路径,您可能可以跳过它。 因此,代替:

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

你需要运行:

cmake . && make DESTDIR=/usr all install

注意,正如user7498341所指出的那样,这并不适用于您真正应该使用PREFIX的情况。


11
我喜欢展示DESTDIR的使用,但这实际上是错误的。您应该参考cmake文档https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html... 使用命令make DESTDIR=/home/john install 安装相关软件,会使用安装前缀(例如“/usr/local”)加上DESTDIR的值,最终得到“/home/john/usr/local”。 - Joakim
3
我不认为这是矛盾的。如果你的软件包是可重定位的,那么你就不需要CMAKE_INSTALL_PREFIX,或者说你可以选择任何一种方法。但如果它不是可重定位的,那么你就需要使用CMAKE_INSTALL_PREFIX,因为在构建时CMAKE_INSTALL_PREFIX将被嵌入到某个地方。 - Bruce Adams
1
如果您知道您的生成器是Makefile,我更喜欢使用cmake --build build --target install -- DESTDIR=/usr。注意:这也适用于Ninja生成器(规则似乎包含$ENV{DESTDIR})。 - Mizux
1
@Joakim 尽管我很想使用 CMAKE_INSTALL_PREFIX,但这样做会将安装路径嵌入到编译后的文件中。恰好我只是在构建一个 .rpm 包,所以这样做行不通。DESTDIR 对于将东西放入 buildroot 中非常有效。 - Mr Redstoner

23

从CMake 3.15开始,实现这一点的正确方法是使用:

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

官方文档

注意,cmake --install 不会为您调用 cmake --build


2
“支持”并不意味着“正确”——这有其用处,但由于构建和安装比生成构建系统更频繁,因此在生成构建系统时仅设置环境变量通常更安全。两种方法都是“正确”的,具体取决于使用情况。 - Woodrow Barlow
<dir>是指构建目录的路径吗?通常是build/吗? - undefined

19

我跨平台构建CMake项目的方式如下:

/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
  • 前两行创建了源外构建目录
  • 第三行生成了构建系统,并指定了安装结果的位置(我总是将其放在./project-root/build/stage中——如果路径不是绝对路径,则始终被认为是相对于当前目录的)
  • 第四行使用构建系统中配置好的.项目进行构建。它将执行 install 目标,如果需要构建所有必要依赖目标,然后将文件复制到 CMAKE_INSTALL_PREFIX 中(在本例中为 ./project-root/build/stage)。对于多配置构建,例如在Visual Studio中,您还可以使用可选的--config <config>标志来指定配置。
  • 当使用cmake --build命令时,好处在于它适用于所有生成器(即makefile和Visual Studio),无需不同的命令。

之后,我使用安装的文件创建软件包或将其包含在其他项目中...


感谢逐步解释!在我看来,这是唯一的方法,否则 cmake(平台无关性)的整个意义都将被抛弃... - helmesjo
1
你是不是忘了在第三行中包含源路径(../)?顺便说一句,这应该是被接受的答案。 - Slava
1
第三行应该是 cmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage .. - codenamezero
1
另外需要注意的是,实际上人们使用make -j $(nproc)指定构建线程数,在Makefile生成器中执行cmake --build . --target=install --config=Release -- -j 8,或在Visual Studio生成器中执行cmake --build . --target=install --config=Release -- /m:8来使用8个线程。实际上,你可以在--之后传递任何命令行参数。 - Cloud
1
@MrRedstoner -j 不是 cmake 的标志,所有的标志都要在 -- 之后传递给底层构建系统... - Cloud
显示剩余3条评论

12

从CMake 3.21 开始,您可以使用--install-prefix选项代替手动设置CMAKE_INSTALL_PREFIX

configure --prefix=DIR && make all install的现代等价物现在将是:

cmake -B build --install-prefix=DIR
cmake --build build
cmake --install build

7

关于Bruce Adams的回答:

您的回答会造成危险的混淆。DESTDIR用于安装根目录之外的内容。如果不指定DESTDIR,它允许您查看将被安装在根目录中的内容。PREFIX是实际安装基础目录。

例如,PREFIX=/usr/local 表示软件包的 最终 目的地是 /usr/local。使用 DESTDIR=$HOME 将文件安装为 $HOME 是根 (/)。如果 DESTDIR 是 /tmp/destdir,那么可以查看 'make install' 会影响到什么。在这种情况下,DESTDIR不应该影响构建对象。

一个解释 makefile 的片段:

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

程序必须假定PREFIX是最终(即生产)目录的基本目录。在DESTDIR=/something安装程序的符号链接可能意味着该程序不会根据PREFIX访问文件,因为这样做将无法工作。 cat(1) 是一个程序,它可以在任何地方(以其最简单的形式)运行。以下是一个不行的示例:

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

如果您试图从$PREFIX/bin/prog以外的地方运行prog,那么由于它不在预期位置中,prog.db将找不到。
最后,/etc/alternatives真的不是这样工作的。有符号链接指向安装在根目录树中的程序(例如vi -> /usr/bin/nvi, vi -> /usr/bin/vim等)。

2
这个答案可能更适合作为回答https://dev59.com/hGgu5IYBdhLWcg3wdG2o的答案。 - Bruce Adams

6

如果使用CMake,调用实际的构建系统(例如通过make命令)被认为是不良做法。强烈建议按如下方式进行:

  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
    

在采用这种方法时,可以轻松地切换生成器(例如 -G Ninja 用于 Ninja),无需记忆任何生成器特定的命令。

请注意,CMAKE_BUILD_TYPE 变量仅由单配置生成器使用,而构建命令的 --config 参数仅由多配置生成器使用。


4
如果为所有使用的论点提供解释并说明它们的用途,那么答案可能会更好。特别是,“--config”参数的作用是什么? - Dmitry Kabanov
2
请勿使用未记录的“-H”标志。官方支持的替代选项是“-S”。 - Alex Reinking
1
@DmitryKabanov CMake支持许多生成器。但是,有两个类别-单配置(如Make和Ninja)和多配置(如Visual Studio)。第一类依赖于在配置期间建立的CMAKE_BUILD_TYPE。第二类依赖于在构建(然后也安装)期间提供的--config参数。这是因为使用多配置生成器,可以从单个CMake配置构建许多类型。 - Adam Badura
我已经改进了我的答案。感谢您的反馈。 - Florian Wolters

2
很多答案,但我想做一个总结来正确地归类并解释它们之间的差异。
首先,您可以以两种方式定义前缀:在配置时或安装时,并且这取决于您的需求。

在配置时

两个选项:
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

安装时

优点:如果想要更改,无需重新配置。

两个选项:

cmake DESTDIR=$install_dir --build $build_dir --target=install # Makefile only
cmake --install $build_dir --prefix=$install_dir 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接