CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,无需修改,非常方便。本文的目的主要是入门CMake并不会涉及复杂的CMake的使用,第二个目的就是用来复习的
1.安装CMake,在Centons当中我们可以使用sudo yum install cmake
sudo yum install cmake
安装完成之后我们可以使用cmake --version命令查看我们当前cmake的版本信息
下面我们来演示一下CMake的简单使用,先从最简单的看起一起来感受一下CMake的使用吧,下面我们来编写一个main.cc
#include
using namespace std;
int main()
{
cout<<"hello word"<<endl;
return 0;
}
然后了我们在main.cc相同的目录下创建一个CMakeLists.txt文件,编写的内容如下:
cmake_minimum_required(VERSION 2.8)
project(demo)
add_executable(main main.cc)
解释:
下面我们在终端上输入cmake . 会有如下信息出来:
此时我们可以看到目录下有一个Makefile文件,还有一些cmake允许之后产生的文件,此时我们在在终端上输入make:
我们发现整个目录下生成了main这个可执行文件了,我们可以运行他了:
我们看此时运行成功,如果我们看到了运行的结果。此时我们发现当我们使用cmake之后会产生很多的文件这些文件在一定程度上影响了我们的源文件因此我们可以在当前目录创建一个build目录:
我们进入到build这个目录当中来然后再输入cmake … :
此时我们发现之前生成的一堆文件现在就来到了build这个目录下来了,此时不会影响我们的源文件所在的目录。
在这里很多老铁可能就要说了要这么麻烦吗直接g++一行不就行了,下面我们来看一下比较复杂的目录结果此时cmake就比g++要舒服的多了
对应add.h当中的代码:
#pragma once
int add(int a,int b);
对应add.c代码:
int add(int a,int b){
return a+b;
}
对应main.cc代码:
#include
#include"add.h"
using namespace std;
int main()
{
cout<<add(10,20)<<endl;
}
下面我们来看看此时这个CMakeLists.txt改如何书写
cmake_minimum_required(VERSION 2.8)
project(demo)
include_directories(./include)
set(SRC_LIST ./src/add.cc ./src/main.cc)
add_executable(main ${SRC_LIST})
下面解释一下上面的书写:
下面我们进入到build目的当中输入cmake …
发现运行成功当然我们也可以在main.cc当中指定add.h这个头文件在哪里.在上面如果源文件有100多个这要敲到猴年马月此时我们就可以使用aux_source_directory(dir var)。第一个参数代表的是目录,第二个参数var是用来存放源文件列表的。此时我们也可以将上面的CMakeLists.txt改为:
cmake_minimum_required(VERSION 2.8)
project(demo)
include_directories(./include)
aux_source_directory(./src SRC_LIST)
add_executable(main ${SRC_LIST})
但是aux_source_directory()也是有弊端的,他会将指定目录下所有的源文件都加入进来,如果在一个目录下有一些源文件我们不想加入进来此时aux_source_directory就不太合适了。此时我们用set定义变量指定特定的源文件即可.
一般的话我们不会这么干,一般我们会将可执行文件放到一个bin目录下,这样会让结构更加的清晰下面我们在把目录结构调整一下:
这时候我们需要修改一下最外层的CMakeLists.txt.内容如下:
cmake_minimum_required(VERSION 2.8)
project(demo)
add_subdirectory(./src)
在这里出现了一个新的命令add_subdirectory(),这个命令可以向当前工程添加存放源文件的子目录,并且可以指定中间二进制和目标二进制存放的位置。在这里指定的src目录下存放了源文件,当cmake执行到这里的时候,会进入src目录下去找CMakeLists.txt.所有我们需要在src目录下建立一个CMakeLists.txt。内容如下:
cmake_minimum_required(VERSION 2.8)
aux_source_directory(./ SRCLIST) #把当前目录下的源文件加载进来
include_directories(../include) #指定头文件
add_executable(main ${SRCLIST})
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
在这里使用set来定义变量。EXECUTABLE_OUTPUT_PATH和PROJEXT_SOURCE_DIR是CMake自带的预定义变量和PROJEXT_SOURCE_DIR变量相对应的还有一个叫做PROJECT_BINARY_DIR.
下面我们来解释一下:
1.EXECUTABLE_OUTPUT_PATH:目标二进制可执行文件存放的位置
2.PROJECT_SOURCE_DIR:代表的工程的路径
3.PROJECT_BINARY_DIR:代表编译的是编译的路径
在这里使用set的意思是将生成的可执行程序放到工程所在路径的bin目录下,下面我们进入build目录在终端上输入cmake …
运行是ok的下我们我们进入到上级目录的bin目录下
之前博主写过利用makefile制作动静态库在这里使用CMake来演示一下生成动静态库相比makefile真的好用多了,下面我们来调整一下啊目录结构
下面我们调整一下最外层的CMakeLists.txt,其内容如下:
cmake_minimum_required(VERSION 2.8)
project(demo)
add_subdirectory(add)
下面我们一起来看看add目录下的CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
aux_source_directory(./ SRC_LIST)
add_library(add_shared SHARED ${SRC_LIST})
add_library(add_static STATIC ${SRC_LIST})
set_target_properties(add_shared PROPERTIES OUTPUT_NAME "add")
set_target_properties(add_static PROPERTIES OUTPUT_NAME "add")
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
在这里我们解释一下一些新的命令和遇定变量:
1.add_library:
2.set_target_properties
这个是用来设置输出名称还有设置库的版本号等
3.LIBARARY_OUT_PATH:库文件默认的输出路径,这里设置为工程目录下的lib目录下
下面我们进入到build目录下cmake …然后在make在进入到lib当中
注意:我们在前面使用了set_target_properties重新设定了库文件的名字。其实也可以不使用那么库的名字就是add_library里面定义的名字但是动态库和静态库的名字不能相同。此时我们可以使用set_target_properties把名字设置为相同,只是后缀不同而已这样相对起来好看一些
总结:
上面我们以及生成好了动态库和静态库下面我们来看如何使用他们,首先我们将build文件当中的所有文件都区别删掉。下面我们需要修改一下目录结构:
src目录下main.cc的内容如下:
#include
using namespace std;
#include"add.h"
int main()
{
cout<<add(10,20);
return 0;
}
修改当前工程目录下的CMakeLists.txt如下:
cmake_minimum_required(VERSION 2.8)
project(demo)
add_subdirectory(src)
src目录下CMakeLists.txt如下:
aux_source_directory(. SRC_LIST)
include_directories(../add)
link_directories(${PROJECT_SOURCE_DIR}/lib)
add_executable(main ${SRC_LIST})
target_link_libraries(main add.so)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
在这里又出现了2个新的命令link_directories和target_link_libraries,下面来解释一下:
1.link_directories:添加非标准共享库的搜索路径
target_link_libraries:一个库当中可能有多个动太库你要告诉它你要链接的是那个
然后我们在回到build目录下在终端上敲上cmake … 然后再进入到bin目录下:
在lib目录下有两个库一个是动态库一个是静态库如果我们不指明后缀默认链接的是动态库,如果lib目录下只有静态库就只会去链接静态库。
扩展:有时候了我们希望在编译代码的时候想要添加一些编译选项,如:-std=c++11,-Wall等等
我们此时就可以使用add_compile_options来进行操作。由于这个比较简单在这里就不做演示了。
以上就是我学习CMake的一些记录,举的列子都比较的简单旨在帮助大家快速入门CMake,同时也是问了自己后面复习使用。CMake的知识比较的多更多的可以去官网学习或者在一个完善的项目当中学习,CMake可以不用让我们去编写复杂的Makefile并且是跨平台的是一个非常强大的工具。如果有错误的话请各位老铁指正谢谢阅读