Makefile 想自己编译

Makefile wants to compile itself

我正在使用 Makefile 使用 LLVM (clang) 编译 C 代码,以便为 ARM Cortex-M3 生成 LLVM IR 和汇编。编译流程为:

  1. %.ll: $(SRC_C) C 代码 --> LLVM IR
  2. %.bc: $(SRC_LL) LLVM IR --> LLVM 二进制文件
  3. %.s: $(SRC_BC) LLVM 二进制 --> ARM 汇编
  4. %.s.o: $(SRC_S) ARM 程序集 --> 目标文件
  5. all 目标文件与 main.o 和 stm32.ld 的链接 --> ELF 文件

不应删除 LLVM IR 文件和 ARM 汇编文件,因此我添加了这一行:.SECONDARY: $(SRC_LL) $(SRC_S)

这是生成文件:

CFLAGS = -I./ -c -O0 -gdwarf-3 -mcpu=cortex-m3 --target=armv7m-none-eabi
LFLAGS = -Tstm32.ld -nostartfiles
LLCFLAGS =  -O0 -mtriple=arm-none-eabi -march=thumb -mattr=thumb2 -mcpu=cortex-m3 -float-abi=soft -thread-model=single -filetype=asm
CC = clang 
LD = arm-none-eabi-ld

TARGET = example_code.elf

SRC_C = example_code.c crc_function.c
SRC_S = $(SRC_C:.c=.s)
SRC_LL = $(SRC_C:.c=.ll)
SRC_BC = $(SRC_C:.c=.bc)
SRC_S = $(SRC_C:.c=.s)
SRC_SO = $(SRC_C:.c=.s.o)

.SECONDARY: $(SRC_LL) $(SRC_S)

all: $(SRC_SO) main.o
    $(LD) $(LFLAGS) -o $(TARGET) main.o $(SRC_SO)

%.ll: $(SRC_C)
    clang -O0 -emit-llvm -S -c $*.c -o $*.ll

%.bc: $(SRC_LL)
    llvm-as $*.ll -o $*.bc

%.s: $(SRC_BC)
    llc $(LLCFLAGS) $*.bc -o $*.s

%.s.o: $(SRC_S)
    $(CC) $(CFLAGS) -o $*.s.o -c $*.s

main.o: main.c
    $(CC) $(CFLAGS) -o main.o main.c

clean:
    -rm $(SRC_S)
    -rm $(SRC_LL)
    -rm $(SRC_BC)
    -rm $(SRC_S)
    -rm $(SRC_SO)
    -rm main.o
    -rm $(TARGET)

这是我的文件:

crc_function.c
crc_function.h
example_code.c
main.c
stm32.ld

编译无误:

clang -O0 -emit-llvm -S -c example_code.c -o example_code.ll
clang -O0 -emit-llvm -S -c crc_function.c -o crc_function.ll
llvm-as example_code.ll -o example_code.bc
llvm-as crc_function.ll -o crc_function.bc
llc -O0 -mtriple=arm-none-eabi -march=thumb -mattr=thumb2 -mcpu=cortex-m3 -float-abi=soft -thread-model=single -filetype=asm example_code.bc -o example_code.s
llc -O0 -mtriple=arm-none-eabi -march=thumb -mattr=thumb2 -mcpu=cortex-m3 -float-abi=soft -thread-model=single -filetype=asm crc_function.bc -o crc_function.s
clang  -I./ -c -O0 -gdwarf-3 -mcpu=cortex-m3 --target=armv7m-none-eabi -o example_code.s.o -c example_code.s
clang  -I./ -c -O0 -gdwarf-3 -mcpu=cortex-m3 --target=armv7m-none-eabi -o crc_function.s.o -c crc_function.s
clang  -I./ -c -O0 -gdwarf-3 -mcpu=cortex-m3 --target=armv7m-none-eabi -o main.o main.c
arm-none-eabi-ld -Tstm32.ld -nostartfiles -o example_code.elf main.o example_code.s.o crc_function.s.o
rm example_code.bc crc_function.bc

但是在成功编译后我不能调用make cleanmake all,它给我以下输出:

llvm-as example_code.ll -o example_code.bc
llvm-as crc_function.ll -o crc_function.bc
llc -O0 -mtriple=arm-none-eabi -march=thumb -mattr=thumb2 -mcpu=cortex-m3 -float-abi=soft -thread-model=single -filetype=asm Makefile.bc -o Makefile.s
llc: Makefile.bc: error: Could not open input file: No such file or directory
make: *** [Makefile.s] Error 1
rm example_code.bc crc_function.bc

Makefile 尝试自行编译,我不明白为什么?

解决方案

感谢您的快速回复。这是我的问题的解决方案:

CFLAGS = -I./ -c -O0 -gdwarf-3 -mcpu=cortex-m3 --target=armv7m-none-eabi
LFLAGS = -Tstm32.ld -nostartfiles
LLCFLAGS =  -O0 -mtriple=arm-none-eabi -march=thumb -mattr=thumb2 -mcpu=cortex-m3 -float-abi=soft -thread-model=single -filetype=asm
CC = clang 
LD = arm-none-eabi-ld

TARGET = example_code.elf

SRC_C = example_code.c crc_function.c
SRC_S = $(SRC_C:.c=.s)
SRC_LL = $(SRC_C:.c=.ll)
SRC_BC = $(SRC_C:.c=.bc)
SRC_S = $(SRC_C:.c=.s)
SRC_SO = $(SRC_C:.c=.s.o)

.SECONDARY: $(SRC_LL) $(SRC_S)

all: $(TARGET)

$(TARGET): $(SRC_SO) main.o
    $(LD) $(LFLAGS) -o $(TARGET) main.o $(SRC_SO)

$(SRC_LL): %.ll: %.c
    clang -O0 -emit-llvm -S -c $< -o $@

$(SRC_BC): %.bc: %.ll
    llvm-as $*.ll -o $*.bc

$(SRC_S): %.s: %.bc
    llc $(LLCFLAGS)  $< -o $@

$(SRC_SO): %.s.o: %.s
    $(CC) $(CFLAGS) -o $@ -c $<

main.o: main.c
    $(CC) $(CFLAGS) -o main.o main.c

.PHONY: clean
clean:
    -rm $(SRC_S)
    -rm $(SRC_LL)
    -rm $(SRC_BC)
    -rm $(SRC_S)
    -rm $(SRC_SO)
    -rm main.o
    -rm $(TARGET)

您需要查看 .PHONY 指令。 clean 并不特殊,make 将检查文件 clean 是否存在。

此外,您的规则需要更改,因为 Makefile.s 有一些与 'Makefile.bc -> Makefile.s' 匹配的隐式规则。你可以看看Disable make builtin rules and variables from inside the make file for ways to disable all built-in rules. Or you can use static pattern rules。例如,如果您有另一种方法来生成“.s”文件作为源,则此规则集可能会变得混乱。对于“.s”规则,这将是,

$(SRC_BC): %.s: %.bc
    llc $(LLCFLAGS)  $< -o $@

现在,只有 $(SRC_BC) 中的文件会应用此规则,没有隐含的 'Makefile.s' 会尝试使用它。您还可以有其他规则将生成汇编程序,并且只有输入变量将指定集合(不是全局匹配;一些 make 隐式规则将具有全局匹配)。