Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Makefile variable value depending on a target

Tags:

makefile

I am not proficient with makefiles, but am used to simple ones. Right now, I have a task on hand.

I need to compile and link a test application with a different library and different include path based on the given target. If target is TARGET1, then link against LIB1 and include INCLUDEPATH1 during compilation. Similarly, if given target is TARGET2, then compile with INCLUDEPATH2 in CFLAGS and link with LIB2.

%.o: %.c
    @echo [CC]  $< ...
    $(CC) $(CFLAGS) -o $*.o $<

Now I have a rule as above which compiles my test application. Now how can the CFLAGS be changed based on the target.

like image 914
sthustfo Avatar asked Jul 16 '10 03:07

sthustfo


People also ask

How do I override a makefile variable?

There is one way that the makefile can change a variable that you have overridden. This is to use the override directive, which is a line that looks like this: ' override variable = value ' (see The override Directive).

What is $@ 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.

What does += mean in makefile?

6.6 Appending More Text to Variables Often it is useful to add more text to the value of a variable already defined. You do this with a line containing ' += ', like this: objects += another.o.


2 Answers

If you are using GNU Make, you can use target-specific variables:

target1: CFLAGS = -IINCLUDEPATH1
target1: LDLIBS = -lLIB1

target2: CFLAGS = -IINCLUDEPATH2
target2: LDLIBS = -lLIB2

all: target1 target2

target1: target1.o misc.o
target2: target2.o

However this doesn't work quite as well as you'd like: if target1 and target2 share some source files, you'll need to arrange for them to each be compiled twice and to differently-named .o files -- which will rather complexify your makefile.

Also, if you type make target1 then -IINCLUDEPATH1 will be propagated to the compilation of misc.c, as desired. However if you type make misc.o it has no way to know that this is eventually destined for target1 and the compilation of misc.c will get no special $CFLAGS value (though it'll get the global one, if there is one).

So this is really only useful in simple cases. But maybe your case is sufficiently simple.

like image 163
John Marshall Avatar answered Sep 20 '22 14:09

John Marshall


I don't think you can alter variable depending on a target. Assume you invoke

make TARGET1 TARGET2

What value would the CFLAGS have then?

In this case, you can use non-pattern rules to distinguish targets.

TARGET1: a.c
    @echo [CC] $< ...
    $(CC) -I INCLUDEPATH1 ...

TARGET2: a.c
    @echo [CC] $< ...
    $(CC) -I INCLUDEPATH2 ...

To decrease repetition, you may also use variables and "functions". Then, you could re-use what would be the body of your pattern rule in different rules.

define compile_cmd
    @echo [CC] $< ...
    $(CC) -I $1 -l$2 $(CFLAGS)
endef

TARGET1: a.c
    $(call compile_cmd,INCLUDEPATH1,LIB1) -o $@ $<

TARGET2: a.c
    $(call compile_cmd,INCLUDEPATH2,LIB2) -o $@ $<

%.o: %.c
    $(call compile_cmd,INCLUDEPATH_DEFAULT,LIB_DEFAULT) -o $@ $<

That would make a nice enough and flexible makefile that suits your needs.

like image 43
P Shved Avatar answered Sep 19 '22 14:09

P Shved