Search code examples
linuxmakefile

makefile with .s files beside .c files


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)

Solution

  • 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:

    • I don't think the wildcard function will pick up any file names in this way. It only looks in the current directory, and doesn't use VPATH to search in others.
    • You use gcc with the objects as inputs. This way it will (try to) create an executable.
    • You have no rules to create the object files. This may be fine if you rely on 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).
    • You have defined 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 $<