Reputation: 893
I'm using a Makefile to compile C code with LLVM (clang) in order to generate LLVM IR and assembly for an ARM Cortex-M3. The compilation flow is:
%.ll: $(SRC_C)
C code --> LLVM IR%.bc: $(SRC_LL)
LLVM IR --> LLVM binary%.s: $(SRC_BC)
LLVM binary --> ARM assembly%.s.o: $(SRC_S)
ARM assembly --> object filesall
Linking of object files with main.o and stm32.ld --> ELF fileThe LLVM IR files and the ARM assembly files should not be deleted, due to this I added this line: .SECONDARY: $(SRC_LL) $(SRC_S)
Here is the 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: $(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)
Here are my files:
crc_function.c
crc_function.h
example_code.c
main.c
stm32.ld
It compiles without errors:
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
However I can't call make clean
or make all
after a successful compilation, it gives me the following output:
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
The Makefile tries to compile itself and I can not figure out why?
Solution
Thanks for the quick response. Here is the solution to my problem:
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)
Upvotes: 4
Views: 302
Reputation: 22395
You need to look at the .PHONY
directive. clean is not special and make will examine whether the file clean exists.
Also, your rules need to change as there is some implicit rule for Makefile.s which is matching 'Makefile.bc -> Makefile.s'. You can look at 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. For instance, if you have another way to generate a '.s' file as source, this rule set might become confusing. For the '.s' rule this would be,
$(SRC_BC): %.s: %.bc
llc $(LLCFLAGS) $< -o $@
Now, only files in $(SRC_BC)
will have this rule applied and no implicit 'Makefile.s' will attempt to use it. You can also have other rule that will generate assembler and only the input variable will specify the set (not a global matching; some of makes implicit rules will have global matches).
Upvotes: 2