CMake
是比make
更为高级跨平台编译工具,它跨平台、开源的构建系统。
介绍
CMake
通过CMakeLists.txt
文件,使用cmake
命令将CMakeLists.txt
转化为makefile
文件,通过make
命令将源码编译为如下之一:
可执行程序(bin)
共享库(so, shared object)
安装
apt install cmake gcc -y
使用
CMake
通常的编译步骤:
mkdir build && cd build
cmake ..
make
说明:
mkdir build
创建编译目录
cmake ..
指向CMakeLists.txt
所在的目录,cmake
会生成很多编译的中间文件以及makefile文件
make
根据生成makefile
文件,编译程序
示例
# 1. 要求的cmake最低版本
cmake_minimum_required(VERSION 3.2)
# 2. 添加c++11标准支持
#set( CMAKE_CXX_FLAGS "-std=c++11" )
# 3. 指定项目的名称,一般和项目的文件夹名称对应
PROJECT(test_sqrt)
# 4. 头文件
INCLUDE_DIRECTORIES(
include
)
# 源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
# 5. 通过设定SRC变量,将源代码路径都给SRC,如果有多个,可以直接在后面继续添加。若不添加编译能够通过,但是执行的时候会出现各种问题,比如 "symbol lookup error xxxxx , undefined symbol"
SET(SRC
${DIR_SRCS}
)
# 6. 编译主函数,生成可执行文件
# 设置路径
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/bin)
# 可执行文件生成
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC})
# 7. 创建共享库/静态库
# 设置路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/lib)
set(LIB_NAME test_sqrt_lib)
# 创建共享库(把工程内的cpp文件都创建成共享库文件,方便通过头文件来调用)
# 这时候只需要cpp,不需要有主函数
# ${PROJECT_NAME}是生成的库名 表示生成的共享库文件就叫做 lib工程名.so
# 也可以专门写cmakelists来编译一个没有主函数的程序来生成共享库,供其它程序使用
# SHARED为生成动态库,STATIC为生成静态库
add_library(${LIB_NAME} STATIC ${SRC})
# 8. 链接库文件
# 把刚刚生成的${PROJECT_NAME}库和所需的其它库链接起来
# 如果需要链接其他的动态库,-l后接去除lib前缀和.so后缀的名称,以链接 libtestsqrt.so 为例,-ltestsqrt
TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
# 容器内编译
$ docker run --rm -it gcc:9.5.0 bash
# 安装依赖
$ sed "s#http://deb.debian.org/debian#https://mirrors.tuna.tsinghua.edu.cn/debian/#g" -i /etc/apt/sources.list
$ apt update
$ apt install cmake -y
# 源码初始化,CMakeLists.txt 参考示例文件
mkdir -p test_sqrt/src/ test_sqrt/include/
cat << EOF > test_sqrt/src/main.c
#include "../include/m.h"
#include <stdio.h>
int main(int argc, char** argv)
{
double a = 81.0;
double b = 0.0;
printf("input a: %f\n", a);
b = cal_sqrt(a);
printf("sqrt result: %f\n",b);
return 0;
}
EOF
cat << EOF > test_sqrt/src/m.c
#include "../include/m.h"
double cal_sqrt(double value)
{
return sqrt(value);
}
EOF
cat << EOF > test_sqrt/include/m.h
#ifndef B_FILE_HEADER_INC
#define B_FIEL_HEADER_INC
#include<math.h>
double cal_sqrt(double value);
#endif
EOF
root@2f5346b34906:/# mkdir build && cd build
root@2f5346b34906:/test_sqrt/build# cmake ..
-- The C compiler identification is GNU 9.5.0
-- The CXX compiler identification is GNU 9.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/local/bin/c++
-- Check for working CXX compiler: /usr/local/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /test_sqrt/build
root@2f5346b34906:/test_sqrt/build# make
Scanning dependencies of target test_sqrt
[ 16%] Building C object CMakeFiles/test_sqrt.dir/src/m.c.o
[ 33%] Building C object CMakeFiles/test_sqrt.dir/src/main.c.o
[ 50%] Linking C executable bin/test_sqrt
[ 50%] Built target test_sqrt
Scanning dependencies of target test_sqrt_lib
[ 66%] Building C object CMakeFiles/test_sqrt_lib.dir/src/m.c.o
[ 83%] Building C object CMakeFiles/test_sqrt_lib.dir/src/main.c.o
[100%] Linking C static library libtest_sqrt_lib.a
[100%] Built target test_sqrt_lib
# 二进制
root@2f5346b34906:/test_sqrt/build# bin/test_sqrt
input a: 81.000000
sqrt result: 9.000000