简介
最近在做一个比较大的工程,但是之前没有大工程的构建和整理经验,所以现在学一下 CMake 并留一些记录。因为今天感觉这个笔记还不错,所以先整理了发出来,剩下的等之后整理了会陆续出来。
工程准备
- 先新建一个目录,用于专门构建动态库
$ mkdir lib_shared
mkdir: created directory 'lib_shared'
- 然后建立相关的目录和文件:
$ mkdir src lib inc build bin
mkdir: created directory 'src'
mkdir: created directory 'lib'
mkdir: created directory 'inc'
mkdir: created directory 'build'
mkdir: created directory 'bin'
$ touch readme.txt CPOYRIGHT
现在的目录结构如下:
$ tree -L 1 .
.
├── CMakeLists.txt
├── CPOYRIGHT
├── bin
├── build
├── inc
├── lib
├── lib_shared
├── readme.txt
└── src
编写源文件和头文件
在 lib 目录下面编写动态库需要的头文件和源文件(这里以一个print
为例):
源文件: hello_world.c
/**
* @file hello_world.c
* @author Pumpkin Rice
* @brief
* @version 0.1
* @date 2021-07-30
*
* @copyright Copyright (c) 2021
*
*/
#include "hello_world.h"
/**
* @brief
*
* @param buff
*/
void print_hello(char *buff)
{
printf("%s", buff);
}
头文件: hello_world.h
/**
* @file hello_world.h
* @author Pumpkin Rice
* @brief
* @version 0.1
* @date 2021-07-30
*
* @copyright Copyright (c) 2021
*
*/
#ifndef _HELLO_WORLD_H
#define _HELLO_WORLD_H
#include <stdio.h>
void print_hello(char *);
#endif
编写CMakeLists.txt 文件
然后编写两个 CMakeLists.txt
文件(CSDN 的MD好像没有支持CMake语言,所以将就看吧)
第一个是 lib 目录下面的,它的作用就是指定编译的动态库文件:
SET(LIB_HELLO_SRC hello_world.c)
# 添加动态库输出
ADD_LIBRARY(hello SHARED ${LIB_HELLO_SRC})
第二个是 顶级 CMakeLists.txt
文件,在 lib_shared 目录下:
CMAKE_MINIMUM_REQUIRED (VERSION 3.0)
PROJECT(HELLOLIB)
# 设置库输出目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 设置可执行文件输出目录
# SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 添加库源文件子目录
ADD_SUBDIRECTORY(lib)
构建和编译
进入build目录执行以下命令:
dark @ Eureka in ~/.../lib_shared/build |16:39:48
$ cmake ..
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.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/dark/Workspace/lib_static/build
dark @ Eureka in ~/.../lib_shared/build |16:39:52
$ make
Scanning dependencies of target hello
[ 50%] Building C object lib/CMakeFiles/hello.dir/hello_world.c.o
[100%] Linking C shared library ../../lib/libhello.so
[100%] Built target hello
之后就能在lib目录下面看到编译好的动态库文件了。
动态库验证
如果需要验证动态库的正确性,可以编写一个 hello.c
文件来调用库里面的函数
/**
* @file hello.c
* @author Pumpkin
* @brief
* @version 0.1
* @date 2021-07-30
*
* @copyright Copyright (c) 2021
*
*/
#include "hello_world.h"
int main(int argc, char *argv[]){
int i = 0;
while (++i < argc) {
print_hello(argv[i]);
}
printf("\n\r");
return 0;
}
然后需要修改一下顶级目录下的CMakeLists.txt
文件,用来构建编译验证动态库的可执行文件:
CMAKE_MINIMUM_REQUIRED (VERSION 3.0)
PROJECT(HELLOLIB)
# 设置库输出目录 语法:SET(LIBRARY_OUTPUT_PATH [path])
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) # 也可以在 lib 目录下进行设置
# 设置可执行文件输出目录 语法:SET(EXECUTABLE_OUTPUT_PATH [path])
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
ADD_SUBDIRECTORY(lib)
# 添加头文件目录
include_directories(${PROJECT_SOURCE_DIR}/lib)
# 添加链接库目录
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 添加需要链接的库
link_libraries(hello)
# 生成可执行文件
add_executable(print ${PROJECT_SOURCE_DIR}/src/hello.c)
之后就可以在 bin 目录下找到编译好的可执行文件了:
dark @ Eureka in ~/.../lib_shared/build |16:39:54
$ ../bin/print hello world!
helloworld!
参考资料
CMake 教程:知乎 (zhihu.com):https://zhuanlan.zhihu.com/p/119426899
Cmake 实践: cmake实践 · 看云 kancloud.cn:https://www.kancloud.cn/itfanr/cmake-practice/82983