文章目录
- 前言
- 对比GCC与Clang
- Clang交叉编译参数选项
- 安装交叉编译器
- 交叉编译生成二进制文件
- Target Arch列表
- Target Triple列表
- 参考文档
- 后话
前言
最近自己写了个C++的小项目,想在Windows编译出其他平台的二进制文件的话,只能交叉编译了,于是就选了LLVM的Clang编译器来使用。
对比GCC与Clang
下面的图我们能看到GCC是根据每个不同指令集动态地编译,而Clang是为每个指令集选择不同的交叉编译器编译
Clang交叉编译参数选项
Clang通过--target=<triple>
驱动器选项动态地选择目标三元组,而为之生成代码。除了三元组,可以用其它的选项以更精细地选择目标:
- 如果不使用
--target=<triple>
这个参数,还可以组合下面这三个参数一起使用 - 选项
-march=<arch>
选择目标的基础架构。<arch>
值的例子,包括ARM的armv4t、armv6、armv7、和armv7f,MIPS的mips32、mips32r2、mips64、和mips64r2。这个选项还单独地选定一个默认的基础CPU,为代码生成器所用。 - 选项
-mcpu=<cpu>
选择具体的CPU。例如,cortex-m3和cortex-a8是ARM具体的CPU,pentium4、athlon64、和corei7-avx2是x86 CPU。每个CPU有一个基础<arch>
值,为目标所定义,并为驱动器所用。 - 选项
-mfloat-abi=<abi>
决定哪种寄存器用于存放浮点值:soft或者hard。如前所述,这决定了是否使用软件浮点数模拟。这还隐含了对调用惯例和其它ABI规范的改变。别名选项-msoft-float
和-mhard-float
也是可用的。注意,如果没有设定此选项,ABI类型会遵从所选CPU的默认类型。
<triple>
格式一般为<arch><sub>-<vendor>-<sys>-<env>
arch
=x86_64
、x86
、arm
、thumb
、mips
等。sub
= 在arm
中,v5
,v6m
,v7a
,v7m
等。vendor
=pc
,apple
,nvidia
,ibm
,等。sys
=none
,linux
,win32
,darwin
,cuda
等。abi
=eabi
,gnu
,android
,macho
,elf
等。
安装交叉编译器
sudo apt-get install gcc-12-arm-linux-gnueabihf g++-12-arm-linux-gnueabihf
交叉编译生成二进制文件
test.cpp
:
#include <iostream>
#int main()
{
std::cout << "hello,world!" << std::endl;
return 0;
}
clang++ --target=arm-linux-gnueabihf -o test test.cpp
Target Arch列表
$ clang -print-targets
Registered Targets:
aarch64 - AArch64 (little endian)
aarch64_32 - AArch64 (little endian ILP32)
aarch64_be - AArch64 (big endian)
arm - ARM
arm64 - ARM64 (little endian)
arm64_32 - ARM64 (little endian ILP32)
armeb - ARM (big endian)
thumb - Thumb
thumbeb - Thumb (big endian)
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
Target Triple列表
enum ArchType {
UnknownArch,
arm, // ARM (little endian): arm, armv.*, xscale
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
aarch64_32, // AArch64 (little endian) ILP32: aarch64_32
mips, // MIPS: mips, mipsallegrex, mipsr6
mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
msp430, // MSP430: msp430
thumbeb, // Thumb (big endian): thumbeb
x86, // X86: i[3-9]86
x86_64, // X86-64: amd64, x86_64
};
enum SubArchType {
NoSubArch,
ARMSubArch_v9_4a,
ARMSubArch_v9_3a,
ARMSubArch_v9_2a,
ARMSubArch_v9_1a,
ARMSubArch_v9,
ARMSubArch_v8_9a,
ARMSubArch_v8_8a,
ARMSubArch_v8_7a,
ARMSubArch_v8_6a,
ARMSubArch_v8_5a,
ARMSubArch_v8_4a,
ARMSubArch_v8_3a,
ARMSubArch_v8_2a,
ARMSubArch_v8_1a,
ARMSubArch_v8,
ARMSubArch_v8r,
ARMSubArch_v8m_baseline,
ARMSubArch_v8m_mainline,
ARMSubArch_v8_1m_mainline,
ARMSubArch_v7,
ARMSubArch_v7em,
ARMSubArch_v7m,
ARMSubArch_v7s,
ARMSubArch_v7k,
ARMSubArch_v7ve,
};
enum VendorType {
UnknownVendor,
Apple,
PC,
SCEI,
Freescale,
IBM,
ImaginationTechnologies,
MipsTechnologies,
NVIDIA,
CSR,
Myriad,
AMD,
Mesa,
SUSE,
OpenEmbedded,
LastVendorType = OpenEmbedded
};
enum OSType {
UnknownOS,
Ananas,
CloudABI,
Darwin,
DragonFly,
FreeBSD,
Fuchsia,
IOS,
KFreeBSD,
Linux,
MacOSX,
Win32,
PS4,
PS5,
ELFIAMCU,
TvOS, // Apple tvOS
WatchOS, // Apple watchOS
};
enum EnvironmentType {
UnknownEnvironment,
GNU,
GNUABIN32,
GNUABI64,
GNUEABI,
GNUEABIHF,
GNUF32,
GNUF64,
GNUSF,
GNUX32,
GNUILP32,
};
enum ObjectFormatType {
UnknownObjectFormat,
COFF,
DXContainer,
ELF,
GOFF,
MachO,
SPIRV,
Wasm,
XCOFF,
};
更多的参数可以在LLVM源码的Triple.h找到
参考文档
https://clang.llvm.org/docs/CrossCompilation.html
https://getting-started-with-llvm-core-libraries-zh-cn.readthedocs.io/zh_CN/latest/ch08.html#id2
https://llvm.org/docs/HowToCrossCompileLLVM.html
后话
交叉编译难度不大,最主要还得是安装编译器,弄清楚各种不同的架构
Enjoy ~