cmake 教程

cmake 教程


1. 创建CMakeLists.txt

在工程中,需要创建很多的CMakeLists.txt,在运行 cmake 时,cmake会根据这些文件,对我们构建的依赖关系创建makefile。
这里以一个最小的工程为例,来实现cmake编译管理工程。

常用的工程目录结构如下:

[duapple@duapple-pc test]$ tree -N -L 3 -I 'build|bin'
.
├── CMakeLists.txt
├── include
│   └── play.h
├── lib
│   ├── CMakeLists.txt
│   └── mylib
│       ├── CMakeLists.txt
│       ├── mylib.c
│       └── mylib.h
└── src
    ├── CMakeLists.txt
    ├── main.c
    └── play.c

4 directories, 9 files
[duapple@duapple-pc test]$ 

一般将 .c 文件放到src中,.h 文件放到include中,然后lib目录存放我们自己的库。main.c可以放顶层目录,也可以放src中。

这里有两个思路构建CMakeLists.txt。一种是:由于工程比较简单,在顶层目录下编写CMakeLists.txt即可,通过这一个文件来生成makefile。第二种是:在每一个目录下都编写CMakeLists.txt,没一个目录下的文件只负责自己目录下的文件依赖关系。

这里我采用第二种方式。

  • 先主目录编写CMakeLists.txt。
# CMake 最低版本号要求
cmake_minimum_required(VERSION 3.1)

# 项目信息
project(test_project)

# 添加  子目录
add_subdirectory(lib)
add_subdirectory(src)
  • lib中编写CMakeLists.txt。(按理来说这里,应该也是可以跳过这个目录在lib/mylib 中直接编写一个就行了,在顶层路径下指定子目录为lib/mylib)
add_subdirectory(mylib)
  • lib/mylib中编写CMakeLists.txt。
aux_source_directory(. SRC_LIST)

include_directories(../include ../lib/mylib)

add_library(mylib STATIC ${SRC_LIST})
  • src中编写CMakeLists.txt。
aux_source_directory(. SRC_LIST)

# 添加头文件搜索路径
include_directories(../include ../lib/mylib)

add_executable(test ${SRC_LIST})

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 链接库的搜索路径
link_directories("../lib/mylib")

# 添加链接库
target_link_libraries(test m mylib)

至此,CMakeLists.txt文件编写完成,非常的简单明了。如果是在顶层路径下编写一个CMakeLists.txt,那么将更加的简单。cmake的语法是易读的,看一些例子就知道这些语句的作用是什么了。

2. 编译

开始生成makefile。

$ mkdir build & cd build
$ cmake ../

编译。(这里可能会遇到链接先后的顺序的问题,链接顺序不对导致出现函数未定义的情况。将需要的库先链接即可。还有可能出现库的相互依赖问题。暂时没有遇到。)

[duapple@duapple-pc build]$ make 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/duapple/work/cmake/test/build
[ 20%] Building C object lib/mylib/CMakeFiles/mylib.dir/mylib.c.o
[ 40%] Linking C static library libmylib.a
[ 40%] Built target mylib
[ 60%] Building C object src/CMakeFiles/test.dir/main.c.o
[ 80%] Building C object src/CMakeFiles/test.dir/play.c.o
[100%] Linking C executable ../../bin/test
[100%] Built target test

运行。

[duapple@duapple-pc build]$ ../bin/test 
play_1 called.
mylib_1 called.
3^4 = 81.000000

3. 快捷生成

每次都需要自己手动编写CMakeLists.txt,比较麻烦。写一个脚本来快捷生成模板。

  • 编写模板文件gen_cmake.conf.
# 支持的最低版本
cmake_minimum_required(VERSION 3.0)

# 项目名称
project(project_name)

# 可执行文件名称
set(OUT_EXEC "out")

# 源文件目录
aux_source_directory(. SRC_LIST)

# 头文件路径
include_directories(./)

# 添加编译参数
add_compile_options(-Os -g -std=gnu99)

# 设置可执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})

# 链接库的路径
link_directories(./)

# 生成可执行文件
add_executable(${OUT_EXEC} ${SRC_LIST})

# 添加链接库
target_link_libraries(${OUT_EXEC} )

  • 编写生成脚本gen_make.sh
#!/bin/bash

cp /usr/local/sbin/gen_cmake.conf ./CMakeLists.txt
  • 设置权限,并放到可执行系统路径下。
$ sudo chmod 777 gen_cmake.sh
$ sudo chmod 777 gen_cmake.conf
$ sudo chmod +x gen_cmake.sh
$ sudo cp gen_cmake.sh gen_cmake.conf /bin/
$ gen_cmake.sh

效果如下:
请添加图片描述

交叉编译模板 gen_cross_cmake.conf

# 支持的最低版本
cmake_minimum_required(VERSION 3.0)

# 项目名称
project(project_name)

# 可执行文件名称
set(OUT_EXEC "main")

# 指定交叉编译器路径
set(TOOLSCHAIN_PATH "/opt/arm-2014.05/")
set(TOOLCHAIN_HOST "${TOOLSCHAIN_PATH}/bin/arm-none-linux-gnueabi")

# 设置工具链编译器
set(TOOLCHAIN_CC "${TOOLCHAIN_HOST}-gcc")
set(TOOLCHAIN_CXX "${TOOLCHAIN_HOST}-g++")

#告诉cmake是进行交叉编译
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_SYSTEM_NAME "Linux")

# Define the compiler
set(CMAKE_C_COMPILER ${TOOLCHAIN_CC})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_CXX})

# 源文件目录
aux_source_directory(. SRC_LIST)

# 头文件路径
include_directories(./)

# 添加编译参数
add_compile_options(-Os -g -std=gnu99)

# 设置可执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})

# 链接库的路径
link_directories(./)

# 生成可执行文件
add_executable(${OUT_EXEC} ${SRC_LIST})

# 添加链接库
target_link_libraries(${OUT_EXEC} )

posted @   duapple  阅读(22)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示