嵌入式爱好者

嵌入式爱好者 门户 知识库 查看内容

CMAKE的使用

2023-4-30 11:34| 发布者: Espoir| 查看: 154| 评论: 0

类目:  >  知识库     文档编号: 996

一、cmake简介

1.1 为什么要用cmake

平时,我们写的一些示例程序,只有一个.c文件,编译起来也比较容易,直接使用GCC编译即可。但是,实际项目中,一个工程可能包含成百上千个源文件,分布在各个目录。这样的工程通常使用makefile编译,makefile可以实现自动化编译,极大地提高效率。但是Makefile也有不足之处,譬如当使用qt编译时,需要用到qmake;qmake的语法和linux上的GNU make的规范完全不同,造成不便。cmake就是为了解决这种问题,用户可以通过一个CMakeLists.txt文件指定编译流程,生成Makefile,再执行make编译。 cmake的诞生主要是为了解决直接使用make+Makefile这种方式无法实现跨平台的问题,所以cmake是可以实现跨平台的编译工具,这是它最大的特点,当然除了这个之外,cmake还包含以下优点:

  • 开放源代码。我们可以直接从cmake官网https://cmake.org/下载到它的源代码;

  • 跨平台。cmake并不直接编译、构建出最终的可执行文件或库文件,它允许开发者编写一种与平台无关的CMakeLists.txt文件来制定整个工程的编译流程,cmake工具会解析CMakeLists.txt文件语法规则,再根据当前的编译平台,生成本地化的Makefile和工程文件,最后通过make工具来编译整个工程;所以由此可知,cmake仅仅只是根据不同平台生成对应的Makefile,最终还是通过make工具来编译工程源码,但是cmake却是跨平台的。

  • 语法规则简单。Makefile语法规则比较复杂,对于一个初学者来说,通常并不那么友好,并且Makefile语法规则在不同平台下往往是不一样的;而cmake依赖的是CMakeLists.txt文件,该文件的语法规则与平台无关,并且语法规则简单、容易理解!cmake工具通过解析CMakeLists.txt自动帮我们生成Makefile,这样就不需要我们自己手动编写Makefile了。

1.2 cmake和Makefile

直观上理解,cmake就是用来产生Makefile的工具,解析CMakeLists.txt自动生成Makefile:

二、cmake的使用

2.1 安装方法

直接apt-get即可安装 sudo apt-get install cmake 查看cmake版本 cmake -version

2.2 cmake编译单个源文件

先从编译helloworld开始,写一个main.c文件:

#include <stdio.h>
int main() 

printf("Hello World!\n");
  return 0; 
}

在当前路径下新建一个CMakeLists.txt文件,CMakeLists.txt文件会被cmake工具解析。CMakeLists.txt文件内容如下:

project(HELLO) 
add_executable(hello ./main.c)

执行cmake命令

cmake ./ 执行完cmake之后,除了源文件main.c和CMakeLists.txt之外,可以看到当前目录下生成了很多其它的文件或文件夹,包括:CMakeCache.txt、CmakeFiles、cmake_install.cmake、Makefile,重点是生成了这个Makefile文件,有了Makefile之后,接着我们使用make工具编译我们的工程,make编译后的目录如下所示:

因为我们没有配置交叉编译,所以编译出的可执行文件是X86架构的。

2.3 CMakeLists.txt文件

  • 第一行project(HELLO) project是一个命令,命令的使用方式有点类似于C语言中的函数,因为命令后面需要提供一对括号,并且通常需要我们提供参数,多个参数使用空格分隔而不是逗号“,”。 project命令用于设置工程的名称,括号中的参数HELLO便是我们要设置的工程名称;设置工程名称并不是强制性的,但是最好加上。

  • 第二行add_executable(hello ./main.c) add_executable同样也是一个命令,用于生成一个可执行文件,在本例中传入了两个参数,第一个参数表示生成的可执行文件对应的文件名,第二个参数表示对应的源文件;所以add_executable(hello ./main.c)表示需要生成一个名为hello的可执行文件,所需源文件为当前目录下的main.c。

2.4 使用out-of-source方式构建

在上面的例子中,cmake生成的文件以及最终的可执行文件hello与工程的源码文件main.c混在了一起,这使得工程看起来非常乱,当我们需要清理cmake产生的文件时将变得非常麻烦,这不是我们想看到的;我们需要将构建过程生成的文件与源文件分离开来,不让它们混杂在一起,也就是使用out-of-source方式构建。 将cmake编译生成的文件清理下,然后在工程目录下创建一个build目录,如下所示:

然后进入到build目录下执行cmake:

cd build/ 
cmake ../ 
make

这样cmake生成的中间文件以及make编译生成的可执行文件就全部在build目录下了,如果要清理工程,直接删除build目录即可,这样就方便多了。

2.5 多个源文件

在工程中加入多个源文件,分别为hello.c hello.h main.c,在hello.c当中有一个打印hello word的函数,在 main.c当中调用函数,内容如下: hello.c

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

void hello(const char *name) 

printf("Hello %s!\n", name); 
}

hello.h

#ifndef __HELLO_H
#define __HELLO_H

void hello(const char *name);

#endif

main.c

#include "hello.h"

int main() 

  hello("world");
  return 0; 
}

CMakeLists.txt文件内容:

project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})

这里设置了一个SRC_LIST变量,也可以不使用这个变量,直接写成add_executable(hello main.c hello.c)。需要注意,引用变量使用的是{},跟shell的变量有区别。

此时,工程目录结构为:

├── build //文件夹 
├── CMakeLists.txt 
├── hello.c 
├── hello.h 
└── main.c

同理,进入build路径下,执行cmake ../即可生成makefile,可以直接make编译。编译后效果如下:

2.6 设置交叉编译

如果不设置交叉编译,默认情况下,cmake会选择主机系统的编译器编译工程,在虚拟机上们就是gcc。而我们的开发板上使用的交叉编译工具为:

arm-poky-linux-gnueabi-gcc #C编译器 
arm-poky-linux-gnueabi-g++ #C++编译器

在我们每次编译应用之前,都需要执行一个环境变量,以下是部分环境变量内容:

export SDKTARGETSYSROOT=/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi
export PATH=/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/usr/bin:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/usr/sbin:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/bin:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/sbin:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/usr/bin/../x86_64-pokysdk-linux/bin:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-uclibc:/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-musl:$PATH
export CC="arm-poky-linux-gnueabi-gcc -march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7 --sysroot=$SDKTARGETSYSROOT"
export CXX="arm-poky-linux-gnueabi-g++ -march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7 --sysroot=$SDKTARGETSYSROOT"
export AS="arm-poky-linux-gnueabi-as "
export LD="arm-poky-linux-gnueabi-ld --sysroot=$SDKTARGETSYSROOT"
export GDB=arm-poky-linux-gnueabi-gdb
export TARGET_PREFIX=arm-poky-linux-gnueabi-
export CONFIGURE_FLAGS="--target=arm-poky-linux-gnueabi --host=arm-poky-linux-gnueabi --build=x86_64-linux --with-libtool-sysroot=$SDKTARGETSYSROOT"
export CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types -fdebug-prefix-map=/home/diskc/home/liyue/poky/fsl-arm-yocto-bsp/build-fb/tmp/work/x86_64-nativesdk-pokysdk-linux/meta-environment-imx6ulevk/1.0-r8=/usr/src/debug/meta-environment-imx6ulevk/1.0-r8 -fdebug-prefix-map=/home/diskc/home/liyue/poky/fsl-arm-yocto-bsp/build-fb/tmp/sysroots/x86_64-linux= -fdebug-prefix-map=/home/diskc/home/liyue/poky/fsl-arm-yocto-bsp/build-fb/tmp/sysroots/x86_64-nativesdk-pokysdk-linux= "
export CXXFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types -fdebug-prefix-map=/home/diskc/home/liyue/poky/fsl-arm-yocto-bsp/build-fb/tmp/work/x86_64-nativesdk-pokysdk-linux/meta-environment-imx6ulevk/1.0-r8=/usr/src/debug/meta-environment-imx6ulevk/1.0-r8 -fdebug-prefix-map=/home/diskc/home/liyue/poky/fsl-arm-yocto-bsp/build-fb/tmp/sysroots/x86_64-linux= -fdebug-prefix-map=/home/diskc/home/liyue/poky/fsl-arm-yocto-bsp/build-fb/tmp/sysroots/x86_64-nativesdk-pokysdk-linux= "
export LDFLAGS="-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed"
#export LDFLAGS="-Wl,--copy-dt-needed-entries -lA"
export CPPFLAGS=""
export KCFLAGS="--sysroot=$SDKTARGETSYSROOT"
export OECORE_DISTRO_VERSION="4.1.15-2.0.0"
export OECORE_SDK_VERSION="4.1.15-2.0.0"
export ARCH=arm
export CROSS_COMPILE=arm-poky-linux-gnueabi-

故配置交叉编译只需要配置几个变量,如下:

# 配置ARM交叉编译 
set(CMAKE_SYSTEM_NAME Linux) #设置目标系统名字 set(CMAKE_SYSTEM_PROCESSOR arm) #设置目标处理器架构 

# 指定编译器的sysroot路径 
set(TOOLCHAIN_DIR /opt/fsl-imx-x11/4.1.15-2.0.0/sysroots) 
set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/cortexa7hf-neon-poky-linux-gnueabi) 

指定交叉编译器arm-gcc和arm-g++ 
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc) 
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++)

# 为编译器添加编译选项 
set(CMAKE_C_FLAGS "-march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7") 
set(CMAKE_CXX_FLAGS "-march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7") 
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)



已解决

未解决

只是看看

最新评论

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2025-5-14 15:15

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

返回顶部