微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Windows 上跨平台编译的问题

如何解决在 Windows 上跨平台编译的问题

我正在学习如何在带有 C++ 的 Windows 机器上使用跨平台编译器,但遇到了问题。我已经尽我所能,但没有任何成功。任何帮助将不胜感激。 我已经在我的 Windows 机器上安装了 CYGWIN64 和 gcc-arm-none-eabi-10-2020-q4-major。

我的代码

#include <iostream>
int main()
{
    std::cout << "Hello World!\n";
}

错误信息:

arm-none-eabi-g++ helloworld.cpp -o helloworld

c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: c:/cross 
gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib/gcc/arm-none-
eabi/10.2.1/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): in 
function `exit': exit.c:(.text.exit+0x2c): undefined reference to `_exit'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../l 
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe:
C:\cygwin64\tmp\cckThWXU.o: in function `m
ain': helloworld.cpp:(.text+0x34): undefined reference to 
`std::basic_ostream<char,std::char_traits<char> >& 
std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> >&,char const*)'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe:   
helloworld.cpp:(.text+0x50): undefined reference to `std::cout'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../l/gcc
/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: C:\cygwin64
\tmp\cckThWXU.o: in function 
`__static_initialization_and_destruction_0(int,int)': helloworld.cpp:
(.text+0x88): undefined reference to `std::ios_base::Init::Init()'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: 
helloworld.cpp:(.text+0xb8): undefined reference to 
`std::ios_base::Init::~Init()'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: c:/cross 
gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib/gcc/arm-none-
eabi/10.2.1/../../../../arm-none-eabi/lib\libc.a(lib_a-abort.o): in 
function `abort': abort.c:(.text.abort+0x10): undefined reference to 
`_exit'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: c:/cross 
gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib/gcc/arm-none-
eabi/10.2.1/../../../../arm-none-eabi/lib\libc.a(lib_a-signalr.o): in 
function `_kill_r': signalr.c:(.text._kill_r+0x1c): undefined reference 
to `_kill'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: c:/cross 
gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib/gcc/arm-none-
eabi/10.2.1/../../../../arm-none-eabi/lib\libc.a(lib_a-signalr.o): in 
function `_getpid_r': signalr.c:(.text._getpid_r+0x4): undefined 
reference to `_getpid'
c:/cross gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib
/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: c:/cross 
gcc/gnu arm embedded toolchain/10 2020-q4-major/bin/../lib/gcc/arm-none-
eabi/10.2.1/../../../../arm-none-eabi/lib\libc.a(lib_a-sbrkr.o): in 
function `_sbrk_r': sbrkr.c:(.text._sbrk_r+0x18): undefined reference to 

`_sbrk' collect2.exe: 错误:ld 返回 1 个退出状态

Error Message

解决方法

我认为您的问题与 cygwin 或 windows 无关。在 Linux 上你也会得到同样的错误。顺便说一句,如果您有 Windows 10 并且不介意 Hyper-V,那么理论上您可以将 Windows 子系统用于 Linux,并在您的项目中使用 Linux 工具链(甚至在窗口内)。

更多的是关于编译的嵌入式特性,在 x86 上,我们假设我们有一个操作系统,它提供了系统调用,已经启动并初始化了内存和外围设备,它有一个可用于应用程序的控制台/标准输出。虽然裸机中的事情非常不同,但在主函数可以执行代码之前,您必须做很多事情。您正在使用 Arm 编译器,它不知道您使用的是什么板,它将具有什么内存映射,它将包含哪些外围设备。 cout 应该做什么?在 UART 上输出(什么波特率,哪个 UART,如果有多个),在 LCD 上输出(什么 LCD,用什么驱动程序,它是如何连接的,SPI 或其他方式,该 LCD 的这些设置是什么)。 . 所以这就是为什么许多嵌入式项目会“闪烁”,因为它们的 hello world 闪烁一些 LED 或切换某些 GPIO 端口上的值通常更容易测试、更容易实现并且是特定的,我们希望某些端口或 LED 可以使用高和低,而使用 cout 可能意味着任何事情,有些目标甚至可能根本无法使 cout 工作(没有 UART,没有 SPI 连接 LCD,没有半主机)。

对于 iostream 和嵌入式设备,它可能意味着很多事情,这样使用它是行不通的。供应商通常为他们的设备提供 HAL,通常与他们的工具链(或 IDE)捆绑在一起,这些工具链具有用于初始化设备并实现系统调用(例如 _open、_write、_close 等)的存根......然后像 iostream 这样的调用可以用来打开“文件”在这种情况下,它可以实现为打开 UART,每个“printf”将使用 putc,这将使用其 HAL 实现的写入。

我建议改为使用一些供应商 IDE(取决于您打算使用的目标板),我至少可以想到其中的一些,它们捆绑了 Arm 工具链并支持 Windows 和 Linux,因此您的跨平台工作。我不打算命名它们,因为我想保持公正(我为一家供应商工作),但它们很容易在 google 上搜索,并且当您可能想要针对特定​​目标时,我是否命名一些并不重要。

如果您想让代码可以在目标之间转移,那么我建议在没有这种限制的情况下开始,并与一个供应商合作并习惯 HAL/启动代码的作用。也许那时我会进行包装并进行一些抽象,并与其他一些供应商进行试验,以了解他们的 HAL 会做什么。

如果有如此通用的代码,那么它就不会像开箱即用的那样工作。您将需要一些 weakly linked 函数的实现,例如 putchar,因此对于每个供应商,他们可以实现该函数只是为了调用他们的 HAL。本质上在做:

<some application> -> <your library> -> <generic HAL call> -> <vendor specific HAL call>

这里有关于 weak 的更多信息: How to make weak linking work with GCC?

以这个跨目标 printf 实现为例,每个用户都必须实现 _putchar,因为他不知道 printf 将被使用什么、如何使用以及在哪里使用。

https://github.com/mpaland/printf

可能您不应该制作一个多目标应用程序,而应该制作一个通用的可插拔库,这样用户就可以将它添加到他们的应用程序中,而不是使用您的应用程序。因为无论您尝试多么通用,您的形状都不会以一种形式工作。每个供应商都有自己的启动代码、HAL、链接器脚本以及组织项目以在其生态系统中工作的方法。没有一种系统可以与所有人兼容,因此如果您想要可移植,您必须允许用户使用他们供应商推荐的任何内容,然后从他们的应用程序中调用您的库。

我强烈建议放弃可移植性,先在一台主机上做一些工作,一个工具链一个目标,获得一些经验和知识,然后再尝试使东西具有可移植性和通用性。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。