跨编译C++项目,通用ELF文件中的重定位(EM: 3)

9
我已经在一段时间内开发了一个C++项目,但想将其移植到我的ARM处理器上。我已经拥有所有的交叉编译工具(我正在使用CodeSourcery),并认为只需更改我的makefile以指向该编译器即可。它使用默认的g++进行编译,但是当我尝试使用交叉编译器进行编译时,出现了重定位错误:
/home/oryan/CodeSourcery/bin/../lib/gcc/arm-none-linux-gnueabi/4.5.2/../../../../arm-none-linux-gnueabi/bin/ld: ServerSocket.o: Relocations in generic ELF (EM: 3) ServerSocket.o: could not read symbols: File in wrong format collect2: ld returned 1 exit status make: *** [simple_server] Error 1
看起来我没有正确设置链接或者链接指向了错误的位置。我对makefile不太熟悉,可能会遗漏一些显而易见的东西。我一直在使用的makefile来自于这里:http://tldp.org/LDP/LG/issue74/tougher.html,已经删除了客户端部分。
# Makefile for the socket programming example
#

simple_server_objects = ServerSocket.o Socket.o simple_server_main.o

all : simple_server

simple_server: $(simple_server_objects)
         /home/matt/CodeSourcery/bin/arm-none-linux-gnueabi-g++ -o simple_server $(simple_server_objects)


Socket: Socket.cpp
ServerSocket: ServerSocket.cpp
simple_server_main: simple_server_main.cpp

clean:
        rm -f *.o simple_server

目前我正在手动编译每个文件,效果很好,但我想进一步了解这里的情况。

谢谢!

2个回答

9
问题是您已经设置了Makefile以链接到新的g++,但是您还没有更改要使用的编译器来首先构建对象。
最简单的方法是设置环境变量CXX为下一个编译器,即:
export CXX=/home/matt/CodeSourcery/bin/arm-none-linux-gnueabi-g++

或者你可以通过在命令行中添加 CXX=... 来为给定的 make 设置编译器。

你需要首先执行 make clean 命令,然后就可以同时用正确的编译器进行编译和链接了。

你也可以在 makefile 中指定一个新的如何编译 C++ 文件的规则来指定新的编译器,但是环境变量更容易操作:

.cc.o:
        /home/.../g++ $(CPPFLAGS) $(CXXFLAGS) -c

我添加了CXX变量并且它指向了交叉编译器,但现在我遇到了/user/bin/ld: ServerSocket.o: Relocations in generic ELF (EM: 40)的错误。所以我认为仍然存在一个错误,它没有指向我的交叉编译工具,而是查看默认的ld。 - Matt
嗯,我记得是 g++ -print-prog-name=ld 来显示它正在使用哪一个,但我不记得如何指定一个了。我认为它会从与 cc1plus 相同的目录中选择一个 - 你在那个目录中有一个 ld 吗(可能是 CodeSourcery/libexec/gcc/arm-none-linux-gnueabi/4.5.2/)?你确定已经为交叉编译器安装了 binutils 吗? - Rup
g++ -print-prog-name 只给了我 "ld"。cc1plus 也没有 ld 文件。但是在 CodeSourcery/bin/ 目录下有一个 arm-none-linux-gnueabi-ld。也许是指向 arm-none-linux-gnueabi-ld 的软链接? - Matt
软链接确实可以工作,但我认为这不是一个好的解决方案。现在交叉编译顺利进行,但要在普通的g++中编译,我需要删除软链接。所以为了避免一个头疼问题,我又引发了另一个问题... - Matt
抱歉我没有忘记这件事 - 我想知道选择所需的ld文件的正确方法,但我不知道答案。我会在接下来的几天里看看能否弄清楚。 - Rup
没关系 Rup,我也还在尝试中。不过还是谢谢你的帮助! - Matt

1
问题出在这三条规则上:
Socket: Socket.cpp
ServerSocket: ServerSocket.cpp
simple_server_main: simple_server_main.cpp

首先,我猜规则的左侧应该是目标文件,因此应该有 .o 后缀。
第二个问题,也很可能是你遇到问题的根源,就是没有编译源文件的命令,这意味着 make 将使用默认编译器而不是你的交叉编译器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接