CMake使用

文|Seraph

01 | CMake简介

makefile通常依赖于当前的编译平台,编写makefile的工作量很大,解决依赖关系时也容易出错。
CMake是makefile的构建工具,可以生产可移植的makefile。
使用CMake可以减少手写makefile的工作量。

02 | CMake安装

  1. CMake官网下载最新版。如下载很慢,可以使用链接https://cmake.org/files/
  2. 安装跟普通程序一致,我这里使用的Mac。
  3. 安装好后,还需要配置环境变量,使Teminal能直接使用。
    打开Tools->How to Install For Command Line Use菜单,弹出的对话框告诉我们怎么配置。
    How to Install For Command Line Use
    这里显示三种方法:
    第一种:临时给PATH添加环境变量,但是重新打开Teminal后,会失效。
    第二种:在/usr/local/bin建立相应的命令链接,而/usr/local/bin存在于系统环境变量中,所以Teminal也就能直接使用。
    第三种:指定一个安装目录,建立相应的命令链接。
    如上所示,我们这里使用第二种即可。
  4. 使用cmake --version查询是否配置好cmake的环境变量以及cmake的版本。

03 | CMake的“Hello World”示例

  1. 新建一个Hello目录,并在目录下添加main.cpp,文件内容如下:
#include <iostream>
using namespace std;
int main()
{
	cout<<"Hello World"<<endl;
	return 0;
}
  1. 再添加一个CMakeLists.txt文件,内容如下:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0) #表示需要CMake最小版本
PROJECT(HELLO) #项目名称
AUX_SOURCE_DIRECTORY(. SRC_LIST) #把当前目录下所有源代码文件名加入变量SRC_LIST
ADD_EXECUTABLE(hello ${SRC_LIST}) #生成应用程序 hello 
  1. hello目录下新建一个build目录,然后使用CMake界面程序配置源码路径和生成二进制路径,然后点击Configure即可。Configure
    所有编译结果文件都会输出至build文件夹下,不会源文件混淆,容易管理。
  2. 使用Teminal进入build目录,然后分别输出cmake ..make。最后运行./hello文件,即能输出Hello World。(这里cmake ..等同于3的界面操作)
    在这里插入图片描述
    如果源码编写错误,则重新使用Vim编写源码,然后直接再次运行make即可,不同重复前面的步骤。

04 | 链接库的依赖处理

  1. hello目录下,新建一个print目录,并在print目录下添加print.hprint.cpp,文件内容如下:
  • print.h文件
#ifndef __HELLO_H__
#define __HELLO_H__
#include <iostream>
using namespace std;
void print();
#endif
  • print.cpp文件
#include "print.h"
void print()
{
    cout<<"Hello World!!!!!"<<endl;
}
  1. 修改main.cpp,如下:
#include "print/print.h"
int main()
{
	print();//调用print中的print函数
	return 0;
}
  1. 修改hello目录下的CMakelists.txt如下:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
PROJECT(HELLO) #项目名称
ADD_SUBDIRECTORY(print)  #添加子目录
AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(hello ${SRC_LIST})
TARGET_LINK_LIBRARIES(hello Print) #链接的库
  1. print目录下也要添加一个CMakelists.txt,如下:
AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)
ADD_LIBRARY ( Print ${DIR_TEST1_SRCS}) #这里的Print与上个文件里链接的库一致

当使用ADD_SUBDIRECTORY添加一个子目录时,Configure会去寻找该目录下的CMakelists.txt,如果我们这里把它删了,就会报错。

  1. 重新cmake ..make以后,就能生成新的hello执行文件了。 hello

05 | CMake调用其它的库(以OpenCV库为例)

  1. 首先安装OpenCV库
  2. 新建一个openimage的工程目录,在openimage下新建binbuildsrc目录。并新建CMakelists.txt文件如下:
PROJECT(openimage)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${openimage_SOURCE_DIR}/bin) #设置运行输出文件目录

find_package(OpenCV REQUIRED)  #查找OpenCV库
include_directories(${OpenCV_INCLUDE_DIRS}) #包括头文件,这里的值,是通过上一条find_package找到的
add_executable(openimage src/openimage.cpp) #执行文件
link_directories(${OpenCV_LIBRARY_DIRS})  #包含库
target_link_libraries(openimage ${OpenCV_LIBS}) #链接库
  1. src目录下新建openimage.cpp文件,内容如下:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
	Mat img = imread("1.png");
	imshow("Viewer", img);
	waitKey(0);
	return 0;
}
  1. binbuild目录下加入1.png图片文件。
  2. 然后进入build目录下进行如前面介绍的一样进行cmake ..make
    cmake
    最后执行输出文件,便能调用OpenCV打开图片。(注意我们代码里面写的是相对路径,所以当我们执行文件时,是在命令执行目录下面寻找图片文件,而不是执行文件openimage目录下)
    输出图片

06 | 生成debug版和release版执行程序

  1. C++之所以会生成不同版本的程序,是因为g++的参数不一样,-O3表示优化程度调到最高,-O0表示优化程度调到最低,-g -ggdb表示添加调试信息。
  2. CMake中有一个变量CMAKE_BUILD_TPYE,当其取值为Debug时,会使用CMAKE_CXX_FLAGS_DEBUG选项生成makefile;当其取值为Release时,会使用CMAKE_CXX_FLAGS_RELEASE选项来生成makefile。
  3. 我们可以通过给如上两个选项赋相应的值来设置Debug编译和Release编译。我们这里继续采用hello项目继续试验,修改CMakeLists.txt如下:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
PROJECT(HELLO) #项目名称
ADD_SUBDIRECTORY(print)
AUX_SOURCE_DIRECTORY(. SRC_LIST)
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
ADD_EXECUTABLE(hello ${SRC_LIST})
TARGET_LINK_LIBRARIES(hello Print)

  1. 进入build目录,使用ccmake ..进行configuregenerate。在执行之前,修改CMAKE_BUILD_TPYE的值为DebugRelease,便能生成对应的程序版本。
    ccmake
    具体快捷键操作,键ccmake下端提示。因为hello程序很小,所以看不出来debug版本release版有什么区别。

07 | 《cmake实践》总结

推荐去看《cmake实践》这篇文章,大概50页,入门很详细,解析很清楚。

  1. make -VERBOSE=1可显示详细构建过程。
  2. make clean清理构建工程。
  3. 为了文件不混淆,一般使用外部编译。
  4. ADD_LIBRARY不能同时生成同名的目标文件(动态库、静态库),需要使用SET_TARGET_PROPERTIES修改输出名。
文章的一些错误和注意事项:
  • P6页中CMakeLists.txt内容的最后一样应为:
    ADD_EXECUTABLE(hello ${SRC_LIST})
    这里需要用${}的形式获取源文件列表。
  • P19页中未给执行程序hello添加安装信息。正确的做法是在src目录下的CMakeLists.txt文件末尾添加如下代码:
INSTALL(TARGETS hello RUNTIME DESTINATION bin)

不要添加到工程根目录下的CMakeLists.txt中,因为hello编译是由src下的CMakeLists.txt执行的。

  • P25页的make install在mac下,如果加sudo还是执行安装失败。可能是mac处于某种保护机制,需要重启进入恢复模式,关闭该保护机制。见《MAC使用》中问题解决的第1个问题。
  • P27页缺少LINK_DIRECTORIES(/usr/lib),但是我加上了也依然连接不上。查了下,新版不推荐使用LINK_DIRECTORIES,可以使用FIND_LIBRARY代替。所有将src下的CMakeLists.txt文件内容修改为:
ADD_EXECUTABLE(main main.c)
INCLUDE_DIRECTORIES(/usr/include/hello)
FIND_LIBRARY(LIBHELLO_PATH hello /usr/lib)
IF(NOT LIBHELLO_PATH)
MESSAGE(FATAL_ERROR "libhello not found")
ENDIF(NOT LIBHELLO_PATH)
TARGET_LINK_LIBRARIES(main ${LIBHELLO_PATH})

问题解决:
CMake Error at CMakeLists.txt:7 (add_executable):
The target name “test” is reserved or not valid for certain CMake features, such as generator expressions, and may result in undefined behavior.

  1. cmake保留test,将工程名修改为其它即可。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值