【CMake 入门与进阶(13)】 CMake如何设置交叉编译(附代码)

news2024/11/17 3:54:16

        cmake如果不设置交叉编译,默认情况下,会使用主机系统(运行 cmake 命令的操作系统)的编译器来编译我们的工程,那么得到的可执行文件或库文件只能在 Ubuntu 系统运行,如果我们需要使得编译得到的可执行文件或库文件能够在ARM 平台上运行,则需要配置交叉编译,本文将进行介绍。我们使用的交叉编译器如下:

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

        其实配置交叉编译非常简单,只需要设置几个变量即可,如下所示:

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

# 指定编译器的 sysroot 路径
set(TOOLCHAIN_DIR /opt/fsl-imx-x11/4.1.15-2.1.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)

        CMAKE_SYSTEM_NAME 变量在前面给大家介绍过,表示目标主机(譬如 ARM 开发板)的操作系统名称,这里将其设置为 Linux,表示目标操作系统是 Linux 系统。 CMAKE_SYSTEM_ PROCESSOR 变量表示目标架构名称。

        CMAKE_SYSROOT 变量前面也给大家介绍过,该变量的值会传递给 gcc 编译器的--sysroot 选项,也就是--sysroot=${CMAKE_SYSROOT},--sysroot 选项指定了编译器的 sysroot 目录,也就是编译器的系统根目录,编译过程中需要链接的库、头文件等,就会去该目录下寻找,譬如标准 C 库、标准 C 头文件这些。

        CMAKE_C_COMPILER 变量指定了 C 语言编译器 gcc,由于是交叉编译,所以应该指定为 arm-gcc。

        CMAKE_CXX_COMPILER 变量指定了 C++语言编译器 g++,由于是交叉编译,所以应该指定为 arm-g++。

        CMAKE_C_FLAGS 变量为 gcc 编译器添加编译选项,CMAKE_CXX_FLAGS 变量为 g++编译器添加编译选项。

        CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 和 CMAKE_FIND_ROOT_PATH_MODE_INCLUDE 被设置为 ONLY;CMAKE_FIND_ROOT_PATH_MODE_INCLUDE 变量控制 CMAKE_SYSROOT 中的路径 是否被 find_file()和 find_path()使用。如果设置为 ONLY,则只会搜索 CMAKE_SYSROOT 中的路径,如果设置为 NEVER,则 CMAKE_SYSROOT 中的路径将被忽略并且仅使用主机系统路径。如果设置为 BOTH, 则将搜索主机系统路径和 CMAKE_SYSROOT 中的路径。

        同理,CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 变量控制 CMAKE_SYSROOT 中的路径是否被 find_library()使用,如果设置为 ONLY,则只会搜索 CMAKE_SYSROOT 中的路径,如果设置为 NEVER, 则 CMAKE_SYSROOT 中的路径将被忽略并且仅使用主机系统路径。如果设置为 BOTH,则将搜索主机系统路径和 CMAKE_SYSROOT 中的路径。

        CMAKE_SYSROOT、CMAKE_C_COMPILER、CMAKE_CXX_COMPILER 这些变量涉及到交叉编译工具的安装路径,需要根据自己的实际安装路径来确定。

        接着我们进行测试,譬如工程目录结构如下所示:

├── build
├── CMakeLists.txt
└── main.c

        main.c 源文件中调用了 printf()函数打印了“Hello World!”字符串,CMakeLists.txt 内容如下:

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

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

# 指定交叉编译器 arm-linux-gcc 和 arm-linux-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)
#################################
# end
##################################

project(HELLO) #设置工程名称
add_executable(main main.c)

        这里要注意,配置 ARM 交叉编译的这些代码需要放置在 project()命令之前,否则不会生效! 接着进入到 build 目录下,然后执行 cmake,此时执行 cmake 会报错!如下所示:

         原因是使用了过低版本的cmake,笔者用的是 Ubuntu 系统自带的 cmake 工具,版本是 3.5.1,导致这里出错,所以笔者建议大家去下载一个高版本的 cmake,然后使用这个高版本的 cmake 工具,不然会报错。

        那怎么去下载高版本的 cmake,其实非常简单,我们首先进入到 cmake 的 GitHub 链接地址 Releases · Kitware/CMake · GitHub,此处下载使用了 3.16.0版本,如下所示:

         这里我们下载 cmake-3.16.0-Linux-x86_64.tar.gz 压缩包文件,这个不是 cmake 的源码工程,而是可以在 x86-64 的 Linux 系统下运行的可执行程序,其中就包括了 cmake 工具,所以我们下载这个即可,非常方便, 都不用自己编译!

        下载成功之后将其拷贝到 Ubuntu 系统的用户家目录下,并将其解压到某个目录,解压之后生成 cmake-3.16.0-Linux-x86_64 文件夹,这里笔者选择将其解压到家目录下的 tools 目录中。

        cmake 工具就在 cmake-3.16.0-Linux-x86_64/bin 目录下。 现在重新进入到我们的工程目录下,进入到 build 目录执行 cmake即可。

        编译生成的 main 可执行文件,通过 file 命令查看可知,它是一个 ARM 架构的可执行程序。 

        上例中的这种交叉编译配置方式自然是没有问题的,但是不规范,通常的做法是,将这些配置项(也就是变量的设置)单独拿出来写在一个单独的配置文件中,而不直接写入到 CMakeLists. txt源码中,然后在执行 cmake 命令时,指定配置文件给 cmake,让它去配置交叉编译环境。

        通过如下方式指定配置文件:

cmake -DCMAKE_TOOLCHAIN_FILE=cfg_file_path ..

        通过-DCMAKE_TOOLCHAIN_FILE 选项指定配置文件,-D 是 cmake 命令提供的一个选项,通过该选项可以创建一个缓存变量(缓存变量就是全局变量,在整个工程中都是生效的,会覆盖 CMakeLists.txt 源码中定义的同名变量 ),所以 -DCMAKE_TOOLCHAIN_FILE 其实就是设置了缓存变量 CMAKE_TOOLCHAIN_FILE,它的值就是“=”号后面的内容,cmake 会执行 CMAKE_TOOLCHAIN_FILE 变量所指定的源文件,对交叉编译进行设置;现在我们进行测试,在工程源码目录下创建一个配置文件 arm-linux-setup.cmake,内容如下:

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

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

# 指定交叉编译器 arm-linux-gcc 和 arm-linux-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)
#################################
# end
##################################

        推荐使用这种方式配置交叉编译,而不是直接写入到 CMakeLists.txt 源码中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/676656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javaWeb医药管理系统

一、引言 二、项目截图 2.1 首页设计 2.2一级页面设计 2.2-1注册界面 2.2-2管理员登录界面 2.3二级页面设计 药品信息模块 药品销售 用户信息 三、项目基本要求 1.主要功能 医药管理系统的主要功能为:、药品更新、药品查询 药品更新功能分为三部分&…

前端Vue自定义支付密码输入键盘Keyboard和支付设置输入框Input

前端Vue自定义支付密码输入键盘Keyboard和支付设置输入框Input&#xff0c; 下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13166 效果图如下&#xff1a; # cc-defineKeyboard #### 使用方法 使用方法 <!-- ref:唯一ref pas…

VMware vCenter Server 7.0 Update 3m 发布下载(重要安全更新)

VMware vCenter Server 7.0 Update 3m 发布下载&#xff08;重要安全更新&#xff09; 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vcenter-7-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org VMware vCente…

canvas详解07-裁剪

裁切路径 裁切路径和普通的 canvas 图形差不多,不同的是它的作用是遮罩,用来隐藏不需要的部分。如右图所示。红边五角星就是裁切路径,所有在路径以外的部分都不会在 canvas 上绘制出来。 如果和上面介绍的 globalCompositeOperation 属性作一比较,它可以实现与 source-in …

基于cycle of curves的Nova证明系统(2)

主要见斯坦福大学Wilson Nguyen、Dan Boneh和微软研究中心Srinath Setty 2023年论文《Revisiting the Nova Proof System on a Cycle of Curves》。 前序博客见&#xff1a; 基于cycle of curves的Nova证明系统&#xff08;1&#xff09; 5. IVC Proof进一步压缩 本文提出了…

【Rust】1、实战:语法和数据结构、生命周期-所有权-借用、自制 CPU、内存、文件

文章目录 零、Rust 好用的资源一、概述1.1 安全性1.1.1 垂悬指针1.1.2 数据竞争1.1.3 迭代器失效 1.2 性能1.3 vscode 設置 二、基础语法2.1 循环2.2 引用2.3 生命周期2.4 泛型2.5 实战grep项目2.6 数组2.6.1 数组和切片2.6.2 动态数组2.6.3 初始化 2.7 包含第三方库2.8 命令行…

深入理解深度学习——BERT(Bidirectional Encoder Representations from Transformers):输入表示

分类目录&#xff1a;《深入理解深度学习》总目录 相关文章&#xff1a; BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff1a;基础知识 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09…

【Linux】MySQL 高级 SQL 语句 (一)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MySQL 高级 SQL 语句 MySQL 高级(进阶) SQL 语句SELECT&#xff1a;显示表格中一个或数个字段的所有数据记录DISTINCT&#xff1a;不显示重复的数据记录WHERE&#xff1a;有条…

CVE-2022-25411

文章目录 CVE-2022-25411一、漏洞介绍二、渗透步骤1、打开网站2、目录扫描3、访问后台4、添加文件后缀5、上传shell6、查看flag值 CVE-2022-25411 一、漏洞介绍 Maxsite CMS文件上传漏洞。 MaxSite CMS是俄国MaxSite CMS开源项目的一款网站内容管理系统。马克斯程序(MaxCMS)以…

【Syncfusion系列】SfDataGrid 轻松实现分页和Excel导出

前言 Syncfusion 封装了一个控件 SfDataGrid &#xff0c;通过SfDataGrid我们只需要 极少量 代码就能分页和Excel导出。 效果展示 包安装 安装下面三个包 将表格绑定到数据库 这次我使用的是一个本地的小型数据库&#xff1a;sqlit 我通过 sqlit-net 这个包 进行访问 sqlit…

Dify 基于 ChatGPT 构建本地知识库问答应用

一、Dify 自从 ChatGPT 横空出世之后&#xff0c;其极高的语言理解和交互能力不仅让人惊呼&#xff0c;ChatGPT不仅能够处理事实性问题&#xff0c;还能理解和生成情感色彩更浓厚的对话内容&#xff0c;能够识别用户的情感倾向&#xff0c;并据此作出相应的回应。这么好的东西…

Linux——文件基础IO的文件描述符和重定向理解

目录 前言&#xff1a; 首先来回顾一下open函数&#xff0c;即在进程中同时打开多个文件&#xff1a; Linux底层进程与文件的关系 &#xff1a; 2.1关闭stdin&#xff1a; 运行结果&#xff1a; ​编辑由结果知&#xff1a;fd1指向文本文件cyq.txt&#xff0c;原本fd1是默…

机器学习多步时间序列预测解决方案

近年来&#xff0c;随着机器学习与深度学习的发展机器学习平台的成熟&#xff0c;数据科学家们不再需要关心底层的基础设施及构建复杂的训练与推理环境&#xff0c;从而可以把主要的时间与精力放在数据与算法本身。在机器学习变得更容易的今天&#xff0c;越来越多的传统行业已…

HAL库——STM32CubeMX中断相关配置(中断反转LED状态)

STM32CubeMX中断相关配置 文章目录 STM32CubeMX中断相关配置1. 选择你要用的芯片(双击打开)2. 设置串口写入3. 配置时钟树&#xff0c;外部时钟为系统时钟&#xff08;PLL倍频时钟&#xff09;4. 查看原理图&#xff0c;找到可以中断控制的器件&#xff0c;或者外接小灯来达到中…

中国版chatGPT【文心一言】

文心一言是一款基于人工智能技术的中文自然语言处理工具&#xff0c;它可以用于文本生成、情感分析、关键词提取等多种应用场景。相比于GPT等其他自然语言处理模型&#xff0c;文心一言有着更多的优势。 首先&#xff0c;文心一言具有更高的准确率和可靠性。它采用了最新的深度…

Redis之RDB和AOF持久化原理解析

Redis之RDB和AOF持久化原理解析 一 RDB持久化原理及缺点 说明&#xff1a; 主进程是没法读取物理内存的&#xff0c;所以会在主进程有一个页表来读取物理内存中的数据子进程共享主进程的数据&#xff0c;会复制页表&#xff0c;写入磁盘中写操作是会拷贝一份在进行写操作 二…

【MySql】MySql事务隔离级别与一致性

文章目录 理解隔离性隔离级别查看与设置隔离性读未提交Read Uncommitted读提交Read Committed可重复读 Repeatable Read串行化serializable一致性(Consistency) 理解隔离性 MySQL服务可能会同时被多个客户端进程(线程)访问&#xff0c;访问的方式以事务方式进行 一个事务可能由…

计算机网络——自顶向下方法(第四章学习记录)

本章学习网络层&#xff1a;数据平面 前一章中我们学习了运输层依赖于网络层的主机到主机的通信服务&#xff0c;提供了各种形式的进程到进程的通信。在本章中我们将看到与运输层和应用层不同的是&#xff0c;在网络中的每一台主机和路由器中都有一个网络层部分。 网络层能够…

【FreeRTOS】FreeRTOS学习笔记 ---- 堆和栈,第1个FreeRTOS程序,创建任务函数及任务管理

&#x1f340;作者&#xff1a;阿润菜菜 目录 一、通过故事介绍FreeRTOS1.什么是FreeRTOS&#xff1f;2.FreeRTOS能做什么&#xff1f; 二、如何使用FreeRTOS&#xff1f; --- 第1个FreeRTOS程序三、FreeRTOS的堆和栈1.堆和栈的概念2.堆和栈的分配方式3.堆和栈的溢出检测 四、创…

【创建一个螺旋状的相机轨迹并可视化该轨迹以及每个点的姿态】

文章目录 焦点的作用static const Eigen::Vector3d b_cam_z(0, 0, 1);static const Eigen::Matrix3d R_w_base = (Eigen::Matrix3d() << 0, 0, -1, 1, 0, 0, 0, -1, 0).finished()import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import …