您现在的位置是:首页 >技术交流 >LLVM-Clang交叉编译详细教程网站首页技术交流

LLVM-Clang交叉编译详细教程

NueXini 2024-06-17 11:19:03
简介LLVM-Clang交叉编译详细教程

前言

最近自己写了个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_64x86armthumbmips等。
  • 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 ~

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。