what does $< and $# mean in make file - visual-studio

I found these pseudo variable name in my makefile in WDK build environment. What is referenced by these variables? It is a little hard for me to get the answer by search engine because they are special, I believe.

These are automatic variables:
$#
The file name of the target of the rule. If the target is an archive member, then ‘$#’ is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ‘$#’ is the name of whichever target caused the rule's recipe to be run.
$<
The name of the first prerequisite. If the target got its recipe from an implicit rule, this will be the first prerequisite added by the implicit rule (see Implicit Rules).
They are used to build rules that can be applied to different targets so that one does not need to repeat the same rule for each and every file that must be worked on...
PS: To find the answer, I first looked for the 'all documentation on a single page' for GNU make, then used my browser's search function...

Related

What's the meaning of targets in a Makefile that start with a ., and how is it different/similar to suffix rules?

In a Makefile, I saw this:
all: .made
# ... some other code
.made: $(Program) bashbug
#echo "$(Program) last made for a $(Machine) running $(OS)" >.made
Is the .made rule a suffix rule as per: https://www.gnu.org/software/make/manual/make.html#Suffix-Rules?
Also, are all rules with targets that have a . in front suffix rules?
Otherwise, what is the significance of targets that start with .? It seems like there's a significance as per this in https://www.gnu.org/software/make/manual/make.html#How-Make-Works:
By default, make starts with the first target (not targets whose names
start with ‘.’).
But its significance is not mentioned.
Also, if it is a suffix rule, how come .made can be used as a prerequisite in the all rule? (It's not mentioned that the targets of suffix rules can be used as prerequisites in other rules.)
P.S.: This question is related to but different from what is the meaning for . (dot) before the target in makefile. This question asks explicitly for the difference between a target with . and a target of a suffix rule.
Is the .made rule a suffix rule
No, because .made is not a "known suffix".
Also, are all rules with targets that have a . in front suffix rules?
No, only those where the word after the dot is a "known suffix":
Your first two questions are answered by https://www.gnu.org/software/make/manual/make.html#Suffix-Rules:
Suffix rule definitions are recognized by comparing each rule’s target against a defined list of known suffixes. When make sees a rule whose target is a known suffix, this rule is considered a single-suffix rule. When make sees a rule whose target is two known suffixes concatenated, this rule is taken as a double-suffix rule.
In your example .made is an actual filename. Your Makefile has a rule for it that creates/updates the file:
#vvvv
.made: $(Program) bashbug
#echo "$(Program) last made for a $(Machine) running $(OS)" >.made
# ^^^^^
All pretty normal; it would work the same way with any other name.
The only significance of the leading dot is that it makes the file "hidden" by convention, i.e. ls won't show it (without specifying -a), plain * won't match it, etc.

Why is Make ignoring an explicit pattern rule?

I'm using GNU Make 4.0 to compile code on an IBM i system. Make is inexplicably choosing the wrong rule to build one type of object.
On this platform, program objects are built from modules, which are compiled from source code. There is also a convenience shortcut command that will create a program directly from a single piece of source code by creating a temporary module from the source code and then building a program from that. The problem I'm running into is that Make is using the shortcut command (crtbndrpg) instead of the two-step version (crtrpgmod + crtpgm), even though the target rule specifies that the program should be built from a module and not the shortcut.
There are two makefiles: a generic one that describes how to create IBM i objects, and a project-specific one that describes object dependencies for all items in this project and includes the generic one. My generic makefile looks like this (edited for simplicity):
# `IBMiMake`, a generic makefile that describes how to create IBM i objects.
OBJPATH := $(CURDIR)
override OBJPATH := $(shell echo "$(OBJPATH)" | tr '[:lower:]' '[:upper:]')
%.MODULE: %.RPGLE
$(eval crtcmd := crtrpgmod module($(OBJLIB)/$*) srcstmf('$<') $(CRTRPGMODFLAGS))
#system "$(crtcmd)" > $(LOGPATH)/$(notdir $<).log
%.PGM: %.RPGLE
$(eval crtcmd := crtbndrpg pgm($(OBJLIB)/$*) srcstmf('$<') $(CRTBNDRPGFLAGS))
system "$(crtcmd)" >$(LOGPATH)/$(notdir $<).log 2>&1
%.PGM:
$(eval crtcmd := crtpgm pgm($(OBJLIB)/$*) module($(basename $(filter %.MODULE,$(notdir $^)))) $(CRTPGMFLAGS))
system "$(crtcmd)" >$(LOGPATH)/$#.log 2>&1
The project-specific makefile looks like this (also edited for simplicity):
# `xpmake`, to create objects in this project.
ROOTDIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
IBMIMAKE := $(ROOTDIR)/../SDE/IBMiMake
include $(IBMIMAKE)
# AB2001.B.MODULE -- CRTRPGMOD
AB2001.B.MODULE: AB2001.B.RPGLE
# AB2001.B.PGM -- CRTPGM
AB2001.B.PGM: AB2001.B.MODULE
To build the object in question:
bash-4.2$ make AB2001.B.PGM OBJPATH:='/qsys.lib/xp33make.lib' -f xp33make/xpmake -d --no-builtin-rules
What should happen: It should first create the module using the crtrpgmod command, which it does. It should then create the program using the crtpgm command. Instead of creating the program via crtpgm, however, it for some reason tries to use the crtbndrpg command to directly build the program from source code. The only thing I can think of is that perhaps Make is seeing AB2001.B.MODULE as an intermediate file and opting to bypass the crtrpgmod step. Could this be true? How do I get make to follow my rules and not try to overthink things?
Here is the output:
GNU Make 4.0
Built for powerpc-ibm-aix5.3.0.0
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'xp33make/xpmake'...
Reading makefile '/home/SMEEP/Source/xp33make/../SDE/IBMiMake' (search path) (no ~ expansion)...
Updating makefiles....
Considering target file '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
Looking for an implicit rule for '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
No implicit rule found for '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
Finished prerequisites of target file '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
No need to remake target '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
Considering target file 'xp33make/xpmake'.
Looking for an implicit rule for 'xp33make/xpmake'.
No implicit rule found for 'xp33make/xpmake'.
Finished prerequisites of target file 'xp33make/xpmake'.
No need to remake target 'xp33make/xpmake'.
Updating goal targets....
Considering target file 'AB2001.B.PGM'.
File 'AB2001.B.PGM' does not exist.
Looking for an implicit rule for 'AB2001.B.PGM'.
Trying pattern rule with stem 'AB2001.B'.
Trying implicit prerequisite 'AB2001.B.CLLE'.
Trying pattern rule with stem 'AB2001.B'.
Trying implicit prerequisite 'AB2001.B.RPGLE'.
Found an implicit rule for 'AB2001.B.PGM'.
Considering target file 'AB2001.B.RPGLE'.
Looking for an implicit rule for 'AB2001.B.RPGLE'.
No implicit rule found for 'AB2001.B.RPGLE'.
Finished prerequisites of target file 'AB2001.B.RPGLE'.
No need to remake target 'AB2001.B.RPGLE'; using VPATH name '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'.
Considering target file 'AB2001.B.MODULE'.
Looking for an implicit rule for 'AB2001.B.MODULE'.
Trying pattern rule with stem 'AB2001.B'.
Trying implicit prerequisite 'AB2001.B.C'.
Trying pattern rule with stem 'AB2001.B'.
Trying implicit prerequisite 'AB2001.B.CLLE'.
Trying pattern rule with stem 'AB2001.B'.
Trying implicit prerequisite 'AB2001.B.RPGLE'.
Found prerequisite 'AB2001.B.RPGLE' as VPATH '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'
Found an implicit rule for 'AB2001.B.MODULE'.
Pruning file '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'.
Pruning file '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'.
Finished prerequisites of target file 'AB2001.B.MODULE'.
Prerequisite '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE' is older than target 'AB2001.B.MODULE'.
Prerequisite '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE' is older than target 'AB2001.B.MODULE'.
No need to remake target 'AB2001.B.MODULE'; using VPATH name '/QSYS.LIB/XP33MAKE.LIB/AB2001.B.MODULE'.
Finished prerequisites of target file 'AB2001.B.PGM'.
Must remake target 'AB2001.B.PGM'.
system "crtbndrpg pgm(XP33MAKE/AB2001.B) srcstmf('/home/SMEEP/Source/xp33make/AB2001.B.RPGLE')" >/home/SMEEP/Source/xp33make/Logs/2016-11-14_11.42.55-Mon/AB2001.B.RPGLE.log 2>&1
Putting child 30016df0 (AB2001.B.PGM) PID 1155363 on the chain.
Live child 30016df0 (AB2001.B.PGM) PID 1155363
Reaping losing child 30016df0 PID 1155363
/home/SMEEP/Source/xp33make/../SDE/IBMiMake:476: recipe for target 'AB2001.B.PGM' failed
Removing child 30016df0 PID 1155363 from chain.
Your example is still difficult to read: creating a minimal example is usually best (that is, construct an example that uses touch etc. to create files, and doesn't depend on your environment).
Also, the use of $(eval ...) inside the recipe to create a make variable assignment is a bit confusing. Don't think that just because you do this in the recipe there's some kind of scoping involved: those variables are still globally assigned.
In any event, the problem is that you have two ways to build a target that matches %.PGM:
%.PGM: %.RPGLE
%.PGM:
You apparently want to use the second one, but if the stem of a matching pattern rule is has equal length (here both have the same stem, .PGM) then make will always choose the first pattern that you define so it will always choose the first one if it can.
So, it will always use crtbndrpg to build that target, as long as make can figure out how to build %.RPGLE, so that pattern rule will match.
I'm not sure if they're omitted in the simplifying process, but your explicit rules lack their recipes.
Pattern rules with no recipe mean canceling any existing implicit rules.
https://www.gnu.org/software/make/manual/html_node/Canceling-Rules.html

Makefile Pattern Rule is found but recipe does not run

I have a makefile that has the following pattern rule to create an implicit rule:
%.cpp:
$(warning foo)
When I check the output of make -d I see that this implicit rule is being found and matching a file. I verify that when I remove the pattern rule, the output of make -d no longer shows a match. However, even when the implicit rule is found, the warning doesn't show up. The recipe isn't running, even though the implicit rule matches.
What gives?
That recipe tells make how to create a %.cpp file (and gives it no prerequisites).
When are you expecting it to be run?
It will not run for any existing *.cpp files as the lack of prerequisites means that make considers the files up to date.
Try running make totally-doesnt-exist.cpp and you should see the warning.

searchpath for prereqisites, like vpath, but only for some pattern rules

I'm trying to build several executables in one make instance, as suggested by
Recursive Make Considered Harmful.
The arguments of that paper apply to my project because some of my source files are generated, and go into multiple executables.
The object files for each of these executables go into separate directories, because they are compiled with different preprocessor flags.
How can I specify separate vpath settings for each of these executables, so that source files with duplicate filenames in separate directories go into the executables where I want them to go?
Setting vpath before the rules to build the object files for one executable, and erasing it afterwards (by not giving any directories) doesn't have the desired effect. Apparently, the last setting is used for all the rules.
Solutions I see currently:
Rename source filenames to use unique names so that I can use a global vpath setting
Instead of vpath, use separate rules for each source directory, with the source directory in the prerequisite pattern (*)
Recursive make, with separate vpath settings in each make instance, and somehow deal with the resulting trouble.
Use something different than make.
Is there a better solution, or which one of the above would you prefer?
(*) The solution with separate rules looks like this:
build/$(PROGRAM)/%.o: %.c
$(COMPILE_RECIPE)
build/$(PROGRAM)/%.o: $($(PROGRAM)_SOURCE_DIR)/%.c
$(COMPILE_RECIPE)
Ok for my current project, but would become ugly fast, if there where more than one directory different in the source paths of the executables
Edit: Test for suggestion of #Etan, which shows that $^ is empty, when the prerequisites appear only in pattern rules (y/y.c) - this only works if each dependency is given directly, as for x/x.c.
.PHONY: all
all: build/x.o build/y.o
build/x.o: x/x.c
# the following rule is ignored:
build/%.o: y/%.c
# because there is a matching pattern rule with a recipe:
build/%.o:
#echo \"$#\" from \"$^\"
#touch $#
The files x/x.c, y/y.c and the directory build exist.
output:
"build/x.o" from "x/x.c"
"build/y.o" from ""
Tested with GNU Make 3.82.90
First, it's never correct to use VPATH or vpath to find derived files (files that are built by make)... that includes "source files that are generated" (if they are generated by make, and not before make is invoked somehow). VPATH/vpath can only be used to find source files (files that are not built by make). See How not to use VPATH for more information.
Second, vpath is a global setting, not a per-target setting. Whenever make wants to find a prerequisite and that prerequisite doesn't exist "normally", make will use the vpath settings to find it. There's no facility in vpath to say "for this target use these vpath settings, for that target use those". In an ideal world, you would be able to set VPATH as a target-specific variable but this doesn't work.
There are various ways to generate prerequisites based on a target: you might find some of the suggestions on metaprogramming in make helpful.
Lastly, the makefile example you give regarding $^ is not correct:
# the following rule is ignored:
build/%.o: y/%.c
# because there is a matching pattern rule with a recipe:
build/%.o:
#echo \"$#\" from \"$^\"
#touch $#
You cannot specify a pattern rule without any recipe and have it "add" prerequisite patterns to some other existing pattern rule. It works for explicit rules, to add more prerequisites to a target, but specifying a pattern rule with no recipe simply deletes the pattern rule.
So, $^ is empty for build/y.o because there are no prerequisites defined in the pattern rule and you've not defined any explicit prerequisites for build/y.o like you did for build/x.o.
ETA: The reference to metaprogramming was to suggest that you can use it to make your second option, which is the one I would use, be less typing and easier maintenance. Pick the method you prefer and auto-generate the various pattern rules. This might be termed a "fifth option".
Other than that any of the four you suggest are fine, and there isn't another option you're missing that I'm aware of.

$+ meaning in makefile

What does $+ in a GNU makefile mean?
Also, please give me some good lookup manual for writing makefiles.
From the make manual:
$^ The names of all the prerequisites, with spaces between them. For prerequisites which are archive members, only the member named is used (see Archives). A target has only one prerequisite on each other file it depends on, no matter how many times each file is listed as a prerequisite. So if you list a prerequisite more than once for a target, the value of $^ contains just one copy of the name. This list does not contain any of the order-only
prerequisites; for those see the `$|' variable, below.
$+ This is like `$^', but prerequisites listed more than once are duplicated in the order they were listed in the makefile. This is primarily useful for use in linking commands where it is meaningful to repeat library file names in a particular order.
In both cases, all I can say is RTFM... or RTFI in this case. Type
info make
at a command prompt and all the information you could ever want will be at your fingertips.
For $+ specifically: it refers to the names of all the prerequisites of the current rule. See for example http://uw714doc.sco.com/cgi-bin/info2html?(make.info)Automatic&lang=en

Resources