Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a variable list as a target in a Makefile?

Suppose I am working on a makefile and I have the following variable declaration at the top:

FILES = file1.cpp file2.cpp file3.cpp 

Now suppose I want to compile each of those with a special command without specifying each target like this:

file1.o : file1.cpp     custom_command file1.cpp file2.o : file2.cpp     custom_command file2.cpp file3.o : file3.cpp     custom_command file3.cpp 

Is there a better way to do this using the $(FILES) variable I declared above?

Something like:

$(FILES:.cpp=.o) : $(FILES)     custom_command $(FILES) 

...only it needs to do this for each file in the $(FILES) variable.

like image 587
Nathan Osman Avatar asked Dec 01 '10 01:12

Nathan Osman


People also ask

What is $@ in makefile?

$@ is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.

Can makefile target be a directory?

Yes, a Makefile can have a directory as target. Your problem could be that the cd doesn't do what you want: it does cd and the git clone is carried out in the original directory (the one you cd ed from, not the one you cd ed to). This is because for every command in the Makefile an extra shell is created.


2 Answers

Yes. There are what are known as pattern rules. An example is the easiest to understand:

%.o: %.cpp        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ 

(remember that Makefiles require tabs). This rule describes how to make an object file from a cpp file.

If you do not want such a broad rule, you can use what are called static patterns:

objects = file1.o file2.o file3.o  all: $(objects)  $(objects): %.o: %.cpp         $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ 

Here's the section on static pattern rules and pattern rules in the GNU Make manual.

like image 172
Chris Avatar answered Oct 01 '22 03:10

Chris


You can do that, as per the following:

SRCS=a.c b.c OBJS=$(SRCS:.c=.o)  $(OBJS): $(SRCS)         cc -c -o a.o a.c         cc -c -o b.o b.c 

but you have to remember that the dependencies are complete - it assumes that a.o depends on b.c as well which is probably not the case.

What you're probably after is a single rule on how to turn one file type into another:

SRCS=a.c b.c OBJS=$(SRCS:.c=.o)  all: $(OBJS)  .c.o:         gcc -c -o $@ $< 

.c.o is such a rule which states what commands to run to turn a .c file into a .o file. In the actual command, $@ is replaced with the specific target and $< is replaced with the name of the first prerequisite.

There are many other automatic variables you can use, look them up with info make or look for a good book on make if you don't have the info stuff available.

like image 28
paxdiablo Avatar answered Oct 01 '22 04:10

paxdiablo