What does the target-specific vairable not take effect in Makefile? - makefile

everyone
How to set different prerequisites for the same target when it belong to a different target. For example,
target t1 depends on file main.o and t1.o where main.o depend on t1.o (it's a module file in fortran, similar as a head file .h in C) besides its source, while
target t2 depends on file main.o and t2.o where at this time main.o depends on t2.o together with it's souce file.
i.e
t1 : main.o t1.o
main.o: t1.o
t2:main.o t2.o
main.o: t2.o
I wrote them together in one makefile, but unforturanatly, the dependece of main.o does not take effect. why?
--
1 .SECONDEXPANSION:
2
3 FC=gfortran
4 PRJ = t1 t2
5
6 all: $(PRJ)
7
8 %.o:%.f90 ; $(FC) -c $<
9
10
11 t1: tname = t1.o
12 t2: tname = t2.o
13
14 $(PRJ) : main.o $$(tname) ; $(FC) $^ -o $#
15 main.o : $$(tname)
16
17 clean:
18 rm -rf $(PRJ) *.o *.mod
line 15 doesnot take effect. why?
here are the source file:
main.f90
use eqn
print *,nam
end
t1.f90
module eqn
character(10):: nam = 't1'
end module
t2.f90
module eqn
character(10):: nam = 't2'
end module

target-specific vairable is actually working, if you run make t1, then make clean, then make t2(It works on my PC). But when you run make or make all, it's not. This is because there are multiple targes and only one target main.o is generated i guess(not quite sure about this part)
The dependency graph maybe like this when running make or make all:
t1 t2
|\ / |
| +-> main.o <-+ |
| |
t1.o t2.o
check below:
GNU make does its work in two distinct phases. .....constructs a dependency graph
of all the targets and their prerequisites. During the second phase, make uses
these internal structures to determine what targets will need to be rebuilt and
to invoke the rules necessary to do so.
and
immediate : immediate ; deferred
deferred
That is, the target and prerequisite sections are expanded immediately
(From this)

Related

How to generate multiple executable files in one Makefile?

My directory contains 2 source files: a.c and b.c. I want to generate executable file a from a.c and b from b.c. Now I can only figure out one method to write Makefile:
all:
gcc -o a a.c
gcc -o b b.c
It seems a little awkward, is it better method?
The answers are fine, still I think you need some insight in how make works:
The basic functionality of make is to create output files from input files if necessary. make decides what is necessary by comparing timestamps: If any input file is newer than an output file created from it, the recipe for this output file is executed.
This means with just a rule named all, this rule is always executed (except when you happen to have a recent file actually called all -- to prevent this behavior, you have to list all as a .PHONY target, that is one that doesn't actually create a file). Your original Makefile is equivalent to a simple shell script, so it doesn't use make properly.
The minimal "correct" version of your Makefile should look like this:
all: a b
a: a.c
gcc -o a a.c
b: b.c
gcc -o b b.c
.PHONY: all
So, all is "phony" and depends on a and b. a is only rebuilt when a.c changed, b is only rebuilt when b.c changed.
In a real project, your programs are probably made from more than just one source file and in this case, you can really take advantage of make: Have it build object files of your translation units, so only the parts that changed are actually rebuilt. It's overkill for your tiny example, but could e.g. look like this:
a_OBJS:= a.o
b_OBJS:= b.o
all: a b
a: $(a_OBJS)
gcc -o$# $^
b: $(b_OBJS)
gcc -o$# $^
%.o: %.c
gcc -c -o$# $<
clean:
rm -f *.o
.PHONY: all clean
You would just have to add more object files to a_OBJS and b_OBJS to include new translation units in your build. The pattern rule %.o: %.c will match them. There's a lot more to discover, I suggest starting with the GNU make manual.
I think the follow method is better:
all: a b
a: a.c
gcc -o a a.c
b: b.c
gcc -o b b.c
In your version, make all will always run gcc twice, whether or not a.c and b.c are modified. In this version gcc will be run only when necessary.
Of course you can use some magic (for-loop or similar) to create the rules but I think the difference between my and your method is clear.
To me
all:
gcc -o a a.c
gcc -o b b.c
looks fine.
Or may be the following for better control
all: a b
a: a.c
gcc -o a a.c
b: b.c
gcc -o b b.c
clean:
-rm a b
A lesser known trick to compile without makefile
make a #run cc -o a a.c by make or
make b #run cc -o b b.c by make
Or to generate both a and b
make a b
make uses implicit rule here, just like magic. But prefer a makefile with rule specified

Makefile is always not up to date even without any changes

I have a directory with two folders, src and bin with the makefile at root directory. This makefile keeps compiling (not up to date) even without changes. Am I missing something with this makefile?
all:
make a b
a: ./src/a.cpp
g++ -o ./bin/a ./src/a.cpp
b: ./src/b.cpp
g++ -o ./bin/b ./src/b.cpp
Your rules claim to create the files a and b, but they don't: They create bin/a and bin/b.
So when make checks your rules, it always finds that a and b don't exist and tries to create them by executing their associated commands.
Possible fix:
.PHONY: all
all: bin/a bin/b
bin/a: src/a.cpp
g++ -o bin/a src/a.cpp
bin/b: src/b.cpp
g++ -o bin/b src/b.cpp
On .PHONY: https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html#Phony-Targets

Execute a Makefile in parallel except for some rules

I have a complex makefile with a lot of recipes. I would like run them with no parallel execution except for the generation of my objects files. I noticed that the .NOTPARALLEL target cannot take any prerequisites otherwise it would have been much easier to solve my issue.
My first guess was to use a nonexistent target named ".PARALLEL" with which I would have mentioned the objects files as dependancies like this:
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
.PARALLEL: $(OBJ)
%.o: %.c
gcc –c –o$# $< -M
a.out: $(OBJ)
gcc –o$# $^
A more functional solution I have found is to use an intermediate target. However, since MyObjects has no dependancies, make will always call MyObjects and recreate a.out.
%.o: %.c
$(CC) –c –o$# $< -M
MyObjects:
$(MAKE) -j $(OBJ)
a.out: MyObjects
$(CC) –o$# $(OBJ)
To avoid this I've found nothing better than using dummy files. I wrote this example to illustrate it:
NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SRC = $(addsuffix .c, $(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))
DUM = $(addsuffix .dummy,$(OBJ))
all: a.out
$(SRC):%.c:
touch $#
$(OBJ):%.o: %.c
cp $< $#
touch $(addsuffix .dummy, $#)
$(DUM):
$(MAKE) -j8 $(OBJ)
a.out: $(DUM) $(OBJ)
zip $# $(OBJ)
clean:
-rm *.o
-rm *.out
-rm *.c
-rm *.dummy
I'm sure this is not the best solution I can get. I would be glad to get some help.
P.S. MadScientist, thank you for your advices.
This is really not right:
MyObjects: $(OBJ)
$(MAKE) -j $(OBJ)
This means that before make tries to build the MyObjects target, it will first try to update all the $(OBJ) files. Once that's all done, then it will try to build the MyObjects target by recursively invoking make to rebuild them again. Obviously that's not what you want. Plus you're using -j which is basically "infinitely parallel" and is likely (if you have enough object files) to bring your system to its knees.
You want something like this:
MyObjects:
$(MAKE) -j5 $(OBJ)
As for your second question about trying to rebuild targets, there's no way we can help without some kind of specific example. Typically this happens because your rules are written incorrectly, and they don't actually update the target you told make they would. So for example, you have a target recipe_a but the rule for recipe_a updates some other target, not recipe_a.
I'll add a few notes based on your second question. Probably if you don't get it after this you should take this off of StackOverflow and ask on the help-make#gnu.org mailing list, or else consider breaking this up and asking several specific StackOverflow questions.
First, why you see make[1]: '15.o' is up to date. for every file in your recursive make: because make always prints that message for every target on the command line, so if you run make 1.o 2.o 3.o ... (doesn't matter whether you use -j or not or what value of -j you use) you'll get that message for every target which doesn't need to be rebuilt. Just as if you ran that same make command from the command line yourself.
Second, why you don't get a.out is up to date, because a.out is NOT up to date. It depends on the build target, and the file build doesn't exist, and thus it's out of date, and so it must be rebuilt every time. And that means anything that depends on the build target, like a.out, must be rebuilt every time. Which explains why it always re-runs the zip command.
Third, the behavior with all.c is because if you create a pattern rule like %.c: with no prerequisites, that tells make that it can create ANY file with a .c extension by running that command. Well, one of the targets you asked make to build is the all target. Since you didn't declare that as a .PHONY target, make tries to build it. Normally that attempt fails because make can't find any rules that know how to build all so nothing happens, but after you tell make how to build a .c file out of nothing (no prerequisites), then when make wants to build all it looks in its internal database of predefined rules and sees a pattern rule % : %.c, which tells make how to build an executable from a source file with the same name (on UNIX systems executables don't have any suffix like .exe: they're just make or cc etc.) So, make tries to run those rules and they fail.
For any target which you don't expect to actually be created, like all, clean, etc. you should declare them to be .PHONY so make won't try to build them.
As for your problem. I think the simplest thing to do is push the entire build of the zip file down into the recursive make, rather than trying to build the objects only in the recursive make. Something like this:
NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SRC = $(addsuffix .c,$(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))
all: recurse
recurse: non-parallel-targets
$(MAKE) -j8 a.out PARALLEL=true
ifneq($(PARALLEL),true)
.NOTPARALLEL:
endif
%.o: %.c
cp $< $#
a.out: $(OBJ)
zip $# $(OBJ)
init: $(SRC)
clean:
-rm *.o
-rm *.out
.PHONY: all clean init

Makefile trick to get dependencies of a rule

Is there any trick in GNU Makefiles to get all dependencies of a rule?
Example:
rule1: dep1_1 dep1_2 dep1_3
rule2: dep2_1 dep2_2 rule1
dump_deps:
echo "Dependencies of rule1: $(call do_the_trick, $(rule1))"
echo "Dependencies of rule2: $(call do_the_trick, $(rule2))"
install: $(prefix install-,$(call do_the_trick, $(rule1)))
I'd like to be able to call make dump_deps and see:
dep1_1 dep1_2 dep1_3
dep2_1 dep2_2 dep1_1 dep1_2 dep1_3
Or automatically install dependencies with make install and things like.
Is it possible?
EDIT:
I changed the example to show better that I want something automatic, and not having to hardcode dependency lists myself.
You can't show the transitive dependencies, only the direct ones, however, you can take the output generated below and feed it into the programs dot (part of graphviz) to make sense of the these transitive relationships.
Edit: I guess you could also post-process the results in other ways to just list the deps, but I think pretty pictures are better; feel free to downvote if you disagree ;)
Here's a sample makefile (watch for missing tabs when c&p!):
# Makefile that demonstrates how to dump dependencies.
# The macros we use for compiling stuff.
CC_OBJ=$(CC) -o $# -c $(CFLAGS) $<
CC_BIN=$(CC) -o $# $(CFLAGS) $(LDFLAGS) $^
# If we get "DUMP_DEPS=1 DUMP_DOT=1" on the command line, then instead of
# make-style dependencies, we'll output 'dot' syntax.
# Note: normally, DUMP_DOT_TAIL is undefined, so it doesn't generate any noise.
ifeq ($(DUMP_DOT),1)
DUMP_DOT_HEAD=digraph dependencies {
DUMP_DOT_TAIL=#echo "}"
$(info $(DUMP_DOT_HEAD))
list_dep=#for f in $^; do echo " \"$#\" -> \"$$f\";"; done
else
list_dep=#echo "$#: $^"
endif
# If we get "DUMP_DEPS=1" on the command line, then
# instead of building the code, just print the dependencies.
ifeq ($(DUMP_DEPS),1)
CC_OBJ=$(list_dep)
CC_BIN=$(list_dep)
endif
# An implicit rule that builds *.c -> *.o.
%.o:%.c
$(CC_OBJ)
# Variables for stuff we wanna build.
target=hello
objects=main.o
objects+=stuff.o
objects+=yeah.o
# The top-level 'all' target.
.PHONY: all
all: $(target)
$(DUMP_DOT_TAIL)
# Builds our final executable
$(target): $(objects)
$(CC_BIN)
# A standard clean target.
.PHONY: clean
clean:
-rm -f $(target) $(objects)
Now, you can do this:
make -B DUMP_DEPS=1
And it will go through and list all your pre-requisites is make style of "target: pre-requisite". Sample outputs:
Normal run:
cc -o main.o -c main.c
cc -o stuff.o -c stuff.c
cc -o yeah.o -c yeah.c
cc -o hello main.o stuff.o yeah.o
With make -B DUMP_DEPS=1:
main.o: main.c
stuff.o: stuff.c
yeah.o: yeah.c
hello: main.o stuff.o yeah.o
With make -B DUMP_DEPS=1 DUMP_DOT=1:
digraph dependencies {
"main.o" -> "main.c";
"stuff.o" -> "stuff.c";
"yeah.o" -> "yeah.c";
"hello" -> "main.o";
"hello" -> "stuff.o";
"hello" -> "yeah.o";
}
You could then run the following to output a pretty picture to an SVG image:
make -B DUMP_DEPS=1 DUMP_DOT=1 | dot -Tsvg > deps.svg
Here's what it looks like (this is actually a png, generated with -Tpng > deps.png):
I think this would need some extra work to produce accurate results in all situations, but the principle is sound (e.g. if you use gcc-generated dependency files, you'll need to create them first).
This should list all of the dependencies:
DEPEND = dep1 dep2 dep3
.PHONY: $(DEPEND)
dump_deps: $(DEPEND)
#printf "%s\n" $^
You should remove the line with .PHONY target for your needs. It is used for the sake of the example. And please note that there is a tab between the beginning of the line and printf.
use the buit in variables available with the make utility , $^ -- this represents all the dependencies of the rule.
also looking thru your code , i did make the rule1 into a variable / macro form to suit my purpose ......
rule1 := dep1 dep2 dep3

Make 3 passes for a target

I'll explain myself, here is my scenario:
Compile my target
Do a first optimization based on the first compilation
Do a second optimization based on the first optimization
Do a third optimization based on the second optimization
So far I tried the following:
.SUFFIXES:
.SECONDARY:
OBJECTS := $(addsuffix .obj,$(SOURCES))
override OBJECTS := $(OBJECTS:$(SRC)/%.obj=$(OBJ)/%.obj)
OC1 := $(patsubst %.obj, %.oc1, $(filter %c.obj,$(OBJECTS)))
O1 := $(L166_CMD:%.lnp=%.o1)
all: $(TARGET) $(O1)
$(TARGET): $(OBJECTS)
#echo Linking $(TARGET)...
$(OBJ)/%.c.obj: $(SRC)/%.c
#echo Compiling $(<F) ...
# c.oc1 is a intermediate file
%.c.oc1: %.c.obj
#echo 1 - Optimize $<...
#touch $#
$(O1): $(OC1)
#touch $#
echo Linking O1
Result is, I modify a C file, the target will regenerate only the modified C file but the O1 pass will optimize all C files again like it was not done before (but it was).
How can I modify this behavior?
The reason is your last target, $(O1): $(OC1). That is each O1 depends on every OC1.
What is the actual value of $(O1)? Is it supposed to be a list or a single target?
I would try to replace this rule by a pattern (if it possible).

Resources