What is the target member name in an archive in a makefile?
It is explained here: https://www.gnu.org/software/make/manual/html_node/Archive-Members.html#Archive-Members
but I don't quite understand it since there's not a brief example.
If I have
target(name): name
echo $%
$% is the automatic variable for target name.
If I use make target, this won't run
why? What is "target member name" actually?
The documentation you link to specifically explains this, near the beginning.
This construct is available only in targets and prerequisites, not in recipes! Most programs that you might use in recipes do not support this syntax and cannot act directly on archive members. Only ar and other programs specifically designed to operate on archives can do so. Therefore, valid recipes to update an archive member target probably must use ar.
So for example, to create an ar archive called target containing name, the commands would be
touch name
ar cr target name
As a Makefile, this is
target: name
ar cr $# $^
name:
touch name
The target(name) syntax is useful when you want to manipulate the copy of name which is inside target. For example, if name was rebuilt at some point, your Makefile might want to compare its date stamp against the date stamp of the name member within target, to decide whether you need to update the copy inside target.
target(name): name
ar cr $# $%
But this doesn't specify how to create target in the first place; as far as I can tell, you need a recipe like the one at the top of my example for that.
Related
At present, I have a makefile that has:
a target which links an executable image file from a bunch of object files
a pattern rule target that compiles the various object files the linker target depends on
I want to make the following changes.
Instead of compiling the object files outright, I want the pattern rule target mentioned above to create (for each object file that needs updating) an empty object_file_name.update file. Essentially, this target's job would be to take stock of all object files that actually need to be recompiled.
Write a new target that launches a Perl process which finds all these object_file_name.update files and, for each object file that must be recompiled, compiles it in this Perl process.
I know how to do 2) ... that part is not giving me any trouble. The part I'm worried about is 1). The reason is that that target would basically have to claim to update any needed object files while, in truth, merely creating an .update file for each such object file but not the object file itself.
I think I could trick GNU Make into not starting to try to link anything before all the object files have been built by declaring my dependencies accordingly (pseudo-code, not a valid GNU Make snippet):
# Phony target that reads the *.update files created by the pattern rule target below and then
# compiles each object file for which an *.update file exists.
COMPILE_OBJECTS :
...
# Pattern rule target to take stock of all object files that need updating. Creates an *.update file for
# each object file that needs recompiling.
%.o : %.c :
...
$(EXE_FILE_TO_LINK) : $(LIST_OF_OBJECT_FILE_PATHS) COMPILE_OBJECTS
...
but I still worry that this might result in undefined behavior because my pattern rule target would basically be lying to GNU Make about updating the needed object files. Is my worry justified?
Basically, I want to interject an intermediate layer between GNU Make and the compiler so that GNU Make doesn't compile each object file separately. Instead, the compiling would be done in a single Perl process that has access to the complete list of object files that need to be compiled, allowing me to do various fancy things that I couldn't do if GNU Make controlled compilation directly.
Yes, it's legal and I often use this pattern.
Consider the case where you only want to kick off a long build step if a file has changed.
target: config-file
target-creator $< -o $#
Now let's say we can't give make the dependencies for config-file (because the config file creation step lacks a dependency listing ability (BAH!)).
.PHONY: FORCE
FORCE: ;
config-file: FORCE
config-creator -o $#.tmp
cmp $#.tmp $# || mv $#.tmp $#
We ask make to build target
Make first has to build config-file
Make will always run the recipe for config-file,
as its dependency FORCE is out of date (being phony)
CRUCIALLY we only update config-file if config-creator decides something has actually changed
If cmp decides config-file.tmp and config-file are the same, and the last line of the recipe completes with no error
OTOH if cmp detects a mis-compare, it fails, and the shell goes on to execute the mv.
After running the recipe for config-file, make does actually check config-file's modification time. IF config-file has become younger than target, only then will target-creator be run.
The subtlety here is that even though config-file's recipe runs every time, config-file itself is not phony.
I'm using GNU Make 4.0 to compile objects on an IBM i. Most items are ok and conflict-free (.c compiles to a .module, .pf compiles to a .file), but a couple types of items use the same filename suffix for both source and object. For example, commands end in .cmd for the source code and also for the compiled command object. This results in a makefile definition like this:
C_CODE1.MODULE: C_CODE1.C # This is ok -- no conflict
COMMAND1.CMD: COMMAND1.CMD # Error! Make thinks it's a circular dependency.
What can be done to tell Make that the .cmd item on the left and the one on the right are actually two different items? The object suffixes are fixed by the operating system and cannot be changed. The source code suffixes could be changed, but then they wouldn't appear correctly in our code editors without customization. The source code does exist in a separate directory from the objects, but paths aren't really specified in the makefile, other than when setting up VPATH.
If the target name does not have to match the prerequisites, I would change the target name to something else, for example COMMAND1: COMMAND1.CMD.
If they have to be matched then I would write like the following to add the extension explicitly in the recipe.
COMMAND1 : COMMAND1.CMD
cat $< > ${#}.CMD
For the source, even if you are using traditional source files, it's not necessary to use the standard source member type. You could use say CMDSRC for the source member type of your command source.
I want to have a generic Makefile that takes any target name and for that target name, checks to see if certain sources exist and then executes some commands. So for example I want to be able to enter:
make mytarget
then make should check to see if mytarget.src1 and mytarget.src2 exist, and if so execute some commands.
I have the following makefile:
%:
$(MYCOMMANDS) $*.scr1 $*.scr2
the only problem with this is that it doesn't check to see if $.scr1 and $.scr2 exist before running $(MYCOMMANDS). This is understandable because I haven't specified any dependencies. However when I try:
%: $*.src1 $*.src2
$(MYCOMMANDS) $*.scr1 $*.scr2
it now doesn't ever run $(MYCOMMAND) and says no rule to make the specified target.
Can someone please explain why in my second code make cannot find the target? Also, how can I achieve the behavior that I want?
The correct way to write a pattern rule is to use the pattern (%) in both the target and the prerequisites:
%: %.src1 %.src2
$(MYCOMMANDS) $^
See Pattern Rules in the GNU make manual. Also see Automatic Variables. By the way, the third paragraph in the second link will explain why your second attempt, using $* in the prerequisites, cannot work.
I was able to get the behavior I want using the MAKECMDGOALS variable. So:
$(MAKECMDGOALS): $(MAKECMDGOALS).src1 $(MAKECMDGOALS).src2
$(MYCOMMANDS) $(MAKECMDGOALS).scr1 $(MAKECMDGOALS).scr2
does what I am looking for. It checks to make sure .src1 and .src2 exist. If they don't make will report an error and if they do it will run $(MYCOMMANDS).
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...
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