I have a baremetal project which includes .s files beside .c files. How can I write a makefile where I separate the compilation of the .s files from the .c files? The files are located in subfolders (source, include, startup) of a program.
I was going for something like this. Is this good? How can I link the objects into an executable then?
SHELL := /bin/bash
ROOT := $(shell pwd)
VPATH := $(ROOT)/source:/$(ROOT)/startup:$(ROOT)/include
EXE := exe
OBJECTS_GCC := $(patsubst %.c,%.o,$(wildcard *.c))
OBJECTS_AS := $(patsubst %.s,%.o,$(wildcard *.s))
AS := arm-none-eabi-as -mcpu=arm926ej-s -Wall
GCC := arm-none-eabi-gcc -mcpu=arm926ej-s -Wall
LD := arm-none-eabi-ld -T test.ld -o $(EXE)
all: $(EXE)
$(EXE): startups sources
startups: $(OBJECTS_AS)
$(AS) $(OBJECTS_AS)
sources: $(OBJECTS_GCC)
$(GCC) $(OBJECTS_GCC)
I am having a hard time finding any example at all which includes .s files alongside .c files.
Regards.
Here is the latest version of makefile, where header.h isn't found:
SHELL := /bin/bash
ROOT := $(shell pwd)
INC := $(ROOT)/inc
SRC := $(ROOT)/src
STR := $(ROOT)/str
EXE := exe
AS := arm-none-eabi-as -mcpu=arm926ej-s -c -Wall -I $(INC) -I$(SRC) -I $(STR)
GCC := arm-none-eabi-gcc -mcpu=arm926ej-s -c -Wall -I $(INC) -I$(SRC) -I $(STR)
LDSCRIPT := test.ld
LD := arm-none-eabi-ld -T $(LDSCRIPT)
HEADERS := $(notdir $(wildcard $(INC)/*.h))
SOURCES_GCC := $(notdir $(wildcard $(SRC)/*.c))
SOURCES_AS := $(notdir $(wildcard $(STR)/*.s))
OBJECTS_GCC := $(SOURCES_GCC:.c=.o)
OBJECTS_AS := $(SOURCES_AS:.s=.o)
VPATH := $(STR):$(SRC):$(INC)
all : $(EXE)
@echo konec postopka: izvrsljiv program po imenu $(EXE) se nahaja v mapi $(ROOT)
$(EXE) : $(OBJECTS_AS) $(OBJECTS_GCC)
@echo objekti so: $(OBJECTS_AS) $(OBJECTS_GCC)
@echo headerji so: $(HEADERS)
@echo linkanje objektov v izvrsljiv program...
$(LD) -o $@ $^
%.o : %.s %.h
@echo prevajanje ASSEMBLY izvornih datotek...
$(AS) -o $@ $<
%.o : %.c %.h
@echo prevajanje C izvornih datotek...
$(GCC) -o $@ $<
.PHONY : clean
clean :
@echo brisanje objektov
rm *.o
@echo brisanje izvrsljivega programa
rm $(EXE)
Think about what commands you would issue without make
. What steps would you take? Which files do you create first, and how do files depend on the existence of others before they can be made?
Once you have a clear picture of that, write make rules that mimic those commands, but with the inclusion of make variables.
If you have that down, you can then enhance your makefile by using things like implicit rules, automatic variables, and such, but keep it simple at first, until you get a grasp of how make
works.
A couple of points:
make
's built-in implicit or pattern rules, but it won't use the version of gcc you want to use, with it's associated flags. You have to set up some other variables for that to work (like CC
, CFLAGS
, and such).LD
, but never use it. Use it in a recipe to create the executable.I guess you should have something more like this:
all: $(EXE)
$(EXE): $(OBJECTS_AS) $(OBJECTS_GCC)
$(LD) $^
%.o: %.s
$(AS) $<
%.o: %.c
$(GCC) -c $<