CMake应用:交叉编译

2023-05-16

交叉编译指的在一个平台上生成另一个平台上的可执行代码。很多时候,开发的代码可能并不只是在开发主机的平台上执行,比如在Windows下开发的程序,希望能够在Linux、或者MacOS下执行;或者有时候目标平台根本就没有操作系统,没有对应的编译器,所以必然需要进行交叉编译。

交叉编译笔者在工作中经常会遇到。笔者开发使用的宿主机一般都是Linux(Ubuntu),交叉编译的目的基本都是为了将程序代码编译成目标嵌入式平台的库文件,然后再在目标系统上调用集成,一般都是ARM系列的CPU。而对于不同操作系统(Windows、Linux、MacOS)之间的交叉编译,则主要是为了编译示例程序,方便在不同操作系统上进行展示或者调试。

一 编译和CMake工具链

就像在前面的文章GCC编译过程概述中说的一样,目标文件的编译构建,其实是有很多个阶段的,每个阶段会使用不同的工具,比如特定语言的编译器、链接器、库文件操作工具等等,这也是GCC被称为编译工具套件的原因。

一般情况下,对于GCC来说,只需要使用命令行工具gcc或者g++就可以完成大部分工作,很多步骤都是被封装好的,套件内的不同工具会被适时地自动调用。

在CMake中,也是类似的概念,这些编译构建工具统称为工具链(toolchain),工具链基于不同的语言有不同配置,一般情况下,CMake会根据宿主机自动选择应该使用的工具链。

在进行交叉编译时,需要显式指定一个工具链文件,指明要使用的编译器、编译器的配置选项以及其他必要工具的路径

1 工具链文件

工具链文件(toolchain file)习惯上一般以.toolchain.cmake结尾。工具链文件的编写并不复杂,一般只需要指定以下这些CMake内置变量:

  1. CMAKE_SYSTEM_NAME:表明目标系统名称,比如LinuxQNXAndroid等;如果目标平台并没有系统,则应该指定为Generic;默认值为CMAKE_HOST_SYSTEM_NAME

  2. CMAKE_SYSTEM_PROCESSOR:表明目标平台架构,比如最常见的arm

  3. CMAKE_<LANG>_COMPILER:表明特定语言的要采用的编译器,需要使用完整路径,一般需要设置C语言编译器变量CMAKE_C_COMPILERC++编译器变量CMAKE_CXX_COMPILER

  4. CMAKE_<LANG>_FLAGS:设置特定编译器对应的编译选项,也可以使用add_compile_options为所有编译器设置相同的一些编译选项。

还有一些是可选的参数,根据目标平台的不同按需设置即可,大多数时候,cmake执行的时候会报错提示的~

下面是一个使用arm-none-eabi-gcc编译器的工具链文件示例:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(TOOLS /home/farmer/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux)
set(CMAKE_C_COMPILER "${TOOLS}/bin/arm-none-eabi-gcc")
set(CMAKE_CXX_COMPILER "${TOOLS}/bin/arm-none-eabi-g++")
set(CMAKE_AR "${TOOLS}/bin/arm-none-eabi-gcc-ar")

add_compile_options(-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -g -Os -MMD -MP -Wall)

对于编译选项,需要结合项目实际开发情况。对于arm平台,比较重要的几个选项包括:

  1. -mcpu

  2. -mfpu

  3. -mfloat-abi

其他更多参数可以在GCC官网或者对应编译器官方查看。

这里是假定知道了arm-none-eabi-gcc所在路径,对于团队协作可能并不是很友好,写死的路径在不同开发者的机器上可能不一样。当然,对于编译都只在服务器进行的情况就没有关系了。

如果开发者将编译套件对应可执行文件目录添加到系统环境变量,那么也可以直接设置对应的编译器可执行文件名称,比如:

set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
set(CMAKE_CXX_COMPILER "arm-none-eabi-g++")

也可以通过find_program在系统路径下查找及指定的路径下查找对应的编译器可执行文件,再进行设置:

find_program(C_COMPILER "arm-none-eabi-gcc" ${SEARCH_PATHS})
find_program(CXX_COMPILER "arm-none-eabi-g++" ${SEARCH_PATHS})
set(CMAKE_C_COMPILER ${C_COMPILER})
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})

二 CMake交叉编译

在需要进行交叉编译的时候,先编写一个适用于目标平台的工具链文件,然后在执行cmake命令开始构建时,可以使用参数--toolchain或者-DCMAKE_TOOLCHAIN_FILE=指定工具链文件的路径即可:

cmake ... --toolchain <path/to/toolchain-file>
# or
cmake ... -DCMAKE_TOOLCHAIN_FILE=<path/to/toolchain-file>

所以交叉编译是比较简单的,一般只需要知道使用什么编译套件以及对应的配置

如果是交叉编译给Android平台使用的库,直接使用Android官方NDK中提供的toolchain就好。

使用Android toolchain路径一定要通过NDK所在目录指定:<NDK>/build/cmake/android.toolchain.cmake,因为它会使用相对路径访问NDK内部其他的资源,否则会出错。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMake应用:交叉编译 的相关文章

随机推荐

  • 【Kubernetes系列】K8s更新镜像的几种方法

    目录 一 准备二 更新镜像1 方法一 xff1a 修改 yaml 文件版本号并执行2 方法二 xff1a 使用 set image3 方法三 xff1a 使用 patch 一 准备 以下以前端的服务为例 xff0c 前端 yaml 文件内容
  • Java中toString的使用

    在java中 xff0c 所有对象都有toString 这个方法 xff0c 因为它是Object里面已经有了的方法 xff0c 而所有类都是继承Object xff0c 所以 所有对象都有这个方法 它通常只是为了方便输出 xff0c 比如
  • Linux安装时至少划分哪两个分区才能正常安装使用

    根 xff08 boot xff09 分区和SWAP分区
  • C#界面动态布局 界面控件随着界面大小尺寸变化而变化

    要想写一个漂亮的界面 xff0c 光靠利用Anchor和Dock属性是远远不够的 xff0c 我们需要用到相对布局 xff0c 就是不管窗口大小怎么变化 xff0c 控件相对父控件的相对位置保持不变 可惜c 里没有提供按照百分比布局 所以只
  • 一个简单的Dockerfile

    一个简单的Dockerfile xff0c 如下 xff1a FROM golang span class token comment 基础镜像 span COPY print num go root span class token co
  • c++ 构造函数后面加冒号

    有四种情况下应该使用初始化表达式来初始化成员 xff1a 1 xff1a 初始化const成员 常量必须在构造函数的初始化列表中初始 xff0c 或将其设为static Wrong Class A const int size 61 0 R
  • PX4程序编译过程解析

    第一章 PX4程序编译过程解析 PX4是一款软硬件开源的项目 xff0c 目的在于学习和研究 其中也有比较好的编程习惯 xff0c 大家不妨可以学习一下国外牛人的编程习惯 这个项目是苏黎世联邦理工大学的一个实验室搞出来的 该方案是基于NUT
  • Git使用之——冲突解决一(git merge conflict)

    Git冲突是在多用户协同工作下出现 xff0c 在一些情况下Git可以智能自动合并 xff0c 但有时需要用户手动合并 xff08 本文链接 xff1a http blog csdn net u012150179 article detai
  • git fetch 的简单用法:更新远程代码到本地仓库

    Git中从远程的分支获取最新的版本到本地方式如下 xff0c 如何更新下载到代码到本地 xff0c 请参阅ice的博客基于Github参与eoe的开源项目指南 方式一 1 查看远程仓库 1 2 3 4 5 6 git remote v eo
  • 各类数值型数据间如何混合运算?

    整型 包括int xff0c short xff0c long 实型 包括float xff0c double 可以混合运算 前已述及 xff0c 字符型数据可以与整型通用 xff0c 因此 xff0c 整型 实型 字符型数据间可以混合运算
  • 整型与字符型相加

    想通过整型与字符型相加的到正确的整型数值 xff0c xff0c 见下面的程序 xff1a include lt stdio h gt void main int a 61 2 char c 61 39 3 39 int b 61 a 43
  • Scrapy研究探索(五)——自动多网页爬取(抓取某人博客所有文章)

    首先 xff0c 在教程 xff08 二 xff09 xff08 http blog csdn net u012150179 article details 32911511 xff09 中 xff0c 研究的是爬取单个网页的方法 在教程
  • Scrapy研究探索(六)——自动爬取网页之II(CrawlSpider)

    原创 xff0c 转载注明 xff1a http blog csdn net u012150179 article details 34913315 一 目的 在教程 xff08 二 xff09 xff08 http blog csdn n
  • reStructuredText

    此文章转自 xff1a http wstudio web fc2 com others restructuredtext html 还有一篇中文教程也可以 xff1a http jwch sdut edu cn book rst html
  • 智能指针tr1::shared_ptr、boost::shared_ptr使用

    对于tr1 shared ptr在安装vs同时会自带安装 xff0c 但是版本较低的不存在 而boost作为tr1的实现品 xff0c 包含 Algorithms Broken Compiler Workarounds Concurrent
  • 关于CSDN几点用户体验较差的功能(收藏夹和草稿箱)

    1 收藏夹不去重 同一专栏或博客每点一次 收藏 都会增加到收藏夹中 收藏内容一般有两种形式 xff1a xff08 1 xff09 专栏收藏 xff08 2 xff09 博客文章收藏 对于前者 xff0c 虽然专栏的文章数量可能是不断在增加
  • 关于提高效率的几点

    有些时候感觉一直没闲着却没看见多少成果 突然看见这篇文章 xff08 http www cppfans org 1644 html xff09 xff0c 虽然不能全部认同 xff0c 但是的确有些部分还是值得思考的 以下为转载 xff1a
  • PX4应用examples[1]:px4_simple_app解析与自己的功能模块构建

    PX4应用examples 1 px4 simple app解析与自己的应用构建 px4 simple app源代码学习代码分析第一部分 PX4简单打印消息的发布第二部分 传感器信息的获取关于sensor combined的介绍 xff1a
  • 已将GitHub scrapy-redis库升级,使其兼容最新版本Scrapy

    1 代码升级 之前的问题 xff1a 随着Scrapy库的流行 xff0c scrapy redis作为使用redis支持分布式爬取的工具 xff0c 也不断的被大家发现 但是 xff0c 使用过程中你会发现的问题是由于scrapy red
  • CMake应用:交叉编译

    交叉编译指的在一个平台上生成另一个平台上的可执行代码 很多时候 xff0c 开发的代码可能并不只是在开发主机的平台上执行 xff0c 比如在Windows下开发的程序 xff0c 希望能够在Linux 或者MacOS下执行 xff1b 或者