Recovering from an abruptly ended make - makefile

When I compile large programs (like gcc or clang for example) there is a chance that my computer will overheat, and be forced to shut down.
I would like to resume the make process from where I left off. The problem seems to be that there are half completed/written .o files that are floating around that cause the rest of the built to break (this is especially bad when I specify -j 8)
Is there an easy way to get around this problem (whithout doing a make clean or make distclean or the like)?
Using GNU Make 3.81

Along the same lines as Beta's comment, but more reliable and less confusing IMO, would be to change your compile rule so that you compile to a temporary file, then at the end rename it to the real file. So where you might have something like:
%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# -c $<
instead you would use something like:
%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $#.tmp -c $< \
&& mv -f $#.tmp $#
You may or may not want to add a "rm -f $#" as well.
As to whether you can make this change "programmatically" or not, it all dependes on your makefile and how it's structured. If it's a well-formed makefile then you can just make these changes in a few places in a few implicit rules, as above.

Related

Linking inside of pattern rules

I have a generic build system that I import as a Git submodule into my projects, each of which has a wrapper makefile that includes the build system's makefile. Suppose I have something like the following in the build system's makefile:
$(BIN_DIR): | $(BIN_DIR)
$(CC) $(LDFLAGS) -o $# $<
And prerequisites like the following in the projects' makefiles:
$(BIN_DIR)/foo: $(FOO_OBJ_FILES:%=$(OBJ_DIR)/%)
While this technique works well for libraries, it obviously doesn't work well for executables, because each needs to be linked with a different set of libraries. So my question is how to achieve that without relying of GNU Make-specific features? With GNU Make, I could do something like this:
$(BIN_DIR): | $(BIN_DIR)
$(CC) $(LDFLAGS) -o $# $< $((nodir $(basename $#))_LINK:%=-l %)
foo_LINK = mylib1 mylib2
$(BIN_DIR)/foo: $(FOO_OBJ_FILES:%=$(OBJ_DIR)/%)
One portable solution that I've thought of but would rather not use because it's a huge hack, is to have a .link file associated with each executable, containing one line like this: -l mylib1 -lmylib2 and then do something like this:
$(BIN_DIR): | $(BIN_DIR)
$(CC) $(LDFLAGS) -o $# $< `cat $#.link`
So, all these things aside, I need to somehow magically pass the correct set of libraries to the pattern rule or to have a variable expand to the correct set of libraries when the pattern rule gets executed.
Any ideas? Thanks.
PS: I know this seems like more trouble than it's worth but I've simplified things for the purpose of this question. In reality, it saves me from dealing with some pepetition, not just saving me one line.
Okay, I've come up with an answer:
$(BIN_DIR): | $(BIN_DIR)
$(CC) $(LDFLAGS) -o $# $< $($(F)_LINK:%=-l %)
foo_LINK = mylib1 mylib2
Unfortunately, while there is a proposal for adding nested/computed variables into POSIX make for Issue 8 of the specification, it seems to have been in limbo for the past 10 years or so.

Makefile Syntax unclear

This is my first Makefile, and I am can't figure out some of the syntax used. The questions are marked below.
$(BUILD_DIR)/%.o: %.c $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $#
What is the usage of "$(BUILD_DIR)" in the dependency?
What is the meaning of "$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $#" in the role?
As with most computer languages the syntax of make cannot be clear if you don't know it. If you are using GNU make the GNU make manual is your friend. In the following explanations I will assume that BUILD_DIR = build and that one of the source files is bar/foo.c.
$(BUILD_DIR) in the list of prerequisites (dependencies) tells make that the build directory (in which object files are supposed to go) must exist before the recipe is executed; logical. There must be another rule somewhere to create the directory if it does not exist yet. Something like:
$(BUILD_DIR):
mkdir -p $#
But unless you forgot to copy an important character, this dependency is terribly sub-optimal. As the last modification time of a directory changes each time its content changes (files or sub-directories added or removed), it will force the re-compilation of all source files every time the directory changes, which is not what you want. A better dependency would be order-only:
$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
that tells make to consider only the existence of $(BUILD_DIR), not its last modification time, when deciding to re-build or not.
$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $# is just a combination of make automatic variables and functions.
$< and $# expand as the first prerequisite (bar/foo.c) and the target (build/bar/foo.o) respectively.
$(<:.c=.lst) replaces .c by .lst in $<: bar/foo.lst.
$(notdir $(<:.c=.lst)) removes the directory part: foo.lst.
All in all, for a bar/foo.c source file, and with BUILD_DIR = build, the pattern rule would be equivalent to:
build/bar/foo.o: bar/foo.c | build
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=build/foo.lst bar/foo.c -o build/bar/foo.o
Note that there are two different situations to consider:
All your source files are in the same directory as the Makefile (no bar/foo.c, just foo.c). Then you can simplify your recipe:
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(<:.c=.lst) $< -o $#
because the $(notdir...) is useless.
Your source files can be in sub-directories (bar/foo.c). Then you need the $(notdir...) in your recipe. But be warned that if you have two source files with the same base name (bar/foo.c and baz/foo.c) you will have a name conflict for $(BUILD_DIR)/foo.lst and your Makefile will not work as expected. Moreover, the order-only prerequisite of the rule should be equivalent to build/bar (or build/baz), not just build. And there should be a rule to create it if needed. If it is your case I suggest to change your pattern rule for:
$(BUILD_DIR)/%.o: %.c
mkdir -p $(dir $#)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $#
There are other solutions (secondary expansion...) but there are a bit too complicated for this already too long answer.

Variable dependent target in makefile

I have a small project for testing and I want to link different implementations of a solution to test.
So, I create makefile that looks like this
CC=g++
FLAGS=-Wall -O2
CFLAGS=-c $(FLAGS)
I_PATH=implementation1.cpp
all: instance
instance: instance.cpp .implementation.o
$(CC) $(FLAGS) instance.cpp .implementation.o -o $#
.implementation.o: $(I_PATH)
$(CC) $(CFLAGS) $(I_PATH) -o $#
clean:
-rm .implementation*
-rm instance
Here, I_PATH is a path to solution implementation. And I want to test different solution passing different implementation via command line arguments: make I_PATH=implementation2.cpp.
But, because of all my implementations compiled to the same object file .implementation.o, make can't understand that something changes and doesn't rebuild project.
Of course, I can call make clean before run make for a specific implementation. But this increase build time (I can run tests for one implementation many times) and not very comfortable.
I can fix this makefile to something like this:
CC=g++
FLAGS=-Wall -O2
CFLAGS=-c $(FLAGS)
I_PATH=implementation1.cpp
C_PATH := $(shell echo -n $(I_PATH) | md5sum | awk '{print ".implementation_" substr($$1, 0, 10) ".o";}')
all: force instance
force_relink:
touch -c $(C_PATH)
instance: instance.cpp $(C_PATH)
$(CC) $(FLAGS) instance.cpp $(C_PATH) -o $#
$(C_PATH): $(I_PATH)
$(CC) $(CFLAGS) $< -o $#
clean:
-rm .implementation*
-rm instance
Here I create I_PATH dependent object file(take hash of path to implementation) and in addition force re-linking instance.cpp with object file every time make runs.
But maybe there is some mechanism in make to fix this behavior? Or I can achieve the same goal with different approaches?
Wouldn't it make more sense to give each compiled .o file a distinct name, and simply link to the compiled .o file you want?
instance: instance.cpp $(IMPL_O)
$(CC) $(FLAGS) $^ -o $# # propably no need to override default rule
Use make IMPL_O=implementation2.o to generate the example in your question.
This way, the name of each file truly reveals its identity, and you don't have to keep track of anything explicitly.
(Obviously, you could refactor the .o extension into the Makefile itself so you can just say IMPL=implementation2 or whatever.)

Makefile separate directories

It really takes a long time to read the make and gcc manual. Since I just need some basic function of them, I want to learn them quickly.
The project directory is like the following.
CWD
|----Source----1.cpp
|----Header----1.h
|----Object----1.o
|----Makefile
There are three directories and one Makefile in Current Working Directories, and "1.cpp" includes "1.h". I want to use Makefile which is in the CWD to compile the project such that the object output is in Object directory.
This is simplified version of the problem I have now. Since it is relatively hard to begin from scratch, could anyone help me to write a Makefile for this simple problem? And I will try to learn from it and solve my own problem. Or could anyone suggests which parts of make and gcc I need to learn to solve this problem.
Thanks in advance.
This will be enough to compile the source and produce the object:
Object/1.o: Source/1.cpp Header/1.h
$(CXX) -c Source/1.cpp -IHeader -o Object/1.o
If you want to build an executable, maybe called "one", add another rule above that:
one: Object/1.o
$(CXX) Object/1.o -o one
Object/1.o: Source/1.cpp Header/1.h
$(CXX) -c Source/1.cpp -IHeader -o Object/1.o
To clean things up a little, use automatic variables:
one: Object/1.o
$(CXX) $^ -o $#
Object/1.o: Source/1.cpp Header/1.h
$(CXX) -c $< -IHeader -o $#
And if you want to make the second rule more general, so that it can handle more objects you can turn the second rule into a pattern rule and separate the header dependency of 1.o:
one: Object/1.o
$(CXX) $^ -o $#
Object/1.o: Header/1.h
Object/%.o: Source/%.cpp
$(CXX) -c $< -IHeader -o $#
And of course there is a lot more you can do, when you're ready.

How to add different rules for specific files?

I have a certain problem with my Makefile.
With this command, I can compile all my *.c files to *.o which works well:
$(OBJ) : %.o : %.c $(LDSCRIPT) Makefile
$(CC) $(ARM9_INCLUDES) -c $(CFLAGS) $< -o $#
But now I'm wondering, what if I want to run -O3 optimization on just ONE particular file, and have -O0 on the rest?
Is there any command to add a different rule for a specific file?
What I'm doing right now is compiling each C file with its own rules, which is very annoying because I have around 30 files which makes the Makefile huge, and every time I change something in one file it compiles EVERYTHING again.
particular_file.o : CFLAGS+=-O3
(assuming GNU make) see target-specific variable values in GNU Make manual
(and the immediately following pattern-specific variable values, maybe).
Also note, that commands are used from the most specific rule for given file, so you can have in case target-specific variable value is not sufficient:
particular_file.o : particular_file.c
completely_special_compiler -o $# $<
%.o : %.c
$(CC) $(CFLAGS) -o $# $<
It's possible to make the solution a bit more extensible.
Suppose you need to compile one set of files in one way and the other set of files in another way, rather than having only one exception, and you could identify patterns in those two sets of files, e.g. one set starts with "a", and the other set starts with "b", you can do something like this:
a%.o : a%.c
completely_special_compiler -o $# $<
b%.o : b%.c
$(CC) $(CFLAGS) -o $# $<
For more explanation, see Static Patterns.

Resources