3

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?

Dumbo
  • 13,555
  • 54
  • 184
  • 288
  • Does `sdcc` have an option that makes it compile to an object file, but not try to link that to make a program? I suppose it must do if it cannot handle multiple source files in the same compilation command. For `gcc`, that option is spelled `-c`. – John Bollinger Sep 22 '16 at 17:12
  • If `sdcc` does not accept multiple source files in the same command, then how are you supposed to use it to build a program from multiple sources? Is there a separate linker for its toolchain? Does it rely on an external linker such as GNU `ld`? – John Bollinger Sep 22 '16 at 17:14
  • Is `-mstm8` a compile option or a link option? – John Bollinger Sep 22 '16 at 17:17
  • @JohnBollinger yes -c for compile only, but I am not sure about linking process yet! – Dumbo Sep 22 '16 at 17:35
  • @JohnBollinger yes -mstm8 -lstm8 are the platform to be compiled for – Dumbo Sep 22 '16 at 17:35

2 Answers2

3

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).

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Note that I'm guessing a bit as to what the `-lstm8` option means and therefore where it should go. I don't find either that specific option or options of its general form documented. It *looks* like an option to add a library to the link, but `sdcc` appears to do that differently. – John Bollinger Sep 22 '16 at 17:52
  • Note also that indentation of build rules should be a single , or at least start with one. That's not reflected in the example because it's hard to insert tabs into the HTML form. – John Bollinger Sep 22 '16 at 17:59
  • Thanks a lot for taking the time! the `$(PNAME)` is the name of the source file which contains the `main` function. Does it change the way your answer works? – Dumbo Sep 22 '16 at 18:48
  • @SaeidYazdani, my point about `$(PNAME)` is that you have to assign its value somewhere, and the Makefile I presented follows your example in not doing that. You could specify the value via an environment variable, or if you're using GNU make then via a command-line argument. Or you could just add an assignment to the makefile. – John Bollinger Sep 22 '16 at 22:22
2

Use patsubst. Typically it is something like:

SOURCES := $(wildcard *.c)
OBJECTS := $(patsubst %.c,%.o,${SOURCES})
prog: ${OBJECTS}
        cc $^ -o $@
%.o: %.c
        cc $< -c -o $@
o11c
  • 15,265
  • 4
  • 50
  • 75