1.CMake编译原理
CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多。CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序或共享库(so(shared object))。因此CMake的编译基本就两个步骤:
1. cmake
2. make
cmake 指向CMakeLists.txt所在的目录,例如cmake .. 表示CMakeLists.txt在当前目录的上一级目录。cmake后会生成很多编译的中间文件以及makefile文件,所以一般建议新建一个新的目录,专门用来编译,例如
mkdir build
cd build
cmake ..
make
make根据生成makefile文件,编译程序。
2.使用Cmake编译程序
我们编写一个C++程序,以此理解整个CMake编译的过程。
a.准备程序文件
文件目录结构如下:
. ├── build ├── CMakeLists.txt └── mars ├── util.cc └── util.h └── main.cc
头文件util.h,如下所示,用到curl、jsoncpp、glog、protobuf等库(util.cc略):
#pragma once
#include <iostream>
#include <curl/curl.h>
#include <json/json.h>
#include <fcntl.h>
#include <glog/logging.h>
#include <google/protobuf/text_format.h>
namespace mars {
namespace util {
...
}
}
main.cc主函数,如下所示:
#include "mars/util.h"
#include <stdio.h>
#include <stdlib.h>
using namespace std;
using namespace mars::util;
int main(int argc, char* argv[]) {
...
return 0;
}
b.编写CMakeLists.txt
接下来编写CMakeLists.txt文件,放哪里都可以,只要里面编写的路径能够正确指向就好了。CMakeLists.txt文件,如下所示:
# cmake verson
cmake_minimum_required(VERSION 3.10.2)
# set the project name and version
project(mars VERSION 1.0)
# head file path
find_package(Threads)
include_directories(/usr/local/include)
#include_directories(/usr/local/opt/curl/include/)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
# add executable file
add_executable( main
main.cc
mars/util.cc
)
# add link library
#link_directories(/usr/local/lib)
target_link_libraries( main
curl
/usr/local/lib/libjsoncpp_static.a
/usr/local/lib/libglog.a
/usr/local/lib/libgflags.a
/usr/local/lib/libprotobuf.a
${CMAKE_THREAD_LIBS_INIT}
)
c.编译和运行程序
准备好了以上的所有材料,接下来,就可以编译了,由于编译中出现许多中间的文件,因此最好新建一个独立的目录build,在该目录下进行编译,编译步骤如下所示:
# 纯cmake方式编译
cmake -H. -Bbuild -G "Unix Makefiles" #指定编译参数和目录
cmake --build build
# make方式编译
mkdir build && cd build #新建build目录用于编译
cmake ../ #..是为了找到CMakeLists.txt文件
make
# g++方式编译
g++ main.cc mars/util.cc -std=c++11 -Wall -L/usr/local/lib -lcurl -ljsoncpp -lglog -lgflags -pthread -lprotobuf -o build/main
# 运行
./build/main