Make rebuilding without any modifications - makefile

I've started writing a couple of simple tests for a library. I am currently trying to write a make target called btests that is supposed to compile them all.
The tests reside in the tests/ directory in the form of simple .cpp files which #include the library.
The makefile's task is simple: compile each tests/name.cpp into an executable tests/name file which has been linked with the library.
And it works fine, except one thing: each time I run make btests, tests get recompiled. However, they should recompile only if they have been changed or the library itself has been changed.
This is the relevant code:
CC=g++
CFLAGS=-Wall
SRCPATH=source
OBJPATH=object
TESTPATH=tests
OBJ=$(OBJPATH)/nameb.o $(OBJPATH)/hebbann.o
INF=$(SRCPATH)/nameb.hpp $(SRCPATH)/hebbann.hpp
TESTS=$(TESTPATH)/test_api $(TESTPATH)/test_speed
all : libname.a
libname.a : $(OBJ)
ar rvs libname.a $(OBJ)
$(OBJ) : $(OBJPATH)/%.o : $(SRCPATH)/%.cpp $(SRCPATH)/%.hpp
$(CC) $(CFLAGS) -c $< -o $#
btests : $(TESTS)
$(TESTS) : % : %.cpp all
$(CC) $(CFLAGS) $< -L. -lname -o $#
install : all
mkdir -p /usr/include/name
cp $(INF) /usr/include/name
cp libname.a /usr/lib
pack : all
mkdir -p name/
cp $(INF) name/
tar -cvf libname.tar name/ libname.a doc/ source/
clean :
rm -f $(OBJPATH)/* libname.a libname.tar $(TESTS)
How can I force make to recompile only when something has changed?

Your tests depend on all. Since there is no file called "all", Make concludes that it must be rebuilt, and so must the tests that depend on it.
The fix is simple. The rule for all does nothing but require libname.a, so just cut out the middleman:
$(TESTS) : % : %.cpp libname.a
$(CC) $(CFLAGS) $< -L. -lname -o $#

Related

build directory with Makefile - compiles everytime

I have 3 files in my directory as follows:
foo.h
foo.cc
main.cc
build/ <-- Created if doesn't exist.
I want the .o and executable files to be generated in a build folder in the same directory.
I also don't want the code recompiling if nothing has changed.
Here is my Makefile:
CC=g++
CFLAGS=-std=c++17
OBJS=build/foo.o
.PHONY: all clean
all: build/main
build/main: main.cc $(OBJS)
$(CC) $(CFLAGS) -o $# $^
build/%.o: %.cc build
$(CC) $(CFLAGS) -c -o $# $<
build:
mkdir -p build
clean:
rm -rf build
If I run make build/foo.o, it doesn't re-compile if nothing has changed in the source code.
But make all or make build/main always re-compiles everything. What am I doing wrong?
I don't have this issue if I output the compiled code in the same directory.
Ugh, just minutes after posting this, I found the answer on Google.
Problem is that because the build directory timestamp gets updated even if one file in the directory is created/updated, it will rebuild always from scratch.
There are several approaches listed in the link above to fix it. I ended up just adding a pipe (|) operator to the build rule to make it an order-only pre-requisite. i.e. this line:
build/%.o: %.cc |build
$(CC) $(CFLAGS) -c -o $# $<
and that seems to have fixed it :|

GNU Make reports no rule when dealing with a target under subdirectory with source from another directory

My project's directory is mounted via NFS. From the directory under which it is mounted, I call make -f msh/Makefile cd=msh. (msh is my mount.) cd is a variable in the Makefile that is prepended to source files. This works fine with source files directly under cd. However, if the source files are under a subdirectory within cd, Make fails, saying that there is no rule to make that target. It does not fail if I call Make from within my mount.
This is my Makefile.
CC?=gcc
CFLAGS:=-Wall -Werror -D_POSIX_C_SOURCE=200112L $(CFLAGS)
cd?=.
objects_nix=if/tty.o
objects:=sub.o if.o $(objects_nix)
ifdef SO
CFLAGS+=-fPIC
bin=libmsh.so
else
bin=libmsh.a
endif
.PHONY : clean
$(bin) :
libmsh.a : $(objects)
$(AR) -r -c -s $# $(objects)
libmsh.so : $(objects)
#echo
#echo If you have resumed compilation after not having used the SO flag,
#echo you should run make clean.
#echo
$(LD) $(LDFLAGS) -shared -o $# $(objects)
test : $(cd)/test.c $(bin)
ifdef SO
$(CC) $(CFLAGS) -I$(cd) $(LDFLAGS) -L. -lmsh -Wl,-rpath,. -o $# $(cd)/test.c
else
$(CC) $(CFLAGS) -I$(cd) $(LDFLAGS) -o $# $(cd)/test.c $(bin)
endif
%.o : $(cd)/%.c
$(CC) $(CFLAGS) -c -o $# $<
clean :
rm -f libmsh.so libmsh.a
rm -f $(objects)
rm -f test.o test
I have tried creating another rule for the subdirectory, and this works. But I'd like it to work with only the one rule.
You have told Make how to make a .o file from .c file in $(cd). It does not know how to make a .o file if the .c file in some other directory. You can solve this in various ways, such as:
Add an explicit rule for all directories. You have already done that.
Use VPATH.
Create a Makefile for each directory.

Makefile - link input file from folder

I try to compile a project with generated object stored in a sub directory :
myproject:
|
src: .cpp, .cpp ...
|
release: .o, .o ...
Here's a part of Makefile:
SRC ?= src
OBJ_PATH = $(SRC)/Release
vpath %.o $(OBJ_PATH)
...
OBJS := $(addprefix $(OBJ_PATH)/,obj1.o obj2.o )
all: build
obj1.o: $(SRC)/Manager.cpp
$(EXEC) $(CC) $(INCLUDES) $(CCFLAGS) $(GNCD_FLGS) -c $(<) -o $(OBJ_PATH)/$# #-o $# -c $<
obj2.o: $(SRC)/Synth.cpp
$(EXEC) $(CC) $(INCLUDES) $(CCFLAGS) $(GNCD_FLGS) $(DEFS) -c $(<) -o $(OBJ_PATH)/$# #-o $# -c $<
myApp: obj1.o obj2.o
$(EXEC) $(CC) $(LDFLAGS) $(GNCD_FLGS) -o $# $(OBJS) $+ $(LIBS)
$(EXEC) mkdir -p $(OBJ_PATH)/$(TRGT_ARCH)/$(TRGT_OS)/$(BLD_TP)
$(EXEC) cp $# $(OBJ_PATH)/$(TRGT_ARCH)/$(TRGT_OS)/$(BLD_TP)
$(OBJECTS) : Stt.h
build: myApp
run: build
$(EXEC) ./myApp
..but i got an error link:
Could not open input file 'obj1.o'
Makefile:86: recipe for target 'myApp' failed
So it seems couldn't find object in src/Release dir;
any ideas ?
thank's
Your recipe for myApp use $+, which list the prerequisites. It expands in obj1.o obj2.o. But you build obj1.o and obj2.o in $(OBJ_PATH). So the linker try to find the objects in the root directory, but cannot find them, since they are in $(OBJ_PATH).
Since your recipe explicitely lists them (with $(OBJS)), you do not need the automatic variable.
Sidenote
According to Paul's Second rule of Makefiles, it is best that every rule updates a file corresponding exactly to the target name (including the path part) (in other words, always use $# in the recipe), in order to always know which is the exact file updated.
In your case, if you want to build the objects files in OBJ_PATH, you could use a rule of the form $(OBJ_PATH)/obj.o for each.
You could also replace the dependency of myApp by $(OBJS), and use the automatic variable (btw, is there a reason why you prefer $+ over $^ (does the same thing but do not conserv duplicates in the prerequisites list) ?).

How to write a makefile for Fortran with modules?

gg=mpif90
DEPS=matrix.mod
OBJ= main.o sub1.o
main.out: $(OBJ)
$(gg) -o $# $^
%.mod:%.90 %.o
$(gg) -c -o $# $^
%.o:%.f90 $(DEPS)
$(gg) -c -o $# $^
.PHONY: clean
clean:
-rm -f *.o *~
Look. The main program is main.f90.sub1.f90 will be called by main.f90. Both will use matrix.f90 which is a module. I know I can directly generate the executable program without compile then link. But I do not like that way.
The mod file is only a by-product of compiling %.o, you shouldn't use -o $# here, change it to
%.mod: %.90
$(gg) -c $^
This will work for most cases, but not all. That's because the name of mod file depends only on the module name, it has nothing to do with the source file name. So the safest way is to specify the dependency explictly.
matrix.mod: matrix.f90
$(gg) -c matrix.f90
Sometimes one f90 source file can contain two or more modules.
matrix33.mod matrix99.mod: matrix.f90
$(gg) -c matrix.f90

How to create directories from makefiles?

Could you help me with the following code I have written?
VPATH= balll mall fall
OBJECTS= objj/goka.o objj/foka.o objj/hoka.o
exec/gola: $(OBJECTS)
gcc $^ -o $#
$(OBJECTS): objj/%.o : %.c
gcc -c $< -o $#
What I want to do is: I don't have exec directory and obj directory and I want them to be created during the compiling of the file and save those files in their respective directories. Can I do that? Creating the directory exec and telling the gcc to save the gola target file in exec directory and same with the objective files.
Is there any command to deal with it?
Try order-only prerequisites. (See the make manual).
Just add mkdir -p dir1 dir2 to the appropriate rule of your makefile, prior to compilation.
Example: (You'll have to modify this for your particular setup)
DIR = obj exec
VPATH= balll mall fall
OBJECTS= objj/goka.o objj/foka.o objj/hoka.o
exec/gola:$(OBJECTS)
gcc $^ -o $#
$(OBJECTS): objj/%.o : %.c
mkdir -p $(DIR)
gcc -c $< -o $#

Resources