Avoid gnu make automatic file deletion - makefile

GNU make is deleting my object files automatically. I don't understand why...
My goal is small test programs generation, hence each source file is an independent program which uses no other module.
My makefile is:
# This makefile is written for Windows cmd shell
SHELL=C:\Windows\System32\cmd.exe
# FILES
SRCS=$(wildcard src/*.cpp)
BINS=$(patsubst %.cpp,bin/%.exe,$(notdir $(SRCS)))
all:compile
obj/%.o:src/%.cpp
g++ -Wall -Wextra -std=gnu++11 -m64 -D_WIN32_WINNT=0x0400 -c -o $# $<
bin/%.exe:obj/%.o
g++ -Wall -Wextra -std=gnu++11 -m64 $^ -o $#
clean:
if exist obj\*.o del /Q obj\*.o
mrproper:clean
if exist bin\*.exe del /Q bin\*.exe
compile:$(BINS)
rebuild:clean all
.PHONY:all compile clean mrproper rebuild
Running GNU make with, for instance, a single source file does as follows:
g++ -Wall -Wextra -std=gnu++11 -m64 -D_WIN32_WINNT=0x0400 -c -o obj/Tester.o src/Tester.cpp
g++ -Wall -Wextra -std=gnu++11 -m64 obj/Tester.o -o bin/Tester.exe
rm obj/Tester.o
Why is my object file deleted?
How to avoid it?
If I replace either obj/%.o:src/%.cpp by obj/Tester.o:src/Tester.cpp or bin/%.exe:obj/%.o by bin/Tester.exe:obj/Tester.o the file Tester.o is not deleted, but this is not what I need.

Since you use implicit rule (such as ‘%.o’), object file will be delete after make.
Add special target .PRECIOUS to protect it.
.PRECIOUS: obj/%.o
Reference:
Special Built-in Target Names
Chains of Implicit Rules

After reading the links yihsiui provides, I come with another answer to my own question.
The object files are deleted because they don't exist and the rules I wrote made them intermediate. To avoid them to be flagged as intermediate, they must be an explicit target in some rule. I still need the pattern rule to generate the object file because I use the pattern substitution to compute the name of the object file. So, why not simply add an "empty" rule?
OBJS=$(patsubst %.cpp,obj/%.o,$(notdir $(SRCS)))
(...)
$(OBJS):

Related

Dynamic library cannot load when running program outside build directory

I have the following Makefile:
OBJ=main.o other.o other1.o other2.o
LINKDIVSUF=-L libdivsufsort-master/build/lib/ -ldivsufsort64 -Wl,-R libdivsufsort-master/build/lib/
INCDIVSUF=-I libdivsufsort-master/build/include -ldivsufsort64
EXE=program
COMPFLAGS=-MMD -fopenmp -std=c++17 -O3
CXX=g++
$(EXE):$(OBJ)
$(CXX) $(COMPFLAGS) $(OBJ) -o $(EXE) $(LINKDIVSUF) -lz -lboost_regex -lboost_program_options
%.o: %.cpp
$(CXX) $(COMPFLAGS) $(INCDIVSUF) -c $<
-include $(OBJ:.o=.d)
The program links to a dynamic library, libdivsufsort64.so.3, located from the build directory at ./libdivsufsort-master/build/lib/.
Use of -Wl,-R libdivsufsort-master/build/lib/is to avoid having to concatenate absolute/path/to/libdivsufsort-master/build/lib/ to LD_LIBRARY_PATH in order to run program. Indeed, when I make program
without -Wl, -R libdivsufsort-master/build/lib/, and without setting the LD_LIBRARY_PATH as mentioned and subsequently run program, I get the following error message:
./program: error while loading shared libraries: libdivsufsort64.so.3: cannot open shared object file: No such file or directory
With -Wl, -R libdivsufsort-master/build/lib/, program runs successfully with no alteration to LD_LIBRARY_PATH, but only when
I run program from the same directory in which it was built.
If I try to run program when compiled with -Wl, -R libdivsufsort-master/build/lib/ from any other directory, it fails to run, terminating with
the aforementioned error message.
How can I change the g++ compilation options (or anything else at compilation time) to enable program to run from
any directory whilst avoiding the need to alter LD_LIBRARY_PATH? The only "solution" I have found is to concatenate libdivsufsort-master/build/lib/ to LD_LIBRARY_PATH. By doing so, I can run program from any
directory, thus removing the need to compile with Wl,-R libdivsufsort-master/build/lib/, however, this of course requires the user of program to manually set their LD_LIBRARY_PATH, which I specifically want to avoid.
Solution
Reading this post that discusses the use of relative or absolute paths with -R (-rpath) I came up with this solution.
Append the following lines, such that the Makefile is now:
libdivsufsort_lib = $(addprefix $(shell pwd), /libdivsufsort-master/build/lib/)
libdivsufsort_include = $(addprefix $(shell pwd), /libdivsufsort-master/build/include/)
OBJ=main.o other.o other1.o other2.o
LINKDIVSUF=-L libdivsufsort-master/build/lib/ -ldivsufsort64 -Wl,-R libdivsufsort-master/build/lib/
INCDIVSUF=-I libdivsufsort-master/build/include -ldivsufsort64
EXE=program
COMPFLAGS=-MMD -fopenmp -std=c++17 -O3
CXX=g++
$(EXE):$(OBJ)
$(CXX) $(COMPFLAGS) $(OBJ) -o $(EXE) $(LINKDIVSUF) -lz -lboost_regex -lboost_program_options
%.o: %.cpp
$(CXX) $(COMPFLAGS) $(INCDIVSUF) -c $<
-include $(OBJ:.o=.d)
This avoids the use of $ORIGIN, to produce an absolute path to programs
directory, which is not supported on some systems. The two additional
lines produce the absolute path irrespective of the binary's location -
it just needs to kept in the build directory and compiled again if the build
directory moves. Importantly, program can now be called from outside the
build directory.
You need to use $ORIGIN with -Wl,-R to locate the library in relative path:
LINKDIVSUF = ... -Wl,-R,'$ORIGIN/libdivsufsort-master/build/lib'

Makefile pattern rule with multiple targets

Below is my makefile:
src/config-comp/%.o: ../src/config-comp/%.c
#echo 'Building file: $<'
#echo 'Invoking: GCC C Compiler'
gcc-4.8 -std=gnu11 -DDEBUG=$(DEBUGOPT) -I"$(ROOT_DIR)/../.local/include" -O0 -g3 -Wall $(GPROF) -c -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
#echo 'Finished building: $<'
#echo ' '
In src/config-comp, I have two C source files, one is config-comp.c and the other one is config-proxy.c. I read GNU make book saying that
"If a pattern rule has multiple targets, make knows that the rule’s
recipe is responsible for making all of the targets. The recipe is
executed only once to make all the targets."
However, my output is as following:
Building file: ../src/config-comp/config-comp.c
Invoking: GCC C Compiler
gcc-4.8 -std=gnu11 -DDEBUG=0 -I"/home/cheng/crane/libevent_paxos/target/../.local/include" -O0 -g3 -Wall -c -MMD -MP -MF"src/config-comp/config-comp.d" -MT"src/config-comp/config-comp.d" -o "src/config-comp/config-comp.o" "../src/config-comp/config-comp.c"
Finished building: ../src/config-comp/config-comp.c
Building file: ../src/config-comp/config-proxy.c
Invoking: GCC C Compiler
gcc-4.8 -std=gnu11 -DDEBUG=0 -I"/home/cheng/crane/libevent_paxos/target/../.local/include" -O0 -g3 -Wall -c -MMD -MP -MF"src/config-comp/config-proxy.d" -MT"src/config-comp/config-proxy.d" -o "src/config-comp/config-proxy.o" "../src/config-comp/config-proxy.c"
Finished building: ../src/config-comp/config-proxy.c
This means the recipe has been executed two times, right? But according to the quote above, it should be executed only once.
Multiple targets means something like:
%.foo %.bar: %.c
And your rule will be responsible for making both *.foo and *.bar. The single execution applies to targets that have the same stem: if baz.foo and baz.bar both have to be made, the rule will only be executed once, but if baz.foo and blargh.bar have to be made it will be executed two times (for the stems baz and blargh).
In your case you have a single target (src/config-comp/%.o), so it'll be executed for every object file you build (which is what you want most of the time).

Why wouldn't make not execute a simple line in the makefile

This is my first time using make, and i've been spinning my wheels trying to get past an issue. I can't understand why a simple echo never gets executed:
CFLAGS = -Wall
LDFLAGS = -g
CC = gcc
SRCS = p4a.c p4b.c
p4static: p4a.c
gcc $(LDFLAGS) -o $# $< -static -L. -lpthread
p4dynlink: p4a.c
#echo "this doesn't print/echo/execute"
gcc $(LDFLAGS) -o p4dynlink $< -L. -lpthread
I'm using tab instead of spaces. Here is the outputs:
mike#elementary:~/p4$ make
gcc -g -o p4static p4a.c -static -L. -lpthread
mike#elementary:~/p4$ make
make: `p4static' is up to date.
From How make Processes a Makefile:
By default, make starts with the first target (not targets whose names start with ‘.’). This is called the default goal. [....]
Thus, when you give the command:
make
make reads the makefile in the current directory and begins by processing the first rule.
So when you type make make tries to build your p4static target which doesn't have an echo line. And the next time you run make it says that target is up to date and has nothing to do.
To build p4dynlink you need to tell make to build that target make p4dynlink.
You can set the default goal manually (in the makefile) with .DEFAULT_GOAL:
# Set our own.
.DEFAULT_GOAL := foo
But convention is usually to create an all target as the first target and have it "Do the Right Thing" by default.
So in your case, assuming you wanted both targets built by default, you would use:
all: p4static p4dynlink

GNU make unexpected behaviour

I want make to build all .cpp in the directory with tracking header changes. I attempt to do it by first making gcc output a target with dependencies with -MM option and then append the body to that target that will actually call the compilation:
OPTIONS = -std=c++11 -Wall
export
all : $(patsubst %.cpp, %.o, $(wildcard *.cpp))
%.o : %.mkt
make -f $*.mkt
%.mkt : %.cpp
gcc $(OPTIONS) -MM $*.cpp > $&.mkt1
echo gcc $(OPTIONS) -c %.cpp > $*.mkt2
cat $*.mkt1 $*.mkt2 > $*.mkt
Yet somehow this script issues the calls of the form
g++ -c -o something.o something.cpp
for each .cpp file in the directory. The temporary files .mkt1, .mkt2 and .mkt are not created. Why does this happen? How do i achive desired behaviour? I'm doing this on windows with mingw.
You have supplied a chain of two pattern rules (%.cpp->%.mkt, %.mkt->%.o), but Make already has a single implicit rule (%.cpp->%.o) which it will find first, when searching for a way to build something.o.
The simplest way to solve the problem is to use make -r (or make --no-builtin-rules) which will disable the built-in implicit rule.

What is the best approach to use different CFLAGS for the same source files?

i need to build the same source tree twice,
1 - with normal cflags to build the project binary
2 - with cflags plus -fPIC to build a static library that would be some sort of SDK to develop project dynamic modules.
Using only one Makefile, what is the best approach to accomplish this?
It would be nice to do some sort of :
all: $(OBJECTS)
lib_rule: $(OBJECTS)
CFLAGS += -fPIC
.cpp.o:
$(CC) -c $< -o $# $(CFLAGS)
But obviously it can't be done.
Thanks
One thing I've used in the past is a different extension:
.cpp.o:
$(CC) -c $< -o $# $(CFLAGS)
.cpp.lo:
$(CC) -c $< -o $# $(CFLAGS) $(EXTRA_CFLAGS)
You then build your static library from the .lo files and you binary from the .o files:
prog: a.o b.o
libsdk.a: a.lo b.lo
Assuming you are using GNU Make, you can use some built in functions to only have to maintain the list of objects one time:
OBJS = a.o b.o
LOBJS = $(patsubst %.o, %.lo, $(OBJS))
GNU make offers also "Target-specific Variable Values". Consider the following Makefile:
# Makefile
CFLAGS := My Cflags
all: $(OBJECTS)
#echo "$# CFLAGS is: " $(CFLAGS)
lib_rule: CFLAGS += extended by -fPIC
lib_rule: $(OBJECTS)
#echo "$# CFLAGS is: " $(CFLAGS)
# Makefile - end.
$ make all
all CFLAGS is: My Cflags
$ make lib_rule
lib_rule CFLAGS is: My Cflags extended by -fPIC
$
(Please note: if you copy and paste the example, remember to re-add the tabstops in front of the command lines. I always get caught by that.)
Instead of placing the compiled .o files in the same directory as the source, I create them in labeled sub-directories. In your case, you can have the static library files created as source_dir/lib/*.o and your normal files as source_dir/bin/*.o. In your different build targets after you set up your unique CFLAGS, simply generate a DIR_NAME value holding the name of the appropriate sub-folder. You can use this variable when you create the paths for the compiler to use when building and when linking.
In a different make tool such as CMake, you can express something like that much more easily.
For instance, you could well do
set(sources ABC.cpp DEF.cpp XYZ.cpp)
ADD_LIBRARY(mylib STATIC ${sources})
add_executable(myExecutable ${sources} main.cpp)
Or, you could repeatedly build the same directory with different flags by including it several times from the directory's logical parent, i.e.
set(MyTweakFlag 2)
add_subdirectory("libDir" "libDir2")
set(MyTweakFlag 3)
add_subdirectory("libDir" "libDir3")
...and then use if() or whatnot in the child directory to set the right flags.
Particularly if you have many such configurations, using make becomes quite fragile; make won't correctly find the transitive closure of recursive make dependancies (and certainly won't correctly find the dependancy on the makefile itself - if you change flags, say) so if you're going to do complicated makefile magic: do it with a better tool!
(CMake simply happens to be what I replaced make with, but there are various other replacements possible, of course)

Resources