make、makefile、cmake、kconfig是怎么做工程管理的?

文章目录

  • 要解决的问题
  • makefile和make
  • cmake
  • kconfig
  • 如何查看编译了哪些文件?
  • 如何增加驱动?
    • 将相关驱动加到现有文件夹中
    • 建立单独文件夹
  • 其他构建系统
  • 工程样例
  • 相关链接

要解决的问题

大型工程项目

  • make、makefile、cmake、kconfig都是干什么的,他们之间什么关系
  • 如何查看编译了哪些文件?
  • 如何增加驱动?

大型工程一般使用make构建的,了解了相关原理就能解决上述问题。
本文用的工程样例是:https://github.com/sipeed/MaixPy.git

makefile和make

一个工程中的源码文件不计其数,需要有一系列的规则说明:

  • 需要编译哪些文件,如何编译指定编译顺序。哪些文件先编译、哪些文件后编译、哪些文件需要重新编译。
  • 需要创建哪些库文件以及如何创建这些库文件
  • 如何最后产生我们想要的可执行文件

把这些规则写到一个文件里,就是Makefile。
make是一个命令工具,用于解释Makefile中的指令。
尝试写一个hellloworld的程序

#include
int main(){
     printf("hello 峡谷金城武\n");
     return 0;
} 

当我们想对这个hello.c生成可执行文件,通常采用

gcc hello.c -o hello

我们采用Makefile来编写这段代码,新建文件Makefile:

hello:hello.c
        gcc hello.c -o hello

使用make指令运行makefile,我们可以看到如下效果
make

cmake

大型工程的makefile文件非常复杂,一般人根本搞不懂,也不会写。有没有简单的方法来生成目标文件呢?
当然有。
如果说make-makefile是一个工程构建系统,cmake就是生成这个构建系统的系统。他可以生成各种IDE的工程文件或解决方案和makefile。
cmake通过读取脚本文件——CMakeLists.txt 中的规则来构建编译系统
举例说明:
生成可运行文件,打印HelloWorld

  • 1.使用cmake构建系统生成makefile
  • 2.使用make生成目标文件
  • 3.最后运行目标文件

1.准备源文件
在这里插入图片描述
main.cpp:

//main.cpp
#include 
int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.9)
project(HelloWorld)
set(CMAKE_CXX_STANDARD 11)
add_executable(HelloWorld main.cpp)

2.执行cmake:

(base) andrew@myg-pc:~/src/learncmake$ ls
CMakeLists.txt  main.cpp
(base) andrew@myg-pc:~/src/learncmake$ mkdir build
(base) andrew@myg-pc:~/src/learncmake$ cd build/
(base) andrew@myg-pc:~/src/learncmake/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.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/andrew/src/learncmake/build
(base) andrew@myg-pc:~/src/learncmake/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
(base) andrew@myg-pc:~/src/learncmake/build$ cd ..
(base) andrew@myg-pc:~/src/learncmake$ ls
build  CMakeLists.txt  main.cpp
(base) andrew@myg-pc:~/src/learncmake$ 

cmake之后文件,可以看到build文件夹下自动生成很多makefile相关文件
make、makefile、cmake、kconfig是怎么做工程管理的?_第1张图片
3.执行make,生成目标文件

(base) andrew@myg-pc:~/src/learncmake/build$ make
Scanning dependencies of target HelloWorld
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/main.cpp.o
[100%] Linking CXX executable HelloWorld
[100%] Built target HelloWorld
(base) andrew@myg-pc:~/src/learncmake/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  HelloWorld  Makefile

可见生成了HelloWorld
make、makefile、cmake、kconfig是怎么做工程管理的?_第2张图片
4.运行HelloWorld

(base) andrew@myg-pc:~/src/learncmake/build$ ./HelloWorld 
Hello, World!
(base) andrew@myg-pc:~/src/learncmake/build$ 

cmake除了生成编译规则,还有其他功能:

  • 生成安装规则
# 指定 MathFunctions 库的安装路径
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

通过上面的定制,生成的 Demo 文件和 MathFunctions 函数库 libMathFunctions.o 文件将会被复制到 /usr/local/bin 中,而 MathFunctions.h 和生成的 config.h 文件则会被复制到 /usr/local/include 中。

  • 为工程添加测试
    添加测试同样很简单。CMake 提供了一个称为 CTest 的测试工具。我们要做的只是在项目根目录的 CMakeLists 文件中调用一系列的 add_test 命令。
  • 支持 gdb调试
    让 CMake 支持 gdb 的设置也很容易,只需要指定 Debug 模式下开启 -g 选项:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
  • 添加环境检查
  • 添加版本号
  • 生成安装包
    cmake提供Cpack打包工具,可以配置生成各平台的安装包,包括二进制安装包和源码安装包。
  • 将其他平台的项目迁移到 CMake

kconfig

了解了cmake,基本上能用比较简单的方式组织源文件结构了。
系统稍微复杂,又会出现新问题,举个例子:
一套代码有很多模块,lcd、触摸屏、摄像头、SPI、I2C、UART等。其中摄像头模块依赖I2C模块。
这套代码可以运行在N个单板,A单板没有摄像头,不需要编译摄像头模组;B单板需要编译全部模块。
如何灵活配置编译单元?
编译过linux就会知道,make menuconfig可以很方便选择编译单元并且配置相关参数。
make menuconfig使用的就是kconfig
kconfig用来做系统配置,生成配置文件:

  • 供cmake使用:CMakeList会使用这些参数
  • 用于编译源码

make menuconfig生成的配置文件有:

  • *.cmake:cmake文件,里面是一些set指令,给变量赋值。
  • *.mk:make的配置文件,里面是一些编译变量
  • *.h:可在make或make之前的menuconfig时生成

举例说明:
https://github.com/sipeed/MaixPy.git
make、makefile、cmake、kconfig是怎么做工程管理的?_第3张图片
MaixPy/Kconfig:

mainmenu "C/CPP CMake project framework Kconfig configuration"

menu "Toolchain configuration"
	config TOOLCHAIN_PATH
		string "toolchain path"
		default ""
	
	config TOOLCHAIN_PREFIX
		string "toolchain prefix"
		default ""
endmenu

menu "Components configuration"
	osource "${SDK_PATH}/components/*/Kconfig"
	osource "${PROJECT_PATH}/*/Kconfig"
endmenu

make、makefile、cmake、kconfig是怎么做工程管理的?_第4张图片make、makefile、cmake、kconfig是怎么做工程管理的?_第5张图片工程提供了默认makefile配置文件:MaixPy/projects/maixpy_k210_minimum/config_defaults.mk 。里面是一些默认配置,make menuconfig读取这个文件生成默认菜单选项。

# Toolchain configuration
#
CONFIG_TOOLCHAIN_PATH="/opt/kendryte-toolchain/bin"
CONFIG_TOOLCHAIN_PREFIX="riscv64-unknown-elf-"
# end of Toolchain configuration
# Board config
CONFIG_BOARD_MAIX=y
# CONFIG_BOARD_M5STICK is not set
CONFIG_LCD_DEFAULT_WIDTH=320
CONFIG_LCD_DEFAULT_HEIGHT=240
CONFIG_LCD_DEFAULT_FREQ=15000000
CONFIG_SENSOR_FREQ=24000000

*.cmake:cmake文件,里面是一些set指令,给变量赋值。

set(CONFIG_TOOLCHAIN_PATH "/opt/kendryte-toolchain/bin")
set(CONFIG_TOOLCHAIN_PREFIX "riscv64-unknown-elf-")
set(CONFIG_BOARD_MAIX "y")
set(CONFIG_BOARD_M5STICK "")
set(CONFIG_LCD_DEFAULT_WIDTH "320")
set(CONFIG_LCD_DEFAULT_HEIGHT "240")
set(CONFIG_LCD_DEFAULT_FREQ "15000000")

*.mk:make的配置文件,里面是一些编译变量

# Toolchain configuration
CONFIG_TOOLCHAIN_PATH="/opt/kendryte-toolchain/bin"
CONFIG_TOOLCHAIN_PREFIX="riscv64-unknown-elf-"
# end of Toolchain configuration
# Board config
CONFIG_BOARD_MAIX=y
# CONFIG_BOARD_M5STICK is not set
CONFIG_LCD_DEFAULT_WIDTH=320
CONFIG_LCD_DEFAULT_HEIGHT=240
CONFIG_LCD_DEFAULT_FREQ=15000000
CONFIG_SENSOR_FREQ=24000000
# end of Board config

*.h:可在make或make之前的menuconfig时生成

#define CONFIG_TOOLCHAIN_PATH "/opt/kendryte-toolchain/bin"
#define CONFIG_TOOLCHAIN_PREFIX "riscv64-unknown-elf-"
#define CONFIG_BOARD_MAIX 1
#define CONFIG_LCD_DEFAULT_WIDTH 320
#define CONFIG_LCD_DEFAULT_HEIGHT 240
#define CONFIG_LCD_DEFAULT_FREQ 15000000

如何查看编译了哪些文件?

  • make menuconfig,查看编译选项
  • 查看各个目录下的CMakeList.txt
    语法比较简单,根据list、append_srcs_dir等函数可以看出来包含了哪些文件夹。
    下面例子中的宏定义就是在make menuconfig阶段确定的,其值可以在*.mk(MaixPy/projects/maixpy_k210/build/config/global_config.mk)中查阅。
    MaixPy/components/kendryte_sdk/CMakeLists.txt
if(CONFIG_COMPONENT_KENDRYTE_SDK_ENABLE)

################# Add include #################
list(APPEND ADD_INCLUDE "include"
                        "kendryte-standalone-sdk/lib/bsp/include"
                        "kendryte-standalone-sdk/lib/drivers/include"
                        "kendryte-standalone-sdk/lib/utils/include"
    )

############## Add source files ###############
append_srcs_dir(ADD_SRCS "kendryte-standalone-sdk/lib/bsp")
append_srcs_dir(ADD_SRCS "kendryte-standalone-sdk/lib/drivers")
append_srcs_dir(ADD_SRCS "src")
if(CONFIG_FREERTOS_ENABLE)
    append_srcs_dir(ADD_SRCS "kendryte-standalone-sdk/lib/freertos")
    append_srcs_dir(ADD_SRCS "kendryte-standalone-sdk/lib/freertos/portable")

如何增加驱动?

将相关驱动加到现有文件夹中

不需要改动CMakeList.txt、*.mk和Kconfig

建立单独文件夹

  • 在Kconfig中添加相关目录、配置信息
  • 在*.mk中增加相关配置开关
  • 在CMakeList.txt中增加相关文件夹

其他构建系统

除了makefile+cmake这套构建系统,还有其他构建系统,比如

  • automake
    与cmake类似
  • SCons
    Scons是一个开放源码、以Python语言编码的自动化构建工具,可用来替代make编写复杂的makefile。并且scons是跨平台的,只要scons脚本写的好,可以在Linux和Windows下随意编译。

What is SCons?
SCons is an Open Source software construction tool—that is, a next-generation build tool. Think of SCons as an improved, cross-platform substitute for the classic Make utility with integrated functionality similar to autoconf/automake and compiler caches such as ccache. In short, SCons is an easier, more reliable and faster way to build software.

  • Ninja
    与make类似,可通过cmake生成Ninja的配置

Ninja is a small build system with a focus on speed. It differs from other build systems in two major respects: it is designed to have its input files generated by a higher-level build system, and it is designed to run builds as fast as possible.

工程样例

  • https://github.com/Neutree/c_cpp_project_framework
  • https://github.com/wzpan/cmake-demo
    • CMake 入门实战
  • https://github.com/XierHacker/LearningCMake
    • CMake入门实践(一) 什么是cmake
    • CMake入门实践(二) 多文件构建
    • CMake入门实践(三) :复杂的HelloWorld项目
  • https://github.com/sipeed/MaixPy

相关链接

  • https://blog.csdn.net/zhuiyunzhugang/article/details/88142908
  • https://zhuanlan.zhihu.com/p/87283287

你可能感兴趣的:(linux)