好久,好久,好久,好久。。。。。没有更新了。因为哥忙。。。。忙着划水。。。。
今天来说一下 CMake 的用法。以前写别的语言的同学刚开始写 Cpp 的时候,都会很疑惑,一会儿 Make ,一会儿 CMake ,一会儿还 QMake,到底这些 Make 是干啥的?其实这个问题是很简单的,我们写程序的时候往往会写出来很多源代码文件,有时候也会使用或者生成一堆库。这就需要有一种将这些源文件之前的关系和编译规则描述给编译器和链接器的工具,这就是这一堆 Make 要做的事情。
先说说 Make 吧。我先去找个 Make 的配图。。。。。。找了半天没找到。。。。
make 可以是读入一个名为 makefile 的文件,然后执行这个文件中指定的指令。在这个 makefile 文件里,你可以指定你的编译器啊,描述你源文件之间剪不断理还乱的联系。。。还有你要链接的库,也要写进来。甚至你最后生成的产物的安装路径,也要弄进来。
这下你就大概知道 make 是干啥的了吧,但是 make 有个很严重的问题,这玩意跨平台能力几乎没有,一些 Linux 的平台上面还好。但是你要同一段程序拿到 Mac 上,Windows 上,那简直要重写 make。而且 windows 上使用 make 还要安装一堆莫名其妙的玩意。灰常蓝瘦。
于是乎,就有好多作用和 make 差不多,或者是相同的东西,就像雨后的狗尿苔一样,沿着墙角就呲出来了。(我这么一说,你那么一听,拿这个骂我就不好了)
其中目前来说被大家广泛认同的狗尿苔是 CMake。我再找个CMake的图去。。。
图来了
CMake是通过读取一个CMakeLists.txt的文件,依照文件内容,将你的工程转换到各个平台的东西。例如,在Linux平台,他可以转换成make,在Mac平台,他可以转换成Xcode工程,在Windows平台,他可以转换成Vs的工程。这样你在写完这个工程后,原则上不需要进行修改,就可以再各个平台上进行编译。
好了,我现在可以用一个例子与大家分享一下。我是怎么使用CMake的。
第一,是建立一个文件夹。这个文件夹就是放你工程的源文件的。
mkdir HST
这样我们就有了一个工程,我一般是这样去做的:将项目按照功能模块做成几个子工程,有的工程最后生成可执行的文件,有的工程最后生成静态库或者动态库,让别的子工程对其依赖。这样我们就可以把各个模块有效得分开,方便管理。值得注意得是,子工程之间千万不要互相引用,这样就很难解耦了。
我们得样例工程是这样设计的。我们做两个子工程,一个工程是最后生成的可执行程序,里面含有一个main.cpp的文件,这个文件里又一个main方法,是程序的入口。这个工程,我们称之为 HSTMain。另一个工程将生成一个静态库,这个静态库将被 HSTMain 引用,提供一个简单的功能,我们称之为 ALib
首先,我们先把工程的源代码准备好。我们再HST文件夹下面建立两个文件夹,一个叫做 HSTMain,一个叫做 ALib 。
HSTMain的文件夹下面,我们新建一个文件,叫做 main.cpp,代码如下
#include
可以看到,我们在 main.cpp 里面使用了一个 ALib 的类。下面我们看一下 ALib 的代码。
在 ALib文件夹下面创建一个 ALib.h 和一个 ALib.cpp。
ALib.h 的文件内容如下:
#ifndef A_LIB__H
#define A_LIB_H
class ALib
{
public:
ALib();
~ALib();
int add(int a,int b);
};
#endif
ALib.cpp 的文件内容如下
#include "ALib.h"
ALib::ALib()
{
}
ALib::~ALib()
{
}
int ALib::add(int a,int b)
{
return a + b;
}
很简单吧。。。。。
接下来,我们来使用 CMake 构建整个工程
首先我们在 HST 下面创建一个 CMakeLists.txt 文件,这是我们的总工程的构建文件,CMake将会从这个文件读起。文件内容如下
PROJECT
可以看到,我们头两行制定了工程的名称和 CMake 的最低支持的版本。后面两个 ADD_SUBDIRECTORY 是把两个子工程包含了进来,这样 Cmake 会去 ALib 和 HSTMain 文件夹里面去找子模块的信息,然后构建项目。
总工程看完了,我们再来看一下两个子模块怎么写
首先在 ALib 文件夹下面创建一个 CMakeLists.txt 文件,这是 ALib 子工程的构建文件,文件内容如下
add_library(
ALib
ALib.cpp
)
add_library 表示我们将生成一个库,库的名字叫做 ALib ,包含的源文件有 ALib.cpp,这样,CMake会把 ALib.cpp 编译成 ALib.a 的静态库
接下来,在 HSTMain 文件夹下面建立一个 CMakeLists.txt 文件,我们看一下这个文件的内容
include_directories (../)
add_executable(
HSTMain
main.cpp
)
target_link_libraries(HSTMain ALib)
可以看到,我们有一个 add_executable ,与 add_library 不同的是,add_executable 会生成一个可执行的程序。CMake 会把 main.cpp 编译成 HSTMain,而在这同时,我们通过target_link_libraries(HSTMain ALib) 将刚刚我们的 ALib 库链接给了 HSTMain,这样 ALib 里的内容我们就可以使用了,也就是说, HSTMain 依赖了 ALib。include_directories (../) 是设置了一个头文件的搜索路径,编译器会到你设置的路径下去搜索的你程序里写的头文件。这个设置可以帮助你方便得设置头文件地址,而不用在代码里写很长的头文件目录。
最后的文件目录如下
接下来,我们就可以去编译了。
在 HST 同级别上,建立一个文件夹 HSTBuild,Cmake 生成的中间文件,以及最后的产物,都会在这个文件夹里面
cd HSTBuild
cmake ../HST
make
cd HSTMain
./HSTMain
么么哒,这样就成功了哦。
我一篇给大家说说怎么链接 FFmpeg 之类的第三方库吧,顺便说说 FFmpeg 的编译。