ClangBuiltLinux / continuous-integration

Continuous integration of latest Linux kernel with daily build of Clang & LLVM tools
https://travis-ci.com/ClangBuiltLinux/continuous-integration
Apache License 2.0
44 stars 18 forks source link

fail if LLVM not configured to target certain backend #209

Open nickdesaulniers opened 4 years ago

nickdesaulniers commented 4 years ago

I usually build llvm with:

$ cmake .. -DCMAKE_BUILD_TYPE=Release -G Ninja -DCMAKE_C_COMPILER=/android1/android-master/prebuilts/clang/host/linux-x86/clang-r353983c/bin/clang -DCMAKE_CXX_COMPILER=/android1/android-master/prebuilts/clang/host/linux-x86/clang-r353983c/bin/clang++ -DLLVM_ENABLE_LLD=ON -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TARGETS_TO_BUILD="AArch64;ARM;X86"

which makes testing mipsel locally with driver.sh error in non-sensical ways. It might be a slight improvement for an edge case to test that clang has been configured to target these. Probably don't need to check all of these tools (theoretically you could have some crazy combo of different clang and lld with differing target support).

Not a priority though.

nathanchance commented 4 years ago

While I think that we could add this to this repo, it is probably worth adding to the kernel source directly. Although all distros build clang with all of the backends enabled, more specialized versions like the one that tc-build creates won't. Something like Android's target check maybe?

tpimh commented 4 years ago

It's possible to just grep for specific architecture from llvm-objdump --version for example. Here is the output for the version from LLVM apt repo:

LLVM (http://llvm.org/):
  LLVM version 10.0.0

  Optimized build.
  Default target: x86_64-pc-linux-gnu
  Host CPU: ivybridge

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    amdgcn     - AMD GCN GPUs
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    avr        - Atmel AVR Microcontroller
    bpf        - BPF (host endian)
    bpfeb      - BPF (big endian)
    bpfel      - BPF (little endian)
    hexagon    - Hexagon
    lanai      - Lanai
    mips       - MIPS (32-bit big endian)
    mips64     - MIPS (64-bit big endian)
    mips64el   - MIPS (64-bit little endian)
    mipsel     - MIPS (32-bit little endian)
    msp430     - MSP430 [experimental]
    nvptx      - NVIDIA PTX 32-bit
    nvptx64    - NVIDIA PTX 64-bit
    ppc32      - PowerPC 32
    ppc64      - PowerPC 64
    ppc64le    - PowerPC 64 LE
    r600       - AMD GPUs HD2XXX-HD6XXX
    riscv32    - 32-bit RISC-V
    riscv64    - 64-bit RISC-V
    sparc      - Sparc
    sparcel    - Sparc LE
    sparcv9    - Sparc V9
    systemz    - SystemZ
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    wasm32     - WebAssembly 32-bit
    wasm64     - WebAssembly 64-bit
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64
    xcore      - XCore
nathanchance commented 4 years ago

I don’t think that is any cleaner than just trying to run:

echo | “$@“ -x c -c -o /dev/null - 2>&1 && echo “y”

with a shell script like Android does.

In fact, we could probably use this justification to upstream that Android patch. It would be easy to combine these two checks into one script. I’ll try to prototype something tonight.

nathanchance commented 4 years ago

In fact, we could probably use this justification to upstream that Android patch. It would be easy to combine these two checks into one script. I’ll try to prototype something tonight.

Hmmm, maybe not because I am sure upstream would want a different error message based on what is failing (target not being valid or target being an Android target) and I can't really think of a clean way to do that right now.

I'll still draft up a patch for the original issue soon.

nathanchance commented 4 years ago

Doubling back to low hanging fruit. This works:

diff --git a/Makefile b/Makefile
index 16d8271192d1..84e75d856cd9 100644
--- a/Makefile
+++ b/Makefile
@@ -528,6 +528,9 @@ endif
 ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 ifneq ($(CROSS_COMPILE),)
 CLANG_FLAGS    += --target=$(notdir $(CROSS_COMPILE:%-=%))
+ifneq ($(shell $(srctree)/scripts/clang-target.sh $(CC) $(CLANG_FLAGS)),)
+$(error "$(CC) does not support $(CLANG_FLAGS), please make sure $(CC) has backend support for selected target")
+endif
 GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
 CLANG_FLAGS    += --prefix=$(GCC_TOOLCHAIN_DIR)
 GCC_TOOLCHAIN  := $(realpath $(GCC_TOOLCHAIN_DIR)/..)
diff --git a/scripts/clang-target.sh b/scripts/clang-target.sh
new file mode 100755
index 000000000000..1a2590581339
--- /dev/null
+++ b/scripts/clang-target.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+echo | $@ -c -x c - -o /dev/null >/dev/null 2>&1 || echo n
$ make -j$(nproc) -s ARCH=hexagon CROSS_COMPILE=hexagon-linux-gnu- AR=llvm-ar AS=clang CC=clang HOSTCC=clang HOSTLD=ld.lld HOSTAR=llvm-ar LD=ld.lld NM=llvm-nm OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump OBJSIZE=llvm-size READELF=llvm-readelf STRIP=llvm-strip distclean defconfig
Makefile:532: *** "clang does not support --target=hexagon-linux-gnu, please make sure clang has backend support for selected target".  Stop.
make: *** [Makefile:327: __build_one_by_one] Error 2

$ make -j$(nproc) -s ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- AR=llvm-ar AS=clang CC=clang HOSTCC=clang HOSTLD=ld.lld HOSTAR=llvm-ar LD=ld.lld NM=llvm-nm OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump OBJSIZE=llvm-size READELF=llvm-readelf STRIP=llvm-strip distclean defconfig

Not sure if it is worth adding that to the build system or just making it a part of driver.sh?