This has been asked many times but from none of the answers can I figure out how to do it.
Simply put, I have directory structure: SRC/ for all *.for and *.f90 files, BLD/ for all files needed for building (that is *.o and *.mod) and lib/ for necessary libraries that need to be linked.
I want to build all source files in the SRC/ directory and put *.o and *.mod to the BLD/ directory while keeping the executable in the root where makefile is. I don't want to have multiple makefiles. The current makefile that does not work is below. I think that one issue there are lines that refere e.g. $(BLD)/$(objects) which probably expands to BLD/nrtype.o nrutil.o nr.o mtypes.o polint.o polyin2.o a.o but I am not really sure, and I am just trying and erroring since I do not have enough knowledge and the manuals are not clear for me to be able to figure it out. In one of the trials, *.mod some got to BLD/ some stayed in the root, it seems that the rules do not work I think they do.
# Compilation related variables
SRC = src
BLD = build
LIB = lib
FC = gfortran
LDFLAGS = $(LIB)/asm_functions.o
FFLAGS = -O0
# the name of the output executable
target = a
# all objects to generate
objects = nrtype.o nrutil.o nr.o mtypes.o polint.o polyin2.o a.o
#
modules = nrtype.mod nrutil.mod nr.mod mtypes.mod
# set module dependencies
nrtype_mod = polint.o polyin2.o
nrutil_mod = polint.o polyin2.o
nr_mod = polin2.o
mtypes_mod = a.o
# set default target
default: $(target)
# add dependencies to the targets
$(nrtype_mod): nrtype.mod
$(nrutil_mod): nrutil.mod
$(nr_mod): nr.mod
$(mtypes_mod): mtypes.mod
# compile modules
$(BLD)/%.mod: $(SRC)/%.f90 $(BLD)/%.o
$(FC) -c $(FFLAGS) -o $# $<
# compile old fortran files
$(BLD)/%.o: $(SRC)/%.for
$(FC) -c $(FFLAGS) -o $# $<
# compile new fortran files
$(BLD)/%.o: $(SRC)/%.f90
$(FC) -c $(FFLAGS) -o $(BLD)$# $<
# link everything
$(target): $BLD/$(objects)
$(FC) -o $# $(FFLAGS) $^ $(LDFLAGS)
# cleaning up
clean:
rm -f $(BLD)/$(objects) $(BLD)/$(modules)
clobber: clean
rm -f $(BLD)/$(target)
.PHONY: default clean clobber
Update
I edited the makefile to the form:
# Compilation related variables
SRC = src
BLD = build
LIB = lib
FC = gfortran
LDFLAGS = $(LIB)/asm_functions.o
FFLAGS = -O0
# the name of the output executable
target = a
# all objects to generate
objects = $(BLD)/nrtype.o $(BLD)/nrutil.o $(BLD)/nr.o $(BLD)/mtypes.o $(BLD)/polint.o $(BLD)/polyin2.o $(BLD)/a.o
#
modules = $(BLD)/nrtype.mod $(BLD)/nrutil.mod $(BLD)/nr.mod $(BLD)/mtypes.mod
# set module dependencies
nrtype_mod = polint.o polyin2.o
nrutil_mod = polint.o polyin2.o
nr_mod = polin2.o
mtypes_mod = a.o
# set default target
default: $(target)
# add dependencies to the targets
$(nrtype_mod): nrtype.mod
$(nrutil_mod): nrutil.mod
$(nr_mod): nr.mod
$(mtypes_mod): mtypes.mod
# compile modules
$(BLD)/%.mod: $(SRC)/%.f90 $(BLD)/%.o
$(FC) -c $(FFLAGS) -o $# $<
# compile old fortran files
$(BLD)/%.o: $(SRC)/%.for
$(FC) -c $(FFLAGS) -o $# $<
# compile new fortran files
$(BLD)/%.o: $(SRC)/%.f90
$(FC) -c $(FFLAGS) -o $# $<
# link everything
$(target): $(objects)
$(FC) -o $# $(FFLAGS) $^ $(LDFLAGS)
# cleaning up
clean:
rm -f $(BLD)/$(objects) $(BLD)/$(modules)
clobber: clean
rm -f $(BLD)/$(target)
.PHONY: default clean clobber
While with this modification the build is successful, it is still not obeying orders. Specifically, *.mod files are being generated where the makefile is but I found in the meantime that it is gfortran who is disobedient and for mod files the output directory is controlled by some other switch. Nevertheless:
Other things that are not clear:
Should the lines look like:
$(BLD)/%.o: $(SRC)/%.for
$(FC) -c $(FFLAGS) -o $# $<
Or
%.o: %.f90
$(FC) -c $(FFLAGS) -o $(BLD)/$# $(SRC)/$<
or is it the same (i prefer the second one for readability).
Why the line such as
nrtype_mod = polint.o polyin2.o
do not need to be prepended by the paths? Or do they have to be (but it built correctly). This is where it is very confusing.
The maual would really benefit from some basic examples of a full makefile.
I think that one issue there are lines that refere e.g. $(BLD)/$(objects) which probably expands to BLD/nrtype.o nrutil.o nr.o mtypes.o polint.o polyin2.o a.o
You are exactly correct in your assessment here.
You can use a GNU make function like addprefix to fix this.
It would be useful to understand what part of the manual you had trouble understanding, so it can be improved.
Related
I'm trying to create a makefile for a very basic c++ program. I'm trying to implement the automatic generation of dependencies by running g++ with the -M flag, storing this output in a .d file, and then including those .d files in my main makefile. The makefile content is below
CC=g++
CPPFLAGS=-Wall -Wextra -g -std=c++11
SOURCEDIR=src
SOURCES = $(wildcard $(SOURCEDIR)/*.cpp)
BUILDDIR=build
OBJDIR=$(BUILDDIR)/objs
OBJS=$(SOURCES:$(SOURCEDIR)/%.cpp=$(OBJDIR)/%.o)
DEP_FILES = $(OBJS:.o=.d)
OUTFILE=hello.out
$(OUTFILE) : $(OBJS)
$(CC) -o $# $^ $(CPPFLAGS)
include $(DEP_FILES)
$(OBJDIR)/%.d : $(SOURCEDIR)/%.cpp
$(CC) $(CPPFLAGS) $< -MM -MT $(#:.d=.o) > $#
$(DEP_FILES) : | $(OBJDIR)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
.PHONY: clean
clean:
rm -f $(BUILDDIR) -r
rm -f *~
rm -f $(OUTFILE)
When I run make, the directory build/objs/ is generated and a .d file is generated with rules in it. Here's main.d file:
build/objs/main.o: src/main.cpp src/main.h
And here's the myfunc.d file:
build/objs/myfunc.o: src/myfunc.cpp src/main.h
Here's the issue
Since I'm calling include on these .d files, I'd expect the .o files which they specify to then be created, and then the main outfile to be created as the main rule. However, make creates the .d files, and then skips directly to the main compilation step without creating any .o files:
g++ -o hello.out build/objs/myfunc.o build/objs/main.o -Wall -Wextra -g -std=c++11
This fails with the following error, since the .o files are never created:
g++: error: build/objs/myfunc.o: No such file or directory
g++: error: build/objs/main.o: No such file or directory
g++: fatal error: no input files
How can I use this makefile to generate the .o files necessary for g++? Thank you for any help in advance!
I saw you got your makefile working but I just wanted to add a few things you might want to consider for future projects. I recommend using the vpath variable rather than specifying $(OBJDIR)/%.o in your makefile recipes. I actually read somewhere that it's not "cannon" to build object files in a separate directory, but in the cursory search I conducted before posting, I couldn't find the document.
That being said, I wrote a makefile that does what you wanted; it builds the output folder, generates the dependencies, and compiles the program. I specifically included the $(COMPILE.cpp) definition so you could see what it's composed of. $(CC) is specifically the C compiler, and $(CFLAGS) is specifically flags for the C compiler. They're just variables, obviously, so you can change them like you did and it will work fine, but the main think to keep in mind is that whoever uses your programs will expect to be able to configure the compilation as they see fit. This means they will set the $(CXX) and $(CXXFLAGS) expecting to set the C++ compiler and flags. $(CPPFLAGS) stands for C/C++ Preprocessor flags.
It's not the cleanest makefile, and if I was to change something, I would just compile the object files in place and save myself that headache. That cuts down on unnecessary make hacking, but for the purposes of answering your question, here it is. Anyways I hope this helps you somewhat, let me know if you have any questions.
Oh yea, I almost forgot; notice I changed your make clean script. I used $(RM) instead of simply rm -f. When you use utilities in your makefiles, you want to use them as variables. Again, this is to allow your users as much freedom and flexibility as possible when they're compiling your program.
vpath %.cpp src
vpath %.hpp include
vpath %.o build/objs
vpath %.d build/objs
.SUFFIXES:
.SUFFIXES: .cpp .hpp .o .d
SRCDIR = src
INCLUDESDIR = include
BUILDDIR = build
OBJDIR = $(BUILDDIR)/objs
SRCS = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
DEP_FILES = $(patsubst %.o, %.d, $(OBJS))
INCLUDE_DIRS = -I $(INCLUDESDIR)
CXX = g++
CPPFLAGS =
CXXFLAGS = -Wall -Wextra -g -std=c++11
PROGRAM = hello.out
COMPILE.cpp = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) $(TARGET_ARCH)
all: $(PROGRAM)
$(PROGRAM): %: $(OBJS)
$(LINK.cpp) $(INCLUDE_DIRS) $(addprefix $(OBJDIR)/, $^) $(LOADLIBES) $(LDLIBS) -o $#
%.o: %.cpp
$(COMPILE.cpp) -c -o $(OBJDIR)/$# $<
%.d: %.cpp
mkdir -p $(OBJDIR)
$(COMPILE.cpp) $^ -MM -MT $(addprefix $(OBJDIR)/, $(#:.d=.o)) > $(OBJDIR)/$#
include $(DEP_FILES)
.PHONY: clean
clean:
#echo $(RM)
$(RM) $(BUILDDIR) -r
$(RM) *~
$(RM) $(PROGRAM)
For anyone having a similar issue, here's the correct solution is in the comments. Here for convenience: The included .d files generate dependencies but not a recipe for making the .o files, and since I'm putting things in various directories the default rule doesn't work here, so the .o files aren't created. The solution was to add in the following rule to my main makefile.
$(OBJDIR)/%.o :
$(CC) -c -o $# $< $(CPPFLAGS)
Thanks Matt and Renaud for your answers!
I have a recipe in my makefile that relies on several object files. I would like it to simply link the them, but they are always recompiling.
I've googled around and found information I did not know(marked with #) and changed it a bit, but the problem persisted.
I am led to believe make expects the name of the recipe be the name of the file, and I am failing to accomplish that. The problem is I do not what else to try and fix this. I would appreciate any help
CC = g++
#.PHONY: sfml-app
LIBS = -lsfml-graphics -lsfml-window -lsfml-system
APPLICATION = sfml-app
INCLUDE_DIR = -I include/
SOURCE_DIR = source
OUTPUT_DIR = bin
SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
OBJECTS = $(notdir $(patsubst %.cpp, %.o, $(SOURCES)))
#$(OUTPUT_DIR)/$(APPLICATION): $(OBJECTS)
#bin/sfml-app: $(OBJECTS)
#sfml-app: $(OBJECTS)
#$(APPLICATION): $(OBJECTS)
$(CC) $(OUTPUT_DIR)/*.o $(LIBS) -o $(OUTPUT_DIR)/$(APPLICATION)
%.o: $(SOURCE_DIR)/%.cpp
$(CC) -c $< $(INCLUDE_DIR) -o $(OUTPUT_DIR)/$#
clean:
rm $(OUTPUT_DIR)/*
print-% : ; #echo $* = $($*)
This rule doesn't create the file it promises to:
%.o: $(SOURCE_DIR)/%.cpp
$(CC) -c $< $(INCLUDE_DIR) -o $(OUTPUT_DIR)/$#
See that -o $(OUTPUT_DIR)/$#? That's instructing the compiler to create a file in $(OUTPUT_DIR) instead of in the working directory.
If you really want your object files to go in $(OUTPUT_DIR), you need to make sure that your rule indicates that:
$(OUTPUT_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(CC) -c $< $(INCLUDE_DIR) -o $#
Or better, to act like the standard %.o: %.c rule (which will include CFLAGS etc):
$(OUTPUT_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(COMPILE.c) $(OUTPUT_OPTION) $<
I note your input files are named *.cpp - usually, that convention is for C++ files (i.e. to be compiled with $(COMPILE.cc), which will invoke $(CXX) rather than $(CC)). Check that you've not mixed up your C and C++ sources!
I don't understand the dependencies very well
TARGET = prog1.exe
SRC = src
# dir. with *.cpp
INC = inc
# dir. with *.hpp
BIN = bin
# dir. with *.o, *.out,*.exe
SOURCE = $(wildcard $(SRC)/*.cpp)
OBJECT = $(patsubst %, $(BIN)/%, $(notdir $(SOURCE:.cpp=.o)))
CXX = g++
CXXFLAGS = -g -I$(INC)
ifneq ($(ARGS),'')
GDBI := --args $(BIN)/$(TARGET) $(ARGS)
else
GDBI := $(BIN)/$(TARGET)
endif
$(BIN)/$(TARGET): $(OBJECT)
$(CXX) -o $# $^
$(BIN)/%.o: $(SRC)/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
.PHONY: help run clean depurate
run: $(BIN)/
$(BIN)/$(TARGET) ${ARGS}
clean:
rm -f $(OBJECT) $(BIN)/$(TARGET)
depurate:
gdb $(GDBI)
help:
#echo "Para ejecutar: \`make run' o \`make ARGS=\"<argumentos>\" run'."
Why is Make not checking changes with the headers files .hpp in the directory inc/?
Is right this solution for headers without source files?
I mean: x.cpp includes x.hpp, and x.hpp includes a.hpp and b.hpp.
$(BIN)/%.o: $(SRC)/%.cpp $(INC)/%.hpp
$(CXX) $(CXXFLAGS) -c $< -o $#
Make isn't doing dependency checking on your header files because they're not explicitly listed as a dependency anywhere.
If you want to make your source files depend on all of the header files, you can do something like this:
HEADERS:=$(wildcard $(INC)/*.hpp)
$(BIN)/%.o: $(SRC)/%.cpp $(HEADERS)
That will rebuild all of your source files whenever any header changes, which works but is probably overkill. If you only want a source file to depend on those header files it actually uses, you'll want to use the compiler's automatic dependency generation capabilities:
CXXFLAGS = -g -I$(INC) -MMD -MF $(<:.cpp=.d)
include $(wildcard $(SRC)/*.d)
$(BIN)/%.o: $(SRC)/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -f $(OBJECT) $(BIN)/$(TARGET) $(SRC)/*.d
Now, when the compiler compiles a .cpp file, it will create a matching .d file alongside it. This file is a tiny fragment of a makefile that lists the headers that .cpp file uses. The next time you build, the include line pulls in all of those .d files and uses that information to help calculate dependencies. The blog post mentioned by Tim in the comments has a great detailed explanation of how this works.
I have a FORTRAN source code consisting of many different .F and .h files. I need to build an executable from it, but I'm having some problems. The makefile that I produced so far (which may have errors as I'm new to this) is:
# compiler
FC = /usr/bin/gfortran-4.5
# compile flags
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons
# link flags
FLFLAGS = -g -fbacktrace
# source files and objects
SRCS = $(patsubst %.F, %.o, $(wildcard *.F)) \
$(patsubst %.h, %.mod, $(wildcard *.h))
# program name
PROGRAM = blah
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FCFLAGS) $# $<
%.o: %.F
$(FC) $(FLFLAGS) -o $# $<
%.mod: %.h
$(FC) $(FLFLAGS) -o $# $<
clean:
rm -f *.o *.mod
When I try to make the program, however, I'm getting a slew of undefined reference errors. I mean, every function and subroutine call in the very first compiled .F file gives back an undefined reference error. I thought this was because gfortran was trying to link the files instead of just compiling them and then linking at the end, but I thought the '-c' option was supposed to prevent that.
UPDATE:
As commenters have pointed out, I mixed up the compile and link flags. Furthermore, you shouldn't compile *.h files. Here is the latest, corrected makefile:
# compiler
FC = /usr/bin/gfortran-4.4
# compile flags
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons -fbounds-check -std=legacy
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.F, %.o, $(wildcard *.F))
# program name
PROGRAM = blah
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $# $<
%.o: %.F
$(FC) $(FCFLAGS) -o $# $<
clean:
rm -f *.o *.mod
Now when I run make, it will compile each *.F file in the code, but it fails at the linking stage. I get a bunch of undefined reference errors in the very first *.F file. The compiler seems to be going over each *.F file individually in the linking stage, which I'm not sure is correct. Then I get an error:
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/libgfortranbegin.a(fmain.o): In function `main':
(.text+0x26): undefined reference to `MAIN__'
collect2: ld returned 1 exit status
However, if I type the command:
gfortran -o blah *.o
The executable will be built, so it seems like I did something wrong in the makefile for the linking stage.
UPDATE: 5/9/2011
Sverre pointed out the final problem with my makefile. In my first target that builds the program, I use the shortcut command for only the first dependency ($<), but I need to include all dependencies (i.e. all *.o files) using the ($^) shortcut. The final, working makefile is as follows:
# compiler
FC := /usr/bin/gfortran-4.5
# compile flags
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons -fbounds-check
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.F, %.o, $(wildcard *.F))
# $(patsubst %.h, %.mod, $(wildcard *.h))
# program name
PROGRAM = vipre
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $# $^
%.o: %.F
$(FC) $(FCFLAGS) -o $# $<
# %.mod: %.h
# $(FC) $(FCFLAGS) -o $# $<
clean:
rm -f *.o *.mod
Are you using GNU make? If so,
$(FC) $(FLFLAGS) -o $# $<
may be the culprit. $< is the name of the first prerequisite, but you want all the *.o files. Try using $^ instead.
I'm working on a cross-platform 2D engine for mobile devices (Windows Mobile 6 and Android). My Windows version is pretty much ready, but I still need to make sure the same functionality is available on Android.
What I want is one Makefile in the root of the project and several Makefile's for the project itself and the test applications.
Makefile
---Engine
------Makefile
------src
------bin
------intermediate
---Tests
------TestOne
---------Makefile
---------src
---------bin
---------intermediate
------TestTwo
---------Makefile
---------src
---------bin
---------intermediate
I'm basing my attempts on the following Makefile:
include ../makeinclude
PROGS = test1
SOURCES = $(wildcard *.cpp)
# first compile main.o and start.o, then compile the rest
OBJECTS = main.o start.o $(SOURCES:.cpp=.o)
all: $(PROGS)
clean:
rm -f *.o src
test1: $(OBJECTS)
$(LD) --entry=_start --dynamic-linker system/bin/linker -nostdlib -rpath system/lib -rpath $(LIBS) -L $(LIBS) -lm -lc -lui -lGLESv1_CM $^ -o ../$#
acpy ../$(PROGS)
.cpp.o:
$(CC) $(CFLAGS) -I $(GLES_INCLUDES) -c $*.cpp $(CLIBS)
However, I'm not very good with these things. What I want is for it to take the .cpp's that are in the src folder, compile them to .o and put them in the intermediate folder and, finally, compile the .o's to the compiled exe and put it in the bin folder.
I've managed to get clean to work like this:
cd intermediate && rm -f *.o
However, I can't get it to retrieve the .cpp's, compile them and put them in the intermediate folder.
I've looked at several other Makefiles, but none do the things I want to do.
Any help is appreciated.
There's more than one way to do this, but the simplest is to run in TestOne, making Intermediate/foo.o out of Src/foo.cpp and test1 out of Intermediate/foo.o, like this:
# This makefile resides in TestOne, and should be run from there.
include makeinclude # Adjust the path to makeinclude, if need be.
PROG = bin/test1
SOURCES = $(wildcard Src/*.cpp)
# Since main.cpp and start.cpp should be in Src/ with the rest of
# the source code, there's no need to single them out
OBJECTS = $(patsubst Src/%.cpp,Intermediate/%.o,$(SOURCES))
all: $(PROG)
clean:
rm -f Intermediate/*.o bin/*
$(PROG): $(OBJECTS)
$(LD) $(BLAH_BLAH_BLAH) $^ -o ../$#
$(OBJECTS): Intermediate/%.o : Src/%.cpp
$(CC) $(CFLAGS) -I $(GLES_INCLUDES) -c $< $(CLIBS) -o $#