关键字:Ubuntu、WSL1、arm-oe-linux-gnueabi-gcc、交叉编译、找不到该文件
1 前言
原先个人编译程序都是在Virtual Box的Linux虚拟机上进行编译的,可是在使用一段时间后就会因为内存不够的原因会变得十分的卡顿,并且卡顿后很容易迎来虚拟机系统的崩溃,因为源代码是直接放在Linux虚拟机上编辑的,一旦虚拟机崩溃,自己的整个源代码工程也就坏掉了,十分让人烦恼,严重影响开发效率。
在接触到微软的WSL之后,自己便萌生了在WSL中进行交叉编译的想法。查看任务管理器发现WSL占用的内存资源也是比较小的,只要将需要编译的代码直接放Windows文件系统下的硬盘,然后Windows下编辑,WSL中编译,一气呵成,十分的方便。如前面的需求所述,这里采用WSL1进行交叉编译链的配置。
2 环境
- 交叉编译器:arm-oe-linux-gnueabi-gcc(硬件模块供应商提供)
- 操作系统:Microsoft Windows 11
- WSL:Ubuntu 20.04.2 LTS(使用WSL1)
- 系统工具:Windows Terminal
3 具体方法
3.1 解压交叉编译链
模块供应商所提供的交叉编译链为oecore-x86_64.tar.bz2,并提供了配置的指令。我自己这里是将之前虚拟机已配好的编译链打包成了oecore-x86_64.zip,实际上只是对这个交叉编译链解压到相应的目录环境下:
# 供应商提供的压缩包
sudo tar xvjf oecore-x86_64.tar.bz2 -C /usr/local/
# 自己的oecore-x86_64.zip压缩包使用unzip命令
sudo unzip oecore-x86_64.zip -d /usr/local/
3.2 配置交叉编译链环境变量
交叉编译链解压完毕后,要确认里头提供的编译程序是否可用,就需要使用命令arm-oe-linux-gcc -v
,这时候发现找不到该命令:
veahow@VEAHOW-AMADEUS:~$ arm-oe-linux-gcc -v
arm-oe-linux-gcc: command not found
这个实际上是环境变量中没有配置交叉编译链所在的路径,进入/usr/local/
中就能够看到之前解压交叉编译链的oecore-x86_64文件夹:
veahow@VEAHOW-AMADEUS:~$ ls
veahow@VEAHOW-AMADEUS:~$ cd /usr/local/
veahow@VEAHOW-AMADEUS:/usr/local$ ls
bin etc games include lib man oecore-x86_64 sbin share src usr
veahow@VEAHOW-AMADEUS:/usr/local$ cd oecore-x86_64/
veahow@VEAHOW-AMADEUS:/usr/local/oecore-x86_64$ ls
environment-setup-armv7a-vfp-neon-oe-linux-gnueabi sysroots/
site-config-armv7a-vfp-neon-oe-linux-gnueabi version-armv7a-vfp-neon-oe-linux-gnueabi
进入oecore-x86_64文件夹我们发现交叉编译链提供了环境变量的相关配置指令,这时候只需要使用该句就可以生效:
# 相对路径下
source environment-setup-armv7a-vfp-neon-oe-linux-gnueabi
# 绝对路径下
source /usr/local/oecore-x86_64/environment-setup-armv7a-vfp-neon-oe-linux-gnueabi
这时候我们就能够得到这一编译器的详细版本信息:
veahow@VEAHOW-AMADEUS:~$ arm-oe-linux-gnueabi-gcc -v
Using built-in specs.
COLLECT_GCC=./arm-oe-linux-gcc
COLLECT_LTO_WRAPPER=/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/libexec/arm-oe-linux-gnueabi/gcc/arm-oe-linux-gnueabi/4.9.3/lto-wrapper
Target: arm-oe-linux-gnueabi
Configured with: ...(此处省略)
Thread model: posix
gcc version 4.9.3 (GCC)
但是当WSL终端关闭后,新打开的WSL终端使用arm-oe-linux-gcc -v
指令时就会又提示找不到命令了,这时我们就需要在~/.bashrc
文件末尾加上一行前面的source /usr/local/oecore-x86_64/environment-setup-armv7a-vfp-neon-oe-linux-gnueabi
生效指令。这样,每次我们打开WSL终端的时候,都会去配置这一环境变量。
3.3 交叉编译程序
我们直接来交叉编译一个简单的程序:
//test.c
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello world!\n");
return 0;
}
使用编译命令arm-oe-linux-gnueabi-gcc test.c -o test.out
,没想到却直接报错:
veahow@VEAHOW-AMADEUS:/mnt/d/Project$ arm-oe-linux-gnueabi-gcc test.c -o test.out
test.c:1:19: fatal error: stdio.h: No such file or directory
#include <stdio.h>
^
compilation terminated.
这里直接提示没有找到头文件stdio.h
,这是因为默认配置是在/usr/include/
中来寻找文件的,经过网上资料查阅,可以使用--sysroot
选项进行指定。
arm-oe-linux-gnueabi-gcc --sysroot=/usr/local/oecore-x86_64/sysroots/armv7a-vfp-ne
on-oe-linux-gnueabi/ test.c -o test.out
编译成功可以使用file
命令来查看文件的状态:
veahow@VEAHOW-AMADEUS:/mnt/d/Project$ file test.out
test.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=d982823a4dc093d3cddfef4ab15fe25236a0de01, not stripped
4 遇到的问题
4.1 路径依赖
原本自己并不想将交叉编译链安装在/usr/local/
目录下,而是想直接存放在硬盘某个专门的软件包目录里,不依赖WSL,例如放在/mnt/d/Software
文件夹下,也就是Windows下D盘的Software文件夹,结果就出现了无法运行交叉编译链的问题,直接进入到命令目录下,使用如下命令也无法运行:
./arm-oe-linux-gnueabi-gcc -v
无法运行 -bash: ./arm-oe-linux-gnueabi-gcc: No such file or directory
实际上自己就在这个命令存放的目录下,这样都无法运行让我十分疑惑,查阅资料有的说是64位操作系统无法运行32位的指令,但是供应商提供的软件包都很明显是支持64位系统运行的,这让我陷入了配置怪圈。最后使用file
命令查看,发现是依赖于特定路径下的某个动态库导致实际运行时找不到而报错。
file arm-oe-linux-gcc
arm-oe-linux-gcc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/lib/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=c607472f349b110298ad9907d7039dd05d914196, stripped
根据该句interpreter /usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/lib/ld-linux-x86-64.so.2
,我们可以推断这个交叉编译链在生成的时候就指定了要依赖这个路径/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/lib/
下的动态库ld-linux-x86-64.so.2
,所以只能乖乖按照供应商的要求解压到/usr/local
下。实际在部署程序到板子上的时候,可能也会比较容易遇见这种问题。
4.2 直接编译代码工程提示popd: not found
这个和Ubuntu的特性有关系,这里我使用的是Ubuntu 20.04 LTS,属于高版本的Ubuntu,其默认的shell就是dash。可以使用ls -l /bin/sh
查看sh链接的是何种shell程序,使用如下命令即可解决:
sudo ln -fs /bin/bash /bin/sh
有些shell脚本因为考虑到这个因素,经常会在文件头部加上#!/bin/bash
来强制指定shell使用bash命令。
5 参考文章
- 比较 WSL 1 和 WSL 2 | Microsoft Docs
- gcc - cross compilation for ARM: error no such file or directory - Ask Ubuntu
- 解决Linux程序编译链接动态库版本的相关问题Linux脚本之家 (jb51.net)
- gcc 运行指定动态库的三种方法__kerneler的博客-CSDN博客_gcc 指定动态库
- gcc - Compiling problems: cannot find crt1.o - Stack Overflow
- 如何更改GCC的crti.o默认搜索目录? - Thinbug
- 交叉编译遇到bin/ld: cannot find crt1.o: No such file or directory问题解决_fanchenxinok的专栏-CSDN博客
- gcc -l参数和-L参数 - 郭振斌 - 博客园 (cnblogs.com)
- 如何配置gcc在特定位置搜索crt1.o和其他libc文件? - 技术翻译 (jishufanyi.cn)
网友评论