0
votes

I know this has been asked a lot, I've looked at a couple of responses but can't figure out what's wrong. I'm trying to store all my object files in a build directory. In the root folder I have my Makefile, and the following directories: include, bin, build, src, and rsrc. I want the object files stored in the build directory, and executables stored in bin. Here is my Makefile.

CFLAGS = -Wall -Werror
DIRS = -I $(IDIR) -I $(SRCDIR) -I $(ODIR)

IDIR = include
SRCDIR = src
ODIR = build


DEPS = include/map_reduce.h include/const.h

BINS = mapreduce

all: $(BINS)

_OBJ = map_reduce.o main.o
OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))

$(ODIR)/%.o: %.c $(DEPS)
    gcc -c -o $@ $< $(CFLAGS)

mapreduce: $(OBJ)
    gcc $(CFLAGS) $(DIRS) $^ -o $@ 


clean:
    rm -f *.o $(BINS)

I currently don't have a rule for storing executables in the bin folder, but I figure if I can understand how to store the object files in build then that part should not be difficult.

I'm getting the error "No rule to make target build/map_reduce.o needed by mapreduce"

Any insight to help me understand what's going on here would be greatly appreciated!

1
Which make are you using?user58697
first, place the macro definitions in the order they are used. Second, when macro definitions will not change use := not =. Third, variable names (including macro names) that begin with _ followed by a capital letter and begin with __ are reserved for the system, The user should not be polluting the system name space with names like _OBJuser3629249
@user3629249, it's clear he is using gmake (gnu make) as % suffix notation is an extension of it. What I don't have for clear is if it's possible to add more dependencies (as he does in $(ODIR)/%.o: %.c $(DEPS)) or he has to make the dependencies not templated in a different rule.Luis Colorado

1 Answers

2
votes

Consider this rule:

$(ODIR)/%.o: %.c $(DEPS)
    gcc -c -o $@ $< $(CFLAGS)

It is a pattern rule (which is a feature specific to GNU make) describing how to build a file whose name has the form $(ODIR)/%.o, based on a file of form %.c and the various files listed in variable $(DEPS).

Supposing your files are arranged as you describe, however, and that you run make with the directory containing the Makefile as the initial working directory, that rule never applies, even though one of the intermediate targets that needs to be built indeed does match the target pattern in that rule. That's because the dependencies expressed by the rule do not all exist, and make can't determine any way to build the missing one.

The problem is that the dependencies you want live in subdirectories, but the rule is written to expect the .c file to be present directly in the working directory. You want something more like this:

$(ODIR)/%.o: $(SRCDIR)/%.c $(DEPS)
    gcc -c -o $@ $(DIRS) $(CFLAGS) $<