Search code examples
makefilegnu-makesdcc

Performing an action over each source file with make


I have created a Makefile like this

CC = sdcc
SRCS = $(PNAME).c\
    ../../src/gpio.c
    ../../src/timers.c
    ../../src/i2c.c
$HDRS = -I../../headers

all:
    mkdir -p ./output
    $(CC) $(SRCS) -lstm8 -mstm8 $(HDRS)

The problem is, sdcc can only compile one source at a time. So I need to perform something like a foreach on each source I have defined in SRCS variable. How to do this in gnu-make?


Solution

  • According to the docs, you must compile the files other than the one containing main() separately, to produce .rel files, then include those in the compilation command for the main file. There are several variations on how you could do that. The following avoids features specific to GNU make:

    # We're assuming POSIX conformance
    .POSIX:
    
    CC = sdcc
    
    # In case you ever want a different name for the main source file    
    MAINSRC = $(PMAIN).c
    
    # These are the sources that must be compiled to .rel files:
    EXTRASRCS = \
        ../../src/gpio.c \
        ../../src/timers.c \
        ../../src/i2c.c
    
    # The list of .rel files can be derived from the list of their source files
    RELS = $(EXTRASRCS:.c=.rel)
    
    INCLUDES = -I../../headers
    CFLAGS   = -mstm8 
    LIBS     = -lstm8 
    
    # This just provides the conventional target name "all"; it is optional
    # Note: I assume you set PNAME via some means not exhibited in your original file
    all: $(PNAME)
    
    # How to build the overall program
    $(PNAME): $(MAINSRC) $(RELS)
        $(CC) $(INCLUDES) $(CFLAGS) $(MAINSRC) $(RELS) $(LIBS)
    
    # How to build any .rel file from its corresponding .c file
    # GNU would have you use a pattern rule for this, but that's GNU-specific
    .c.rel:
        $(CC) -c $(INCLUDES) $(CFLAGS) $<
    
    # Suffixes appearing in suffix rules we care about.
    # Necessary because .rel is not one of the standard suffixes.
    .SUFFIXES: .c .rel
    

    If you look carefully, by the way, you will see that the file does not explicitly perform any looping over the source files, or any such thing. It just describes how to build each target, including intermediate targets. make figures out on its own how to combine those rules to go from sources to final program (or to any other target you specify from among those you've taught it to build).