6
votes

I have a set of .cpp files that I want to compile. These .cpp files are in a hierarchical directory structure. I want the corresponding .o files to all end up in one build folder.

Here's how I get GNU make to enumerate the files...

SRCS = \
    $(wildcard $(CODE)/**/*.cpp) \
    $(wildcard $(CODE)/AlgebraLibraries/**/*.cpp) \
    $(wildcard $(CODE)/Calculator/Environments/**/*.cpp)

BARE_SRCS = $(notdir $(SRCS))
BARE_OBJS = $(BARE_SRCS:.cpp=.o)
OBJS = $(addprefix $(BUILD)/, $(BARE_OBJS))

Having done this, I have no idea how to create the rules that will create the .o files from the .cpp files. Intuitively, what I want to do is the following psuedo-code.

for i=0, N do  # <-- a for-loop!
  $(OBJS)[i]: $(SRCS)[i]   # <-- the rule!
    $(CPP) -c $(SRCS)[i] -o $(OBJS)[i] # <-- the recipe
end

Of course, this is not valid GNU make code, but I trust you understand what it is here that I'm trying to do. The following will not work.

%.o: %.cpp
    $(CPP) -c $< -o $@

This doesn't work, because GNU make is matching up the % signs, assuming that the .o files live along-side the .cpp files.

The alternative to all of this, which I know will work, but will be extremely tedious, is to enumerate all of the rules by-hand as explicit rules. That's retarded! There has to be a better way.

I've been researching GNU make's ability to generate rules, but there appears to be no way to do it without the built-in logic. It would be really nice if I could utilize some flow-control statements to generate the rules that I want to make. Is this asking too much of GNU-make?

In any case, is there a way to do what it is I'm trying to do with GNU make? If so, how?

Thank you for your help!

2

2 Answers

15
votes

This looks like a job for... several advanced Make tricks:

all: $(OBJS)

define ruletemp
$(patsubst %.cpp, $(BUILD)/%.o, $(notdir $(1))): $(1)
    $$(CPP) -c $$< -o $$@
endef

$(foreach src,$(SRCS),$(eval $(call ruletemp, $(src))))
2
votes

If $(BUILD) is constant, you can always just do:

$(BUILD)/%.o: %.cpp
    $(CPP) -c $< -o $@