CMake实质上是用于生成Makefile的工具,现在越来越多开源的项目, 在项目的编译框架上使用CMake替换Makefile. CMake 相对于Makefile规则更加简单,重要的是CMake官方网站提供了较为友好的指南.

CMake 替换Makefile

接下来会以以下三个点来展示CMake 替换Makefile.

  1. 编译目标文件,直接生成可执行程序
  2. .a 或者 .so 库文件编译生成
  3. 链接库文件
1. 直接生成可执行程序

打开Linux下的终端,创建如下目录和文件.

➜  cmake_example tree
.
├── build
└── src
    ├── CMakeLists.txt
    └── hello.c

-> hello.c, 只是简单的一个main函数,然后打印字符串"Hello"

#include <stdio.h>

int main(int argc, char **argv){
    printf("Hello \r\n");
    return 0;                                                   
}

-> src/CMakeLists.txt, 只是设置了项目名称(最终可执行程序的名称),和直接直接编译可执行程序

# set the project name and version
cmake_minimum_required(VERSION 3.10)

#set the project name
project(Hello VERSION 2.0)


#add the executable
add_executable(Hello hello.c)

在完成目录和文件的创建后,我们通过cmake指令进行Makefile的生成和代码工程编译.

在工程的顶层目录,执行cd指令进入build目录,然后运行cmake指令+源码所在目录(也就是CMakeLists.txt的所在目录). 具体过程如下,cmake命令运行成功后在build目录生成了Makefile文件和其它相关文件.

➜  cmake_example cd build 
➜  build ls
➜  build cmake ../src/
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.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/bin/c++
-- Check for working CXX compiler: /usr/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: /home/tracy/Work_Space/Apollo/base_tech/apollo_cmake/basic_start/cmake_example/build
➜  build ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile

在生成Makefile文件后,可以直接在build目录下执行: make或者cmake指令,具体如下,

➜  build cmake --build .
Scanning dependencies of target Hello
[ 50%] Building C object CMakeFiles/Hello.dir/hello.c.o
[100%] Linking C executable Hello
[100%] Built target Hello
➜  build make
[100%] Built target Hello

最后会在build目录下生成,可执行程序Hello.

➜  build make
[100%] Built target Hello
➜  build ls
CMakeCache.txt  cmake_install.cmake  Makefile
CMakeFiles      Hello
➜  build ./Hello 
Hello
2. .so或者 .a 库文件编译生成

打开Linux下的终端,创建如下目录和文件

➜  cmake_example tree
.
├── build
└── src
    ├── CMakeLists.txt
    ├── hello.c
    └── hello.h

hello.c, 库的源文件

#include <stdio.h>

int say_hello(void){
    printf("Hello \r\n");
    return 0;
}

hello.h

#ifndef __HELLO__
#define __HELLO__

int say_hello(void);

#endif

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

#set the project name
project(Hello VERSION 2.0)

# SHARED 为动态库, STATIC为静态库
add_library(hello SHARED 
            hello.c) 

 target_include_directories(hello PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )
                           
在以上文件完成创建后,在工程的顶层目录,执行cd指令进入build目录,然后运行cmake指令+源码所在目录(也就是CMakeLists.txt的所在目录). 具体过程如下,cmake命令运行成功后在build目录生成了Makefile文件和其它相关文件
```bash
➜  build cmake ../src
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.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/bin/c++
-- Check for working CXX compiler: /usr/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: /home/tracy/Work_Space/Apollo/base_tech/apollo_cmake/basic_start/cmake_example/build
➜  build make
Scanning dependencies of target hello
[ 50%] Building C object CMakeFiles/hello.dir/hello.c.o
[100%] Linking C shared library libhello.so
[100%] Built target hello

最后会在build目录下生成,库文件libhello.so

3. 链接库文件

打开Linux下的终端,创建如下目录和文件

➜  cmake_example tree
.
├── build
└── src
    ├── CMakeLists.txt
    ├── hello.c
    ├── hello.h
    └── main.c

main.c, 调用libhello.so 中的say_hello()

#include <stdio.h>
#include "hello.h"

int main(int argc, char **argv){
    say_hello();
    return 0;
}

hello.c, 库的源文件

#include <stdio.h>

int say_hello(void){
    printf("Hello \r\n");
    return 0;
}

hello.h

#ifndef __HELLO__
#define __HELLO__

int say_hello(void);

#endif

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

#set the project name
project(Hello VERSION 2.0)

# add the executable
add_executable(Hello main.c)

add_library(hello SHARED 
            hello.c)

target_link_libraries(Hello PUBLIC hello)

target_include_directories(hello PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

在以上文件完成创建后,在工程的顶层目录,执行cd指令进入build目录,然后运行cmake指令+源码所在目录(也就是CMakeLists.txt的所在目录). 具体过程如下,cmake命令运行成功后在build目录生成了Makefile文件和其它相关文件.

最后在build目录,生成了可执行程序Hello.