What does $^ in gnu make mean? - gnu-make

I am translating GNU makefile to NMake makefile.
I came across such construction in GNU Makefile:
DEP1 = dependencyA1.c dependencyA1.c
DEP2 = dependencyB1.c dependencyB2.c
libABC.a: $(DEP1) $(DEP2)
$(ARCHIVE) libABC.a $^ #**what this does?**
I quite often write GNU Makefiles, but it is first time I found such instruction. Could someone more experienced explain what it does?
Thanks in advance,
Regards.

Related

Make rule using `$<` only adding one object to archive library

I feel stupid, but I cannot find the solution myself:
I have a Makefile that correctly builds objects from C source, and I want to place $(OBJECTS) in an archive library.
I'm using GNU Make 4.0.
x.a: $(OBJECTS)
echo "$< ($(OBJECTS))"
$(AR) $(ARFLAGS) $# $<
(Lines are indented with TABs in original. The echo was added for debugging purposes only, The $(AR) $(ARFLAGS) $# $< was copied from make's internal rules)
Make outputs (at the end after the objects were built):
echo "log_thread/log_thread.o (log_thread/log_thread.o log_thread/thread.o)"
log_thread/log_thread.o (log_thread/log_thread.o log_thread/thread.o)
ar rv x.a log_thread/log_thread.o
ar: creating x.a
a - log_thread/log_thread.o
So I expect both objects modules to be added to the library x.a, but $< only contains one object module, as opposed to $(OBJECTS)).
My Make knowledge may be a little rusty, maybe that's why I don't get it.
Of course both object modules exist, and the output was created after having removed x.a (the original file is a bit more complex).
I'm not sure where the confusion lies:
The $< automatic variable contains the first prerequisite only, as per definition.
See the GNU make manual.
To get all prerequisites newer than the target, $? is the correct automatic variable.
So the correct rule probably is:
x.a: $(OBJECTS)
echo "$? ($(OBJECTS))"
$(AR) $(ARFLAGS) $# $?

GNU make: detect target creation vs. update

Is there a way in GNU make to detect whether the target needs to be created resp. updated?
I need this differentiation due to a oddity of MS lib.exe (which I have to use).
UN*X-like tools support "ar cr lib.a file.o" either creating or updating "lib.a". Unfortunately MS lib.exe requires this:
1st call : lib.exe -out:lib.lib file.obj
next call(s) :
lib.exe -out:lib.lib lib.lib file.obj
So I have 2 different commands with target and dependencies being the same...
lib.lib : file.obj lib.exe -out:$# $^ <-- if lib.lib not exist
resp.
lib.exe -out:$# $# $^ <-- if lib.lib exist
I want this to be handled by GNU make and not delegate it to the command (aka shell).
NB: double-colon rules actually won't help as the problem is burried in an implicit rule
(%.obj) : %.obj
$(AR) $(ARFLAGS) -out:$# $# $^
There's no built-in way to do it but you can write your rule to do it:
lib.lib: file.obj
lib.exe -out:$# $(if $(wildcard $#),$#) $^

How to split up path names in gnu make?

In GNU Make, I have a requirement to obtain the name of the parent directory of the directory my makefile is running in.
For example, if the makefile is /home/fnord/foo/bar/Makefile, I want to set a variable to the string "foo".
I can do this using some of the GNU Make built in functions, shown here all split up for clarity.
V1=$(CURDIR)
V2=$(dir $(V1))
V3=$(subst /, ,$(V2))
V4=$(lastword $(V3))
This seems complex for such a simple requirement, but I can't find a better way. Are there any better techniques for splitting up pathnames in GNU Make?
I need this to work in GNU Make version 3.81 and later.
Because of the way the $(dir ...) function works in GNU make, it's not as nice as it could be, but it's better than the above (IMO):
V4 = $(notdir $(patsubst %/,%,$(dir $(CURDIR))))
The idea behind leaving the trailing slash is to allow joins (making the operation reversible), but in my experience this ends up not being very useful in practice, and having to strip the trailing slash is a PITA. However, it is what it is and there's far too much history to change it now.
ETA:
If you like you can make a function that works more like the shell's dirname and use call:
dirname = $(patsubst %/,%,$(dir $1))
V4 = $(notdir $(call dirname,$(CURDIR)))

makefile rule to build multiple targets without intermediate file

I am stumped coming up with a makefile rule to have several executables where each depends on its respective source file. There is a library common to all and each program has a single source file: a.c compiled and linked with the library produces executable a, etc.
LIB_C_FILES = f1.c f2.c f3.c
LIB_H_FILES = f1.h f2.h f3.h
TARGETS = a b c
CFLAGS = -g -O0 -DDEBUG
.PHONY : all clean
.c.o:
g++ -c $(CFLAGS) -o $# $<
all: $(TARGETS)
${TARGETS} : lib.a ${#:%=%.c}
g++ $(CFLAGS) ${#:=.c} -o $# lib.a
lib.a: ${LIB_C_FILES:.c=.o} $(LIB_H_FILES)
ar r $# $?
The library portion works fine. And when an executable does not exist, it also works fine. But when one of the standalone source files is modified it says make: Nothing to be done for 'all'.
I don't understand the proper way to make target a depend on source a.c individually in a list. What am I missing?
Just for completeness: you can do what you want with plain old static pattern rules, so long as you can match all of ${TARGETS} with make's (noddy) pattern matching.
${TARGETS}: %: %.C lib.a
g++ ${CFLAGS} $< -o $# lib.a
lib.a: ...
ar ...
A tad more readable, and perhaps more compatible than .SECONDEXPANSION?
First, I assume fio.a was a typo (you probably meant lib.a).
Second, I think the tricky part is your ${#:%=%.c} prerequisite. AFAIK, $# can't be used this way.
I think you can get the behavior you're looking for using .SECONDEXPANSION though.
Try:
.SECONDEXPANSION:
${TARGETS} : lib.a $$(patsubst %,%.c,$$#)
There may be an old-style substitution way to do this, but I find the patsubst line to be more readable than ${#:%=%.c}.
(I should add that this applies to Gnu make 3.82. YMMV with older versions of Gnu make, or [heaven forbid] non-Gnu versions of make).

Running make from Outside the Tree

Let's say I have a makefile like the following:
CXXFLAGS := -I./Include
Foo:
$(CXX) $(CXXFLAGS) -o Foo
If the user cds into the source tree and runs make, everything is fine and dandy. However, if make is invoked from somewhere outside the source tree, the include directory will be incorrect.
Using full paths instead of relative paths works, but that destroys the portability of the makefile.
Should I just rely on users invoking make "properly?" Or is there an easy way to get around this?
If you want to have CXXFLAGS be -Isome_dir/Include
when the make is invoked asmake -f some_dir/Makefile,
MAKEFILE_LIST
might meet the purpose.
For example:
MAKEFILE_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
CXXFLAGS := -I$(MAKEFILE_DIR)Include
If your make's version is 3.80 or lower, lastword might not work.
In that case,
$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) will work instead.
EDIT: This answer is for GNU-make.
Use the -C flag.
make -C my_dir
You could present your users a compile command that looks like (cd /to/proper/directory && make -k)

Resources