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应用:交叉编译 的相关文章

  • CLion - 命令行程序参数

    当我分配给 运行 调试配置 程序参数 之类的 aaa bbb 然后打印它时 任何人都可以告诉我 JetBrains CLion 有什么问题吗 printf s n argv 1 我刚刚得到 aaa 而它必须是 aaa bbb 因为它们用双引
  • 在cmake中,什么是“项目”?

    这个问题是关于project命令 推而广之 是什么concept of a project意思是cmake中的 我真的不明白什么是project是 以及它与target 我想我确实理解 我看了一下cmake 文档project http w
  • 如何通过 Cmake 查找 iOS/mac OS X 框架

    Context 我通过此将 Boost C 库打包到一个框架 适用于 iOS 中script https github com davidandreoletti boostoniphone generic 该脚本产生boost框架 当链接到
  • cmake 找不到 Qt4

    由于4 8 0已经发布 我重新安装了Qt 现在我也想使用cmake 为了使 cmake 工作 我记得必须添加 mingw bin 文件夹 QtSDK Desktop Qt 4 7 3 到Qt4 7 3中的PATH 所以我猜测在中会有一个类似
  • 针对 dll/lib 的 cmake 链接

    我的 cmake 的输出是一个静态库 我正在这样创建它 add library myMainLib STATIC BACKEND SOURCES 当我尝试让 myMainLib 链接到第三方 lib dll 时 出现了问题 dll 文件将在
  • 在 C 中使用 pow 时,CMake 可以检测是否需要链接到 libm 吗?

    对于某些编译器 using powC 程序中的某些其他函数需要链接到m library https stackoverflow com q 8671366 1959975 但是 某些编译器不需要这样做 并且在链接到m图书馆 C 也存在几乎相
  • CMake“无法运行 MSBUILD.exe”命令错误

    当我想为 opencv 3 3 0 创建 Visual Studio 15 2017 make 文件时 它给了我以下错误消息 error in configuration process project files maybe invali
  • 使用星号更改多个源文件的 CMake 编译器标志

    我正在尝试调试与编译器优化相关的问题 O2 或以下版本没有问题 O3 出现段错误 并且我希望能够切换我的源代码块的编译器标志 以便我可以尝试缩小段错误的来源范围 我可以将全局优化级别设置为 O2 并更改单个文件的属性 如下所示 SET SO
  • 了解 CMake 背后的目的[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我试图理解 CMake 背后的目的 为什么它被设计成现在这样 以下是我想回答的一些问题 为什么CMake会生成生成文件 https e
  • 在 CMake 中使用 GLOB 指定源文件还是单独指定每个文件更好?

    CMake 提供了多种方法来指定目标的源文件 一种是使用通配符 文档 https cmake org cmake help latest command file html 例如 FILE GLOB MY SRCS dir 另一种方法是单独
  • CMake - 未定义参考

    我正在尝试将 gtest 包含到我的项目中 问题是我在 GTest 中收到未定义的引用错误 我正在尝试在 Gtest 中测试 Node 类 在节点的构造函数中 我使用类记录器 尽管我已将库记录器添加到 gtest target 中 但我仍然
  • CMake:如何更改单个目标的编译器

    我有使用交叉编译器的嵌入式项目 我想介绍一下Google测试 用原生GCC编译器编译 另外使用 CTC 编译器构建一些单元测试目标 Briefly 我有 3 个不同的目标并用 3 个不同的编译器编译它们 如何表达它CMakeLists tx
  • CMake 添加对安装目标的依赖

    我在使用cmake时遇到以下问题 我使用 UseDoxygen 来自http tobias rautenkranz ch cmake doxygen http tobias rautenkranz ch cmake doxygen 为我的图
  • 将 cmake 与 nmake x64 一起使用

    我使用 cmake 生成 NMake 文件 一切正常 我使用 x64 工具集 没有 Visual Studio 只有 SDK 因此我输入 nmake 但它生成 x86 构建而不是 x64 构建 你知道为什么吗 以及如何强制 nmake 以
  • CMake、Exe找不到DLL

    所以我尝试在 Windows 上使用 cmake 设置一个项目 这就是我的项目结构 游戏引擎 git build include source testing CMakeLists txt 这个想法是 source 目录包含 GameEng
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • 我可以安装共享导入库吗?

    我有一个外部项目和一个导入的共享库 include 目录和 implib 都可以正常工作 但尝试安装共享库 dll 失败并出现以下错误 install TARGETS given target my shared lib which doe
  • 编译器标志的 cmake list 附加会产生虚假结果?

    我需要向 CMake 文件 CMake 2 8 10 2 中的 C 和 C 编译行添加各种标志 我看到有些人使用add definitions但据我所知 这是用于预处理器标志的 D 我有一些标志不想传递给预处理器 所以我一直在尝试修改CMA
  • 奇怪的函数参数名称行为

    我问了一个关于cmake和传递变量的问题here https stackoverflow com questions 14375519 cmake how to write a nice function that passes varia
  • CMake第三方库安装

    我是编程新手 对于我的研究项目 我需要安装一个第三方库以便与 CMake 一起使用 GitHub项目 https github com cpp io2d P0267 RefImpl blob master BUILDING md 我在我的电

随机推荐

  • 【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 或者