Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile Dynamic Rules w/ No GNU-make Pattern

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!

like image 295
user2125275 Avatar asked Mar 01 '13 22:03

user2125275


People also ask

What is makefile GNU?

This file documents the GNU make utility, which determines automatically which pieces of a large program need to be recompiled, and issues the commands to recompile them. This is Edition 0.76, last updated 31 October 2022, of The GNU Make Manual , for GNU make version 4.4.

What does $@ mean in makefile?

The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run.

Can you have multiple rules in a makefile?

There can only be one recipe to be executed for a file. If more than one rule gives a recipe for the same file, make uses the last one given and prints an error message.

What is a GNU Make file?

GNU Make is a tool that helps to generate executable programs from source code and also process other non-source files from the project. Make gets the logic of building the executables and processing other non-source files from a file called a makefile or a Makefile.


2 Answers

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))))
like image 186
Beta Avatar answered Nov 10 '22 10:11

Beta


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

$(BUILD)/%.o: %.cpp
    $(CPP) -c $< -o $@
like image 40
Ponkadoodle Avatar answered Nov 10 '22 10:11

Ponkadoodle