3
votes

I have a Makefile which includes makefiles from sub-directories. However, what I want is to include these "sub"-makefiles on base of a selected target.

Background is, that the sub-makefiles define different object files and depending on these object files the target executable should be created.

Assuming sub-makefile1 sets the variable

OBJECTS := foo.o foo1.o

sub-makefile2 sets

OBJECTS := bar.o bar1.o

And the generic rule would be:

lib/%.so: $(OBJECTS)
    link $^ -o $@

The targets are (for example):

foo: lib/foo.so
bar: lib/bar.so

whereas target foo should include the foo makefile, target bar the bar-makefile.

Any idea how to handle this situation?

Thanks, Christian

2

2 Answers

3
votes

Beta has mentioned the $(MAKECMDGOALS), but not described it:

ifeq ($(MAKECMDGOALS),foo)
include sub-makefile1
endif
ifeq ($(MAKECMDGOALS),bar)
include sub-makefile2
endif

# Rest of Makefile follows...

This isn't such a great idea, as it will only work when make is called interactively. You can hack around this by making rules for foo and bar that recursively invoke make:

ifeq ($(MAKECMDGOALS),foo)
include sub-makefile1
foo: # ...
    # Normal commands to build foo
else
foo:
    $(MAKE) $<
endif

ifeq ($(MAKECMDGOALS),bar)
include sub-makefile2
bar: # ...
    # Normal commands to build bar
else
bar:
    $(MAKE) $<
endif
2
votes

The specific thing you're asking for -- conditional inclusion -- is difficult in Make. It can be done, but it's not elegant.

There are several ways to get the effect you want. You could use a conditional on MAKECMDGOALS. You could could have your makefile invoke a second makefile, and pass it the name of the subdirectory to use. But (without knowing more about the situation) I think this way is the tidiest:

include sub-makefile1
FOO_OBJECTS := $(OBJECTS)

include sub-makefile2
BAR_OBJECTS := $(OBJECTS)

lib/%.so:
    link $^ -o $@

lib/foo.so: $(FOO_OBJECTS)

lib/bar.so: $(BAR_OBJECTS)

foo bar : % : lib/%.so

(You could be clever with variable names like foo_OBJECTS to save a line or two, but I advise against that.)