In makefiles, how can I compile module files first using automatic variables? - makefile

I am new to makefiles. My current makefile looks like this:
FC=ifort
FFLAGS=-c -module mod/
LDFLAGS=
SOURCES=$(wildcard src/*.f90)
OBJECTS=$(addprefix obj/, $(notdir $(SOURCES:.f90=.o)))
EXECUTABLE=RUN
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(FC) $(LDFLAGS) $^ -o $#
obj/%.o: src/%.f90
$(FC) $(FFLAGS) $< -o $#
The problem is my module files have names start with s and p which are usually compiled in the end of the list, and this causes problems when I have some changes in these module files. I am wondering what is the easiest way to compile these module files first? Yes I can change my module file directory to mod/ and set variables:
MODULES=$(wildcard mod/*.f90)
MODULE_OBJECTS=$(addprefix obj/, $(notdir $(MODULES: .f90=o)))
then add
$(MODULE_OBJECTS):$(MODULES)
$(FC) $(FFLAGS) $< -O $#
But, is there other ways to do this?

Related

How to use a makefile with gprof to recompile dependencies?

I have a makefile which compiles and links together objects to create an executable. In order to profile, I need to use an additional flag -pg before compiling. Here is my current makefile:
# objects required
OBJS = obj1.o obj2.o
# flags
FC = gfortran
FLAGS = -O3
PROFILEFLAG = -pg
# executable
EXE = program.exe
PROFEXE = program_prof.exe
# suffixes
.SUFFIXES: .o .f90
# rules
%.o: %.f90
$(FC) $(FLAGS) -c $<
default: $(OBJS)
$(FC) $(FLAGS) $(OBJS) -o $(EXE)
profile: $(OBJS)
$(FC) $(FLAGS) $(OBJS) -o $(PROFEXE) $(PROFILEFLAG)
clean:
rm *.o *.mod
Running make profile runs the rule associated with profile, which creates the executable program_prof.exe which can be profiled. However, since the individual dependencies obj1 and obj2 are not compiled with the -pg flag, I cannot profile the code running in those files.
Is there a way I can add a rule such that the individual objects are also recompiled with the -pg flag when I need to profile?
Currently I am editing the individual object dependencies manually to:
%.o: %.f90
$(FC) $(FLAGS) -c $< -pg
which works as expected, but is time consuming (my actual makefile has multiple dependencies in subfolders, all of which need to be edited). Ideally, I am looking for a rule which should recompile individual objects with the `-pg' flag.
You can do exactly what you want, with target-specific variables:
PROFILE :=
%.o : %.f90
$(FC) $(FLAGS) $(PROFILE) -c -o $# $<
default: $(OBJS)
....
profile: PROFILE := -pg
profile: $(OBJS)
....
However, this is not usually the preferred way. Unless you're really diligent about always doing a full clean when switching back and forth between profile and non-profile builds it's very easy to get confused and have some objects compiled with profiling and others compiled without.
As mentioned in the comments, it's better to build them into separate directories:
$(PDIR)/%.o : %.f90
#mkdir -p $(#D)
$(FC) $(FLAGS) -pg -c -o $# $<
$(ODIR)/%.o : %.f90
#mkdir -p $(#D)
$(FC) $(FLAGS) -c -o $# $<
default: $(addprefix $(ODIR)/,$(OBJS))
$(FC) $(FLAGS) $^ -o $#
profile: $(addprefix $(PDIR)/,$(OBJS))
$(FC) $(FLAGS) -pg $^ -o $#

Makefile executable not generated

CC=g++
CFLAGS=-c -o
PROG=craps
LIBSRCS=craps.cpp craps_game.cpp craps_helper.cpp craps_io.cpp
LIBOBJS=$(patsubst %.cpp, %.o, $(LIBSRCS))
LIBCRAPS=craps
CXXFLAGS=-I./ -fpic
LDFLAGS=-L./
all: $(PROG)
$(PROG): $(LIBSRCS)
$(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o
$(LIBCRAPS): $(LIBOBJS)
$(CC) -shared -o lib$(LIBCRAPS).so $(LIBOBJS)
%.o: %.cpp
$(CC) $(CXXFLAGS) -c -o $# $
depend:
${CC} -MM ${PROG}.cpp ${LIBSCRS} > depends.mak
include depends.mak
Why executable file not compiled and generated?
All o files generated with no error.
Why this line $(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o does not run ? what is wrong ?
You misunderstood my comment. I'm saying this this:
PROG=craps LIBSRCS=craps.cpp craps_game.cpp craps_helper.cpp craps_io.cpp
is wrong. You can't assign two variables on the same line, in a makefile. These variables must look like this:
PROG=craps
LIBSRCS=craps.cpp craps_game.cpp craps_helper.cpp craps_io.cpp
I'm asking, is the latter how your actual makefile looks, or is the example you provided here just inaccurate.
Also these rules both have incorrect newlines:
$(PROG):
$(LIBSRCS) $(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o
$(LIBCRAPS):
$(LIBOBJS) $(CC) -shared -o lib$(LIBCRAPS).so $(LIBOBJS)
You are adding the prerequisite lists $(LIBSRCS) and $(LIBOBJS) into the recipe (shell commands) used to build the target. Prerequisites must be on the same line as the target. These should look like this:
$(PROG): $(LIBSRCS)
$(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o
$(LIBCRAPS): $(LIBOBJS)
$(CC) -shared -o lib$(LIBCRAPS).so $(LIBOBJS)
This is your problem, below
Finally, you can't have both the program and the target have the same name:
PROG=craps
LIBCRAPS=craps
You can only create one target with a given name so the value of both these variables cannot be craps. Maybe you wanted:
PROG = craps
LIBCRAPS = libcraps.so
Assuming the makefile you've quoted here is identical to what you're running, you must be getting warnings like this from make when you run this makefile:
Makefile:15: warning: overriding recipe for target 'craps'
Makefile:12: warning: ignoring old recipe for target 'craps'
These warnings are why you are not seeing the compile rule invoked: the library rule is overriding it just as the warning says.
Also, you should have the program depend on the library (since it links it) and the object file $(PROG).o because currently make doesn't know it needs to be built. And you don't need to have it depend on all the source files. You want something like:
$(PROG): $(LIBCRAPS) $(PROG).o
$(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o

How do you call a rule that involves `%` from another rule in a Makefile?

I have the following makefile snippet to compile my C++ project.
obj/%.o: src/%.cpp
$(CXX) $(CFLAGS) -c $< -o $#
Now I want to link the .o files. But I want to be able to just call the rule name of the link, like make build/main, in order to compile AND link.
Neither this:
build/main: $(wildcard obj/*.o)
$(CXX) $^ -o $#
works, as it only links and does not compile, as I would expect by this answer;
nor this:
build/main: obj/%.o
$(CXX) $^ -o $#
with the error:
No rule to make target 'obj/%.o', needed by 'build/main'. Stop.
even though it is needed.
SOURCES := $(wildcard src/*.cpp)
OBJECTS := $(patsubst src/%.cpp, obj/%.o, $(SOURCES))
build/main: $(OBJECTS)
$(CXX) $^ -o $#

What does the target ".cpp.o:" mean in a Makefile?

I'm learning the GNU makefile. I came across this page: http://mrbook.org/blog/tutorials/make/
At the end of this article, I found this:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Could anyone explain what's in OBJECT variable and what target .cpp.o: means (also the $< in it)?
I also found when I use something like:
SRC = $(wildcard $(SRC_DIR)*.c)
SRC_OBJS = $(patsubst %.c, %.o, $(SRC))
and use "$(SRC_OBJS)" as a target, it will compile all objects for each required object. This doesn't happen for the first one. What's the difference?
It's a suffix rule telling make how to turn file.cpp into file.o for an arbitrary file.
$< is an automatic variable referencing the source file, file.cpp in the case of the suffix rule.
$# is an automatic variable referencing the target file, file.o.

How can I put .o files to different folder and how should I improve this overall?

I've never really wrote any makefiles before and I have little knowledge of its syntax.
I'd like to put .o files into separate folder, obj/ for example. But I'm a bit lost how this should be done since there seem to be lot's of different ways to write makefile.
This is what I have currently and I would like to improve it.
PROGRAM=Project
CC=g++
CFLAGS=-c -g -std=c++0x -Wall -Wextra -pedantic -I $(SFML)/include -I src
LDFLAGS=-lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio -L $(SFML)/lib -Wl,-rpath=$(SFML)/lib -Wl,-rpath-link=$(SFML)/lib
SOURCES=$(wildcard src/*.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=bin/project
all: build $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS)
I've tried some different approaches but haven't yet figured out how to put .o files in their own folder.
Replace your OBJECTS line with something like:
OBJECTS=$(patsubst src/%.cpp,obj/%.o,$(SOURCES))
Remove the .ccp.o rule and replace it with something like:
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) $< -o $#
You can probably also remove $(SOURCES) from the prerequisite list of the all target unless you expect make to try to create those files somehow.

Resources