arge
arge

Reputation: 635

Make: build different applications from one global Makefile

I'm currently facing following problem:

How can I create one global Makefile to build different applications(maybe using the same or different libraries) from my source tree? At the moment I have only one application and all what I do is:

include $(ROOT)/SETUP.MAK

SUBDIRS = \
        lib1 \
        lib2 \
        app1

include $(ROOT)/RULES.MAK

The application is built as it should be. But now I'm going to have more applications and maybe additional libraries. I don't want to create a seperate Makefile for every single application, because the libraries/code base are the same for the different applications. This is what I tried:

include $(ROOT)/SETUP.MAK

ifeq ($(strip $(MAKECMDGOALS)),proj1)
SUBDIRS = \
        lib1 \
        lib2 \
        app1
endif

ifeq ($(strip $(MAKECMDGOALS)),proj2)
SUBDIRS = \
        lib1 \
        lib2 \
        lib3 \
        app2
endif

.PHONY: proj1
proj1: $(SUBDIRS)

.PHONY: proj2
proj2: $(SUBDIRS)

include $(ROOT)/RULES.MAK

But the problem is make enters the first directory which is here "lib1" and tries to build "lib1", but there is no rule for "proj1" in "lib1". How is this done correctly? I invoke make at the command line with "make proj1".

Note: the make rule for SUBDIRS is in the file RULES.MAK

EDIT 1: Here is the rule for SUBDIRS:

# entering dir c; calculating deps; leaving dir c; entering dir c; making blah; leaving dir c
$(SUBDIRS) :
# call as make NOT_RECURSIVE=1 to avoid recursion
ifndef NOT_RECURSIVE
ifneq ($(MAKEFILE_DIR),./) # some makefile path given
    $(VERBOSE) $(MKDIR) $@
ifneq ($(call isabspath, $(MAKEFILE_DIR)),) # absolute makefile path
    @$(MAKE) -C $@ -f $(MAKEFILE_DIR)$@/$(MAKEFILE_NOTDIR) $(MAKECMDGOALS)
else # relative makefile path
    @$(MAKE) -C $@ -f ../$(MAKEFILE_DIR)$@/$(MAKEFILE_NOTDIR) $(MAKECMDGOALS)
endif
else # no makefile path given
    @$(MAKE) -C $@ $(MAKECMDGOALS)
endif
endif

Upvotes: 1

Views: 1650

Answers (2)

Beta
Beta

Reputation: 99134

You're using Make in a very un-Make-like way, and causing yourself a lot of unnecessary trouble.

Look at lib1. Presently you use a rule that works out to

lib1:
    $(MAKE) -C lib1 proj1

(We'll assume the "no makefile path given" mode for now.) I presume that the files in lib1/ add up to a library, and that that library does not have to be built with a specific project in mind. So there's no need to pass "proj1" to the Make process running in lib1/. And Make doesn't require an explicit target; if invoked without a target, Make will try to build the default target, which is (usually) the first target in the makefile, which in this case should be the library (lib1/lib1.a or something). So we can simplify the rule:

lib1:
    @$(MAKE) -C lib1

Or better:

lib1:
    @$(MAKE) -C $@

In fact, we can generalize this to all subdirectories that we use the same way:

lib1 lib2 lib3 app1 app2:
    @$(MAKE) -C $@

If we use "SUBDIRS" to mean all subdirs we treat this way, and spell out the proj prereqs, the global makefile gets a lot simpler:

SUBDIRS = lib1 lib2 lib3 app1 app2

.PHONY: proj1
proj1: lib1 lib2 app1

.PHONY: proj2
proj2: lib1 lib2 lib3 app2

Further improvements are possible, but this answer is getting long. (As for the "makefile path given" mode, you can simplify that a good deal too, and get rid of much or all of the branching, but it seems to be entangled with parameters set in SETUP.MAK, and maybe details of your OS.) So maybe it's best to leave them for another day.

Upvotes: 1

Marcassin
Marcassin

Reputation: 1405

If you call make proj1, make will enter in this condition clause :

ifeq ($(strip $(MAKECMDGOALS)),proj1)
SUBDIRS = \
        lib1 \
        lib2 \
        app1
endif

so SUBDIRS is defined as "lib1 lib2 app1". Don't know the content of SETUP.MAK but in case where no makefile path is given make enter in the last if clause :

else # no makefile path given
@$(MAKE) -C $@ $(MAKECMDGOALS)

make interpret this command by : make -C lib1 proj1 Your Makefile hasn't any proj1 rule. You should create a generic all rule in lib1/Makefile creating your lib (.a / .so) from lib1/Makefile, project's name has not to be specified.

Try with

else # no makefile path given
@$(MAKE) -C $@ 

(or remove others $(MAKECMDGOALS) in your IFs clauses)

Upvotes: 1

Related Questions