Two targets with the same name in a Makefile - makefile

I was wondering what happens if there is 2 targets with the same name in a Makefile:
According to This question, Having 2 targets with the same name throws warnings.
However, i don't understand how this Makefile in openwrt works:
In include/package.mk:
define Build/DefaultTargets
$(if $(QUILT),$(Build/Quilt))
$(if $(USE_SOURCE_DIR)$(USE_GIT_TREE),,$(if $(strip $(PKG_SOURCE_URL)),$(call Download,default)))
$(call Build/Autoclean)
download:
$(foreach hook,$(Hooks/Download),
$(call $(hook))$(sep)
)
Note here the call to Downloadfunction in the 3rd line and the definition of the target download in the 6th line.
By having a look at the definition of the function Download in include/download.mk:
define Download
$(eval $(Download/Defaults))
$(eval $(Download/$(1)))
$(foreach FIELD,URL FILE $(Validate/$(call dl_method,$(URL),$(PROTO))),
ifeq ($($(FIELD)),)
$$(error Download/$(1) is missing the $(FIELD) field.)
endif
)
$(foreach dep,$(DOWNLOAD_RDEP),
$(dep): $(DL_DIR)/$(FILE)
)
download: $(DL_DIR)/$(FILE)
I see that the download target is redefined.
What i know is that using call will expand the function, so how this could work?

If a target is specified without a recipe, it's simply adding a dependency to the target. You're allowed as many of these as you want. So the following is valid:
foo: dep1 dep2
foo: dep3
recipe1
In which case, if dep1, dep2, or dep3 are rebuilt, then recipe1 is run. But this is not:
foo:
recipe1
foo:
recipe2
At this point make wouldn't know which recipe to run, and/or in which order, so Make complains. (note that you can have multiple definitions for pattern rules, in which case make chooses the first one that matches, but that's not allowed with static rules)

Related

How should you use .PHONY in included Makefiles?

Say I have a set of Makefile modules:
# foo.mk
rule1: prereq1
recipe1
and
# bar.mk
rule2: prereq2
recipe2
and a primary Makefile:
# Makefile
include foo.mk
include bar.mk
Should .PHONY: be included in each individual .mk file for the phony targets just in that file, or should there be some acculmulated list that is included only in the primary Makefile?
# foo.mk
TARGETS += rule1
...
# bar.mk
TARGETS += rule2
...
# Makefile
.PHONY: $(TARGETS)
I didn't find anything relevant in the GNU Make docs or similar questions.
The statement
.PHONY: rule1
tells Make that it should not consider "rule1" the name of a file to be built. Suppose you put it in the Makefile. What happens when you run another makefile, either foo.mk or a makefile that includes it?
When you run the rule1 rule, do you want Make to treat it as a PHONY target? If your answer isn't "that depends on which makefile I'm using", then you should have the statement in the makefile that defines the rule.
As with other targets, you can add to .PHONY multiple times cumulatively. So giving each file its own .PHONY is can be a nice way of keeping things compartmentalized.

Re-evaluating GNU make makefile variable

I have inherited a large branched project? that requires a volatile set of .a archives $(LIB_FILES) to be included into link target, located in some directories $(LIB_DIRS). I can write an expression like this:
LIBDEP = $(foreach ldir, $(LIB_DIRS), \
$(filter $(addprefix %/, $(LIB_FILES)), $(wildcard $(ldir)/* )))
The problem is that they might not exist at moment of make's invocation and would be built by invoking $(MAKE) inside of another target's rule, which is a prerequisite to the link step.
The problem is actual list of files that should be created varies on external factors determined at their build steps, that I can't hard-code it properly, without turning makefile into a spaghetti mess and said variable is not re-evaluated at the moment of link command invocation.
I have suspicion that $(eval ) function can be used somehow, but manual is not very forthcoming as well as I didn't found examples of its use in this way.
Toolchain: GCC and binutils, make 3.81
Another solution is to create an explicit dependency of your make script on the output of the step which currently creates the variable $(LIB_FILES). This is what the manual is dealing with in the chapter How makefiles are remade and it aims at the technique which make is best at, namely deriving dependencies from the existence and timestamp of files (instead of variables). The following hopefully depicts your situation with the process of deducing a new set of libraries simulated by the two variables $(LIBS_THIS_TIME) and $(LIB_CONFIG_SET).
LIBS_THIS_TIME = foo.a:baz.a:bar.a
LIB_CONFIG_SET = $(subst :,_,$(LIBS_THIS_TIME))
include libdeps.d
linkstep:
#echo I am linking $^ now
touch $#
libdeps.d: $(LIB_CONFIG_SET)
-rm libdeps.d
$(foreach lib,$(subst :, ,$(LIBS_THIS_TIME)),echo linkstep: $(lib) >> libdeps.d;)
$(LIB_CONFIG_SET):
touch $#
If make finds that libdeps.d is not up to date to your current library configuration it is remade before make executes any other rule, although it is not the first target in the makefile. This way, if your build process creates a new or different set of libraries, libdeps.d would be remade first and only then make would carry on with the other targets in your top makefile, now with the correct dependecy information.
It sometimes happens that you need to invoke make several times in succession. One possibility to do this is to use conditionals:
ifeq ($(STEP),)
all:
<do-first-step>
$(MAKE) STEP=2 $#
else ifeq ($(STEP),2)
all:
<do-second-step>
$(MAKE) STEP=3 $#
else ifeq ($(STEP),3)
all:
<do-third-step>
endif
In each step you can generate new files and have them existing for the next step.

nested defines in makefile

I'm very new to creating makefiles, so this question might be trivial. If I'm using bad coding practices, I would appreciate to be pointed at it.
I am trying to create a generic makefile that creates rules based on input variables. At the end of my posting is a "minimal" example.
I got 2 problems.
In line 35 I instantiate the meta_template. I would expect the variable $(Dirs) to be expanded and then the meta_template to be called with each entry of $(Dirs). But it only expands till the second last, ie. the result of make terminates with:
make: *** No rule to make target 'Dir03Target01Tag01', needed by 'Dir03'. Stop.
In line 21 I want to create a shortcut rule, a rule that prerequisites all tags to a given example.
Eg: Dir01Target02: Dir01Target02Tag04 Dir01Target02Tag05
First I was puzzled that I couldn't use $($$(1)Tags) but had to use $$($$(1)Tags) to access the according Tags. (stored in Target01Tags for example).
Using $(addprefix) does not seem to expand as I expected, ie the result of make Dir01Target01 is:
Create Rule Dir01Target01 with Dir01Target01Tag01 Tag02 Tag03
where I expected it to be:
Create Rule Dir01Target01 with Dir01Target01Tag01 Dir01Target01Tag02 Dir01Target01Tag03
edit: I found the answer to question 2. I had $(addprefix $(1)$$(1),$$($$(1)Tags))alter to $$(addprefix $(1)$$(1),$$($$(1)Tags)). I think it's because this needs to be expanded in 2 runs. So after the first run $(addprefix Dirxx$(1),$($(1)Tags)) remains.
Thanks in advance.
# Targets to compile
Targets = Target01 Target02
# Tags to add to Targets
Target01Tags = Tag01 Tag02 Tag03
Target02Tags = Tag04 Tag05
# Some List (in the actual makefile a list of directories $(wildcard NumeratedDir*))
Dirs = Dir01 Dir02 Dir03
all: $(Dirs)
define meta_template
$(1): $(foreach target,$(Targets),$(foreach tag,$($(target)Tags),$(1)$(target)$(tag)))
define compile_meta
# $(1) 1st argument of meta_compile (<Dirs>xx, eg Dir03)
# $$(1) 1st argument of compile_template (<Targets>, eg Target01)
$(1)$$(1): #$(addprefix $(1)$$(1),$($$(1)Tags))
#echo Create Rule $(1)$$(1) with $(addprefix $(1)$$(1),$$($$(1)Tags)) <---- Line21
endef
$(foreach target,$(Targets),$(eval $(call compile_meta,$(target))))
define compile_template
# $(1) 1st argument of meta_compile (<Dirs>xx, eg Dir03)
# $$(1) 1st argument of compile_template (<Targets>, eg Target01)
# $$(2) 2nd argument of compile_template (<Targets>Tags, eg Tag01)
# create rule using arguments (eg Dir03Target01Tag01)
$(1)$$(1)$$(2):
#echo Create Rule $(1)$$(1)$$(2)
endef
$(foreach target,$(Targets),$(foreach tag,$($(target)Tags),$(eval $(call compile_template,$(target),$(tag))))) <--- Line35
endef
$(foreach prog,$(Dirs),$(eval $(call meta_template,$(prog))))

generating multiple executables from the same sources

To build multiple executables from the same source, I have to translate every source file with different Compiler Switches. For every variant, I have a set of defines to be set. I want to store the resulting object files into different subfolders. I have a variable, keeping all object file from all variants. Now I have problems to define a proper static rule to build the object files from the sources:
SOURCEEXT=.c
ALL_OBJECT_FILES := abcdefg/cctalkio.o tollcoll/cctalkio.o
source-from-object = $(addsuffix $(SOURCEEXT),$(basename $(notdir $(1))))
$(ALL_OBJECT_FILES): %.o: $(call source-from-object,%.o)
#echo $*.o
when I run make abcdefg/cctalkio.o, I get:
make: *** No rule to make target 'abcdefg/cctalkio.c', needed by 'abcdefg/cctalkio.o'. Schluss.
The same, when I simpify the rule to:
abcdefg/cctalkio.o: %.o: $(call source-from-object,%.o)
#echo $*.o
But when I change the rule to:
abcdefg/cctalkio.o: %.o: $(call source-from-object,abcdefg/cctalkio.o)
#echo $*.o
I get abcdefg/cctalkio.o as Output. So the stem seems to be abcdefg/cctalkio, thus %.o should be the same as abcdefg/cctalkio.o. But why is make behaving different in both cases?
When I "debug" the source-from-object function:
debug:
#echo $(call source-from-object,/abcdefg/cctalkio.o)
I get the expected result cctalkio.c, so it seem like the function is working.
Your $(call) in the prereq is happening immediately and so your function is actually being passed %.o (not the matched result as you expected).
You would have to use something like:
.SECONDEXPANSION:
abcdefg/cctalkio.o: %.o: $$(call source-from-object,%.o)
...
to get what you want I believe.
Alternatively you could probably loop over your object files and statically give them the correct prerequisites and just let the static pattern rule supply the body.

Generic make rules using define

I'm trying to create a common template to generate rules build a set of test cases and place them in unique target locations but have hit a bit of snag with the define directive. The following is the relevant section of my Makefile:
ROOT=../..
PLATFORM=akyboard_gcc
# include all the test cases for the current platform
# They add to the TEST_CASES variable
TEST_CASES=A B
A_FILES = a1.c a2.c
B_FILES = b1.c b2.c
check: $(TEST_CASES:%=check_%)
define CHECK_template
# build artifact directories
$(1)_BLDDIR=$(ROOT)/build/$(PLATFORM)/$(1)
$(1)_OBJDIR=$$($(1)_BLDDIR)/obj
$(1)_EXEDIR=$$($(1)_BLDDIR)/exe
# prepend src/ to all the files that are part of the test case
$(1)_FILES := $($(1:%=%_FILES):%=src/%)
# add the test runner as one of the files to be compiled
$(1)_FILES += test_runner/$(PLATFORM)/main.c
# construct list of objects generated by sources
$(1)_OBJ = $($(1)_FILES:%.c=$$($(1)_OBJDIR)/%.o)
# This creates a rule such as check_{test_case}:
check_$(1): $$($(1)_OBJ)
#echo 1 $(1)
#echo 2 $$($(1)_FILES)
#echo 3 $$($(1)_OBJ)
#echo 5 $$($(1)_OBJDIR)
#echo 4 $$($(1)_BLDDIR)
#echo 6 $$($(1)_EXEDIR)
$$($(1)_OBJDIR)/%.o: $(ROOT)/%.c
#echo coconut
endef
$(foreach testcase, $(TEST_CASES), \
$(eval $(call CHECK_template,$(testcase))) \
)
Issuing "make check" gives the following error
*** No rule to make target `../../build/akyboard_gcc/A/obj/a1.o', needed by `check_A'. Stop.
If I manually create the target rules below it builds without errors
../../build/akyboard_gcc/A/obj/a1.o:
../../build/akyboard_gcc/A/obj/a2.o:
../../build/akyboard_gcc/B/obj/b1.o:
../../build/akyboard_gcc/B/obj/b2.o:
But changing rules like below causes the build error:
../../build/akyboard_gcc/A/obj/%.o:
Would be grateful for any help.
You can find what wrong with your template by replacing eval with info call.
$(foreach testcase, $(TEST_CASES), $(info $(call CHECK_template,$(testcase))))
And your template is fine. But you probably have a problem with pattern rules.
From GNU make manual:
A pattern rule can be used to build a given file only if there is a
target pattern that matches the file name, and all prerequisites in
that rule either exist or can be built.
Perhaps you don't have required sources in $(ROOT) directory. And make just can't create a rule for object file from pattern.

Resources