Makefile dependency from a variable that is reset in another file - makefile

Given this Makefile (stripped down to a minimal example):
include Makefile2
NAME=bar
And a second Makefile2 with some general rules:
NAME=foo
something: $(NAME).txt
#echo $(NAME).txt
Calling make something will depend on foo.txt but it will print bar.txt.
Is it possible to define a rule in Makefile2 that depends on $(NAME).txt with the actual value of NAME, so the example rule would use bar.txt as dependency also?

This is a hack, but it works:
NAME:=foo
something:
#$(MAKE) -s other OTHERNAME=$(NAME)
other: $(OTHERNAME).txt
#echo NAME is $(NAME).txt, and this rule depends on $<

Related

Change directory before running any targets

I have the following use case where I read a variant at the top of a Makefile and then according this variable I must change directory to execute all the targets. I'd avoid to repeat in each target something like
my_target:
cd $(MY_DIR) &...
Any approach I could use to achieve that?
It's not 100% clear to me what you need but something like the following should work
ifndef submake
export submake=1
variant := somedir
$(MAKECMDGOALS):
$(MAKE) -C $(variant) -f $(realpath $(MAKEFILE_LIST)) $#
else
#actual targets defined here
foo:
#echo $#
bar:
#echo $#
endif
Go to the directory (cd) where you want Make to operate, and then
make -f /path/to/Makefile

Match anything pattern rule with dependency

File Name: Makefile.mk
%: foo
#echo %: $# with foo
foo:
#echo foo
Run
$ make -f Makefile.mk test
Output:
foo
%: Makefile.mk with foo
%: test with foo
I am running this in GNU Make 3.81 version.
I Don't understand, why file name also printed(%: Makefile.mk with foo).
Can some one please explain me?
This is because of how makefiles are remade. That is to say that
Sometimes makefiles can be remade from other files
and
If a makefile can be remade from other files, you probably want make to get an up-to-date version of the makefile to read in
so
after reading in all makefiles, make will consider each as a goal target and attempt to update it.
Which then matches against your match-anything rule and triggers the way you see.
If you add an explicit Makefile.mk: ; target to your makefile it will override the match-anything target and prevent this.

GNU make interdependent predependencies

I am trying to write a make rule with pre-dependencies which are inter related.
a: b $(FILES)
b: $(FILE_1)
$(eval FILES := some_function_using_file($(FILE_1)))
$(FILES):
do something ...
Basically, I need $(FILE_1) to get $(FILES). When make first reads in the file, this rule below does not exist because $(FILES) is not defined initially but gets evaluated dynamically.
$(FILES):
do something ...
Is there a way to make this work? I want to dynamically create $(FILES) and then run its rule.
The targets get evaluated before any of them run. Your best bet is to generate the list before that happens.
FILES = $(shell ls) new.txt
all: $(FILES)
$(FILES):
echo $#
If you're really desperate you could generate another makefile from within the makefile and call another copy of make.

How does % in Makefiles work?

I am trying to understand how makefiles work. If I try the following
1.out : 1.inp
cat 1.inp
it, works as expected (if 1.inp is newer as 1.out or if 1.out does not exist, the content of 1.inp is printed).
Then I need to do the following:
cat 1.inp
cat 2.inp
cat 3.inp
I thought that for that I can use
%.out : %.inp
cat $<
but it does not work. Can anybody please explain to me the use of %?
In your first makefile:
1.out: 1.inp
cat 1.inp
1.out is a target with a prerequisite 1.inp and a command cat 1.inp. This constitutes a rule for
making 1.out and if you run the makefile, specifying either no explicit target or the target 1.out, the
rule will be executed.
In your second makefile:
%.out: %.inp
cat $<
you have only expressed a pattern rule for making a target of the form something.out from a prerequisite of the form something.inp You have not specified any actual targets that the makefile can make.
You can specify 1.out as a target with a makefile like this:
%.out: %.inp
cat $<
1.out:
In that case 1.inp will be cat-ed when 1.inp is newer that 1.out
Or you can specify a phony target, e.g. all, that has prerequisite targets 1.out, 2.out, 3.out in a makefile like this:
.PHONY: all
%.out: %.inp
cat $<
all: 1.out 2.out 3.out
In this case each of 1.inp, 2.inp and 3.inp will be cat-ed when it is newer than the corresponding .out file.
Whenever make discovers that it has to make a target of the form something.out, it will recognize that the pattern rule is applicable and will execute the matching instance of the pattern rule.

variable target in a makefile

I am trying to compile set of targets. However it only seems to do the first one. Below is a cut down of the my makefile that shows the error.
OBJECTS = abc def ghi
SOURCES = abc.c def.c ghi.c
$(OBJECTS): $(SOURCES)
#echo target is $#, source is $<
In shell,
$ touch abc.c def.c ghi.c
$ make
When I run make I get the following output:
target is abc, source is abc.c
So it only seems to be running the first target.
If I replace $< with $^, the output is:
target is abc, source is abc.c def.c ghi.c
My question, is it possible to perform expansions on variables like with the (%: %) pattern?
Try this:
OBJECTS = abc def ghi
all: $(OBJECTS)
$(OBJECTS):%:%.c
#echo target is $#, source is $<
The trouble was
The default target (which is what Make chooses if you just type `make`) is the first target in the makefile, which was `abc`.
You made all sources prerequisites of every object. That is, all three sources were prerequisites of `abc`. They were also prerequisites of `def` and of `ghi`.

Resources