交叉编译介绍以及openssl如何交叉编译_openssl交叉编译
1 交叉编译定义
- 交叉编译是指在一种计算机平台(如x86架构的PC)上生成另一种平台(如ARM架构的嵌入式设备)可执行代码的过程。其核心价值在于提升开发效率,允许开发者使用高性能主机为资源受限的目标设备编译程序。
2 交叉编译工具链的组成
- 进行交叉编译需要使用交叉编译工具链。交叉编译工具链是一个综合开发环境,包含以下关键组件:
- 编译器:将源代码编译为目标平台的机器码,如gcc/g++。
- 链接器:将多个目标文件与库文件链接为可执行文件,如ld。
- 库工具:管理静态库、符号表等,如ar、nm。
- 调试与分析工具:查看ELF文件结构、反汇编等,如objdump、readelf。
3 常用交叉编译工具链
- Linaro Toolchain
- 由 Linaro 组织提供的官方工具链,支持多种 ARM 架构,包括 AArch32 和 AArch64。
- 进入下载页面后点击 GNU Toolchain Integration Builds
- GNU Arm Embedded Toolchain
- 由 ARM 公司维护的开源工具链。支持多种 ARM 架构,包括 Cortex-M 和 Cortex-A 系列。
4 Linaro编译工具链使用
-
进入下载页面后点击 GNU Toolchain Integration Builds
-
选择编译器版本
-
选择编译工具链。
aarch64-linux-gnu
主要用于ARM 64位平台,如Cortex-A72。arm-linux-geueabihf
主要用于ARM 32位平台,如Cortex-A9。
-
以aarch64-linux-gnu为例,下载 gcc-linaro-12.2.1-2022.12-x86_64_aarch64-linux-gnu.tar.xz
-
下载后执行
tar -xvf gcc-linaro-12.2.1-2022.12-x86_64_aarch64-linux-gnu.tar.xz
解压。 -
解压成功后,进入 gcc-linaro-12.2.1-2022.12-x86_64_aarch64-linux-gnu/bin 目录,可以看到所有工具链。
-
直接使用交叉编译工具gcc编译一个可执行程序,
./aarch64-linux-gnu-gcc main.cpp -o res
。 -
可以看到,编译的可执行程序为ARM架构。
4.1 OpenSSL交叉编译
-
先设置下环境变量,打开/etc/profile文件,在末尾添加
export PATH=$PATH:/root/gcc-linaro-12.2.1-2022.12-x86_64_aarch64-linux-gnu/bin
。执行source /etc/profile
使配置生效。 -
下载OpenSSL源码后解码,执行以下命令
./config no-asm --prefix=${PWD}/_install_arm --cross-compile-prefix=aarch64-linux-gnu-
-
--cross-compile-prefix
参数用于指定交叉编译前缀。 -
执行成功会有以下打印
-
然后执行
make -j4
进行编译。可能会有以下报错 -
打开Makefile文件,删除文件中的
-m64
。重新执行make -j4
进行编译。 -
编译成功后,执行
make install
进行安装。 -
安装成功后,进到_install_arm目录下,有编译好的库和可执行程序,可以看到为ARM架构的可执行程序和库。
4.2 手动指定编译器
- 大部分开源项目都支持交叉编译,如果不支持,需要修改下CMakeLists.txt文件,手动指定编译器。
- 以下面这个工程为例,目录结构如下
-
├── build ├── CMakeLists.txt ├── README.md └── src ├── socketclient.cpp └── socketserver.cpp
-
- CMakeLists.txt文件内容
-
cmake_minimum_required (VERSION 3.5) project(sockettest) # 设置目标系统名 set(CMAKE_SYSTEM_NAME Linux) # 设置目标系统处理器名 set(CMAKE_SYSTEM_PROCESSOR arm) set(SRC_SERVER_LIST ${PROJECT_SOURCE_DIR}/src/socketserver.cpp) set(SRC_CLIENT_LIST ${PROJECT_SOURCE_DIR}/src/socketclient.cpp) # 指定gcc编译工具-如果未设置环境变量,这里指定绝对路径 set(CMAKE_C_COMPILER \"aarch64-linux-gnu-gcc\") # 指定g++编译工具 set(CMAKE_CXX_COMPILER \"aarch64-linux-gnu-g++\") ADD_EXECUTABLE(socketServer ${SRC_SERVER_LIST}) if(UNIX) target_link_libraries(socketServer -lpthread) endif(UNIX) ADD_EXECUTABLE(socketClient ${SRC_CLIENT_LIST})
-
- 然后在build目录下执行
cmake ..
构建工程,执行make
编译工程。 - 编译出来的程序为ARM架构
5 GNU Arm Embedded编译工具链使用
- 这里包比较多
- 以
arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
为例,说下包名的含义。arm-gnu-toolchain
:arm
表示是针对ARM 架构的工具链,gnu-toolchain
表示这是一个基于 GNU 工具链的发行版。14.2.rel1
:版本信息。x86_64
:表示该工具链是在 x86_64 架构的主机上构建的。aarch64-none-linux-gnu
:aarch64
表示目标架构为AArch64
,none
表示没有特定的供应商,linux
表示目标操作系统是 Linux,gnu
表示使用 GNU 工具链和标准的 GNU EABI。
- 在Windows系统下的Ubuntu虚拟机中,编译ARM架构64位的目标程序,就可以使用这个包。
- x86_64 架构上的主机区别如下
-
# 用于ARM 32位系统,无操作系统的裸机。eabi表示嵌入式应用二进制接口 arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz # 用于ARM 32位系统,有操作系统的机器。gnueabihf表示Linux 系统下的硬浮点优化。 arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz # 用于ARM 64位系统的裸机 arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-elf.tar.xz # 用于ARM 64位系统,有操作系统的机器。字节序为小端。 arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz # 用于ARM 64位系统,有操作系统的机器。字节序为大端。 arm-gnu-toolchain-14.2.rel1-x86_64-aarch64_be-none-linux-gnu.tar.xz
-
5.1 OpenSSL交叉编译
- 解压编译工具链包后,同样设置环境变量,
export PATH=$PATH:/root/arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-linux-gnu/bin
。 - 在OpenSSL源码目录下执行以下命令
./config no-asm --prefix=${PWD}/_install_arm --cross-compile-prefix=aarch64-none-linux-gnu-
- 步骤和上文提到的编译步骤一样,这里就不再介绍了。
- 编译完成,可以看到为目标文件ARM架构