konze
konze

Reputation: 893

Makefile wants to compile itself

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:

  1. %.ll: $(SRC_C) C code --> LLVM IR
  2. %.bc: $(SRC_LL) LLVM IR --> LLVM binary
  3. %.s: $(SRC_BC) LLVM binary --> ARM assembly
  4. %.s.o: $(SRC_S) ARM assembly --> object files
  5. all Linking of object files with main.o and stm32.ld --> ELF file

The 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

Answers (1)

artless-noise-bye-due2AI
artless-noise-bye-due2AI

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

Related Questions