Running make from Outside the Tree - directory

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)

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) $# $?

How to define a rule with a recursive recipe in GNU make?

I want to call make files in subfolders from one top make file.
An example of my top make file that works looks like this, where buildPath is a parameter in to the make script:
.PHONY: testSystem
testSystem:
$(MAKE) all -C $(buildPath)/Test1Build
$(MAKE) all -C $(buildPath)/Test2Build
$(MAKE) all -C $(buildPath)/Test3Build
The problem with this solution is that I have to list all subfolders; Test1Build, Test2Build, Test3Build etc.
Is there a way (with make) to define this rule in such a way that the subfolders in the receipt are recursively found without having to list them all?
...or can I solve this problem in a totally different way?
All subfolders begins with Test and ends with Build as a pattern.
It's not hard at all. One simple way:
testSystem:
for d in $(buildPath)/*/.; do \
$(MAKE) all -C $$d; \
done
However, that has many problems. Much more reliable and robust will be this:
subdirs := $(wildcard $(buildPath)/*/.)
testSystem: $(subdirs)
$(subdirs):
$(MAKE) -C $# all
.PHONY: testSystem $(subdirs)
One caveat: if you use parallel make (-j) then you may run into problems with the second solution if the results of the subdirectories depend on each other. If they do then you'll have to declare these dependency relationships in your makefile:
$(buildPath)/foo/. : $(buildPath)/bar/.
etc.

Passing rules to make recursively

It's probably trivial to do this but I can't see how.
I want to have a parent Makefile to decide which Makefile to call recursively based on the value of a variable passed in the command line.
I.e., I want to be able to call my main Makefile with:
make some_rule TARGET=a
or
make some_rule TARGET=b
and have my main Makefile decide based on the value of TARGET which makefile to invoke to run make some_rule. (For example, decide whether to call sub_directory_a/Makefile or sub_directory_b/Makefile to execute rule some_rule.)
Note: I have many different rules, so I do not want my main Makefile to list all the possible rules and for each of them call recursively the correct Makefile. I am hoping my main Makefile can only be a few lines long and not have to be updated whenever I create new rules.
You could do what you describe with
default_target:
%:
$(MAKE) -C some_directory_$(TARGET) $#
The %: rule is a pattern rule in which the pattern matches all rules (called a match-anything rule by the GNU make manual); $# is the current target. Note that the default_target: rule doesn't have a recipe, so calling make without a target will use the recipe of the match-anything rule (the only one that applies and has a recipe) to try to build default_target.
The caveat of this approach is that targets cannot be declared phony. If you want to have phony targets, you'll have to specify the recipe for those targets again, for example
PHONY_TARGETS = all clean distclean
.PHONY: $(PHONY_TARGETS)
$(PHONY_TARGETS):
$(MAKE) -C some_directory_$(TARGET) $#
%:
$(MAKE) -C some_directory_$(TARGET) $#
Unfortunately, I do not know a trick to declare all targets phony, which is what you'd really want to do.
Note that you can use ifeq etc. with the variables you set at the command line if you want to allow more fancy values for TARGET than parts of directory names, such as
%:
ifeq ($(TARGET),gibson)
echo 'Planet $# was successfully hacked.'
else
$(MAKE) -C some_directory_$(TARGET) $#
endif
Also note that a more common way to set common variables for many Makefiles is to put them into a file, often common.mk, and include it from the other Makefiles:
include ../common.mk # to include common.mk from some_directory_a/Makefile
But you'll have to decide yourself which approach is a better fit for your project.

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).

ar on an existing .a file?

Essentially, what I want to do is this:
gcc foo.c -o foo.o
ar rcs foo.a foo.o
gcc bar.c -o boo.o
ar rcs bar.a bar.o foo.a
I want to archive both an object and a static library into another static library. Unfortunately, the last command doesn't end up containing foo.o (it contains bar.o and foo.a), so when I get to the linking stage, the linker can't find the symbols from foo.o.
Is there a way to do what I want here? I'm doing all of this out of make, so I'm looking for a solution that doesn't involve extracting & re-archiving the objects (which seems kinda painful). Is there a way to make this kind of "archive from another archive" setup work?
Actually, you do not want to archive one whole '.a' file inside another. You might want to archive the members of the one archive in the other - but that is a wholly different operation.
The 'ar' program is perfectly capable of storing source files, gzipped tar files, HTML files, XML files, and pretty much any other type of file in the '.a' (and the '.a' suffix is only conventional, not mandatory) -- try it some time. However, it treats object files (and only object files) specially, and makes them available for use by the linker ('ld'), but the linker only uses such files if the extension is '.a'.
So, you want to have two libraries:
foo.a containing just foo.o
bar.a containing bar.o and all the objects from foo.a
Short of doing as you suggest and extracting the objects from foo.a and building them into bar.a, the only alternative is to list the members of foo.a as members of bar.a too:
FOO_OBJS = foo.o
BAR_OBJS = bar.o $(FOO_OBJS)
foo.a: $(FOO_OBJS)
$(AR) $(ARFLAGS) $# $(FOO_OBJS)
bar.a: $(BAR_OBJS)
$(AR) $(ARFLAGS) $# $(BAR_OBJS)
I am assuming that your example is minimized. If it is not, then why bother with two libraries. Anything that uses just code from foo.o will only link foo.o even if given bar.a to link with. (It would be slightly different if these were shared objects, but it would probably still be better to use just one rather than two shared objects.)
ar rcs foo.a foo.o
cp foo.a foo2.a
gcc -c bar.c
ar rs foo2.a bar.o
And perhaps use foo.a instead of foo2.a if you don't need to keep it in its original form.

Resources