3
$\begingroup$

It's possible that this question belongs on Stackoverflow; however, the Mathematica context may be important so I'm asking here first.

I am working on a project to interact with sensors connected to a Raspberry Pi via Mathematica. The first version of the code is here for reference and because of its simplicity, can be compiled with something like:

mcc -o vernier vernier.c vernier.tm -I/usr/include/GoIO -lGoIO

As the project becomes a bit more sophisticated, I decided to implement make. Following the Development guide and adding some tweaks I've learned along the way, I have this Makefile;

SHELL=/bin/bash # for access to shell expansion
CC = gcc
# Setting Wolfram directories
MVER = 10.3
MLINKDIR = /opt/Wolfram/WolframEngine/$(MVER)/SystemFiles/Links/MathLink/DeveloperKit
CADDSDIR = $(MLINKDIR)/Linux-ARM/CompilerAdditions
LIBDIR = $(CADDSDIR)
MPREP = $(CADDSDIR)/mprep
# Flags
CFLAGS = -I/usr/include/GoIO -I$(CADDSDIR)
LIBS = -lGoIO -lm -luuid -lML32i4
# Assume all .h files are dependencies
DEPS = $(shell ls *.h)
__OBJ = $(shell ls *.{c,tm})
_OBJ = $(__OBJ:.c=.o)
OBJ = $(_OBJ:.tm=tm.o)

vernier: $(OBJ)
    $(CC) $(CFLAGS) $^ -L$(LIBDIR) $(LIBS) -o $@

$(ODIR)/%.o: %.c $(DEPs)
    $(CC) -c -o $@ $< $(CFLAGS)

%tm.c : %.tm
    $(MPREP) $? -o $@

# For testing purposes, type `make print-VAR` to get the value of VAR
print-%: ; @echo $* = $($*)

The "nifty" part is searching for template files created with the extension (.tm) and running them through mprep to generate .c files. What surprises me is that if I have this Makefile in the same directory as the aforementioned code (which contains a single vernier.c file with corresponding vernier.tm template), I get a successful compile but the verniertm.c file generated by mprep is deleted at the end! I do not object, since it is a temporary file anyway; however my question is, what causes this behavior?

$\endgroup$

1 Answer 1

5
$\begingroup$

It's a feature of make, see the manual for Chains of Implicit Rules.

Intermediate files are remade using their rules just like all other files. But intermediate files are treated differently in two ways.

The first difference is what happens if the intermediate file does not exist. If an ordinary file b does not exist, and make considers a target that depends on b, it invariably creates b and then updates the target from b. But if b is an intermediate file, then make can leave well enough alone. It won’t bother updating b, or the ultimate target, unless some prerequisite of b is newer than that target or there is some other reason to update that target.

The second difference is that if make does create b in order to update something else, it deletes b later on after it is no longer needed. Therefore, an intermediate file which did not exist before make also does not exist after make. make reports the deletion to you by printing a ‘rm -f’ command showing which file it is deleting.

For preventing deletion of intermediate files, see the documentation of the .PRECIOUS or .SECONDARY special targets (the second one might be specific to GNU make).

$\endgroup$
1
  • $\begingroup$ That's good enough for a necromancer badge :-) $\endgroup$ Jan 27, 2018 at 21:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.