CMake 学习三:CMake 工程实例

CMake 工程实例

本章不会像其他文章那样,直接使用 CMake 去编译一个 C/C++ helloworld 级别的源文件,因为那除了入门外,没有任何意义,而是让 helloworld 看起来更像一个工程,为此,先做如下准备:

  • 为工程添加一个子目录 src,放置源代码;
  • 为工程添加一个子目录 doc,放置说明文档;
  • 在工程中添加一个 README.md 文件,对整个工程进行简要说明;
  • 将生成的目标文件放入工程目录的 bin 子目录中;
  • 安装时,将 doc 目录和 README.md 放到指定的安装目录中。

若是库文件,还需要一个 include 目录,放置头文件,供其他程序引用,后面将库文件时会有说明。


helloworld 工程实例

先按照上面的步骤,建立好目录,并且创建 build 编译目录。其中 src 目录中也要有一个 CMakeLists.txt 文件,工程的结构如下

[mayw@localhost helloworld]$ tree .
.
├── build
├── CMakeLists.txt
├── doc
│   └── helloworld.txt
├── README.md
└── src
    ├── CMakeLists.txt
    └── helloworld.cpp

最外层的 CMakeLists.txt 文件内容

cmake_minimum_required(VERSION 3.5)

project(helloworld)
add_subdirectory(src bin)

src/CMakeLists.txt 文件内容

add_executable(helloworld helloworld.cpp)

src/helloworld.cpp 文件内容

#include <iostream>

int main(int argc, char *argv[])
{
    std::cout << "hello cmake ..." << std::endl;
    return 0;
}

其他的都比较好懂,唯一就是最外层的 CMakeLists.txt 文件的第四行 add_subdirectory 指令 ,前面介绍过,该指令是添加编译子目录的意思,但其实还有其他参数,格式如下,可参考 官方说明

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

参数说明:

  • source_dir

    必选参数,向当前工程中添加一个子目录并构建该子目录,而且子目录下应该包含 CMakeLists.tx 文件和源码文件;

  • binary_dir

    可选参数。指定一个目录,用于存放 source_dir 中的输出文件,即编译后的二进制文件或库文件。如果没有指定,则默认使用 source_dir 作输出目录。

  • EXCLUDE_FROM_ALL

    可选参数。若指定了该参数,则 source_dir 下的目标不会被包含,即父目录的 CMakeLists.txt 不会编译构建 source_dir 目录的目标文件,比如测试目录,此时,必须在 source_dir 目录下去显式构建。但是当父目录依赖 source_dir 中的目标文件时,该关系就会失效,仍然会构建 source_dir 目录 ,如使用了 target_link_libraries 链接 source_dir 中编译的库文件。

对应到 add_subdirectory(src bin) ,它的意思是将 src 子目录加入到工程中,并将编译结果输出到 build/bin 目录中。若不进行 bin 目录的指定,则编译结果(包含中间结果)都将存放在 build/src 目录中。

也可以使用 set 命令重新定义 EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH 变量,来指定最终二进制目标文件(包含库文件)的位置。哪里要改变存放路径,就应该将这一设置放在对应的 CMakeLists.txt 中。一般情况下用不到这两个变量。

以上一切都完成后,可以使用如下命令构建、编译和执行程序

$ cd build
$ cmake ..
$ make
$ cd bin		# 需要进入 bin 目录中,因为指定了输出目录。
$ ./helloworld
hello cmake ...

helloworld 工程安装

CMake 中安装工程一般分两步:

  • 在构建项目时使用 -DCMAKE_INSTALL_PREFIX 指定安装目录;
  • 在代码编译后直接使用 make installcmake --install 进行安装。

CMake install 安装时,安装目标可以包含:二进制、动态库、静态库、文件、目录和脚本等,具体信息可以参考 官网 install 命令说明 ,这里只介绍最常用的几种。

首先在 helloworld 工程目录中添加一个 run.sh 脚本文件,用于运行程序,整个工程目录结构如下

[mayw@localhost helloworld]$ tree .
.
├── build
├── CMakeLists.txt
├── doc
│   └── helloworld.txt
├── README.md
├── run.sh
└── src
    ├── CMakeLists.txt
    └── helloworld.cpp

在最外层的 CMakeLists.txt 最后添加安装代码

# 将 run.sh 拷贝到 bin 目录中
install(PROGRAMS run.sh DESTINATION bin)

# 将 编译的可执行程序拷贝到 bin 目录中
install(PROGRAMS build/bin/helloworld DESTINATION bin)

# 将 README.md 拷贝到 share/doc 中
install(FILES README.md DESTINATION share/doc)

# 将 doc 目录拷贝到 share/doc 中
install(DIRECTORY doc/ DESTINATION share/doc)

注意:这里的 bin 是安装目录中的 bin 目录,于前面 add_subdirectory(src bin) 中的 bin 不是一个概念,它们是两个相互独立的目录。


安装脚本

PROGRAMS :指定目标程序或脚本的安装目录。

DESTINATION :指定安装路径,可以写绝对路径;也可以是相对路径,即 ${CMAKE_INSTALL_PREFIX}/bin 定义的路径。

install(PROGRAMS run.sh DESTINATION bin)

将 run.sh 脚本安装到指定的目录中,一般是 ${CMAKE_INSTALL_PREFIX}/bin 目录。若未指定,则默认安装到 /usr/local/bin 目录中。


安装文件

FILES :指定安装文件,可以同时指定多个文件,用空格分开,如

install(FILES README COPYRIGHT DESTINATION share/doc)

安装目录

DIRECTORY :指定安装目录,可以直接使用所在项目的相对路径,如

install(DIRECTORY doc/ DESTINATION share/doc)

注意:doc 和 doc/ 有很大区别,前者是将 doc 目录安装到目标路径中,后者是将 doc 目录中的所有内容安装到目标路径中。


helloworld 工程实践

编译方法如下

$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/helloworld .. # 手动设置安装目录
$ make
$ make install

编译和安装完成后,会在 /tmp 目录中生成 helloworld 目录,目录结构如下

[mayw@localhost helloworld]$ tree .
.
├── bin
│   ├── helloworld
│   └── run.sh
└── share
    └── doc
        ├── helloworld.txt
        └── README.md

此时运行 bin 目录中的 run.sh 即可运行程序。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值