Christopher Clark
Christopher Clark

Reputation: 35

Making multiple libraries automatically with Make

I am trying to create a framework where each folder in the source directory becomes a library. I haven't gotten to the .d dependencies yet, I am stuck trying to get the LLIST (library list) expansion to work.

My makefile is as follows:

# Directories
OBJDIR = obj
TGTDIR = target
INCDIR = include
SRCDIR = src
TSTDIR = tests
LIBDIR = lib
DEPDIR = .d
DIRS = $(OBJDIR) $(TGTDIR) $(INCDIR) $(LIBDIR) $(DEPDIR)

# Target name
TGT = caffeine
LLIST = utils middleware

OBJS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(wildcard $(SRCDIR)/**/*.c))
INCS := $(patsubst $(SRCDIR)/%.h, $(INCDIR)/%.h, $(wildcard $(SRCDIR)/**/*.h))

.PHONY: all
all: $(TGTDIR)/$(TGT)

$(TGTDIR)/$(TGT): $(LIBDIR)/$(LLIST).so
    touch $@

$(LIBDIR)/$(LLIST).so: $(OBJDIR)/$(LLIST)/%.o
    touch $@

$(OBJDIR)/$(LLIST)/%.o: $(SRCDIR)/$(LLIST)/%.c
    touch $@

.PHONY: folders
folders:
    mkdir -p $(DIRS)

.PHONY: clean
clean:
    rm -rf $(DIRS)

The error I'm receiving is. makefile:35: *** mixed implicit and normal rules: deprecated syntax Which is this line. $(OBJDIR)/$(LLIST)/%.o: $(SRCDIR)/$(LLIST)/%.c

To add for clarity the folder structure is as follows.

src
  |-utils
      |-utils.h
      |-utils.c
      |-hash.c
      |-json.c
  |-middleware
      |-middleware.h
      |-middleware.c
      |-req.c
      |-res.c

Upvotes: 1

Views: 418

Answers (1)

MadScientist
MadScientist

Reputation: 100781

Well, what does that line expand to?

OBJDIR = obj
TGTDIR = target
SRCDIR = src
LIBDIR = lib

TGT = caffeine

LLIST = utils middleware

$(TGTDIR)/$(TGT): $(LIBDIR)/$(LLIST).so
        ...

$(LIBDIR)/$(LLIST).so: $(OBJDIR)/$(LLIST)/%.o
        ...

$(OBJDIR)/$(LLIST)/%.o: $(SRCDIR)/$(LLIST)/%.c
        ...

expands this way. which is obviously not right:

target/caffeine: lib/utils middleware.so
        ...

This says that the target target/caffeine has two prerequisites: the first is lib/utils and the second is middleware.so. I expect that's not what you wanted.

lib/utils middleware.so: obj/utils middleware/%.o
        ...

This is not actually a pattern rule: a pattern rule MUST have a pattern matching character (%) in the target. This creates two targets, lib/utils and middleware.so, and each one depends on two prerequisites: obj/utils and the literal file named middleware/%.o (because this is not a pattern rule).

obj/utils middleware/%.o: src/utils middleware/%.c
        ...

This tries to create an explicit rule for the target obj/utils and the pattern rule for the pattern middleware/%.o in the same rule, which is illegal and that's why make complains.

In short, you can't just create a variable with multiple words in it, like LLIST = utils middleware, then plop that variable down into the middle of things and expect make to somehow do some type of iteration over those words and create multiple rules, or whatever. That's not how variable expansion works in a makefile: the variable is simply expanded and the results are parsed exactly as if you'd written the makefile without variables at all.

Upvotes: 3

Related Questions