Makefile compiling multiple times the same sources - makefile

** Question edited **
Here's a typical Makefile template :
TARGET = my_prog # project name
CC = gcc -o
CFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): $(OBJECTS)
#$(CC) $(TARGET) $(CFLAGS) $(SOURCES)
#echo "Compilation complete!"
clean:
#$(rm) $(TARGET) $(OBJECTS)
#echo "Cleanup complete!"
Question : why is the line 11 (#S(CC) $(TARGET) ...) still echoing when calling make ?
Answer : Because the problem is in the default rule and line 11 is fine.
** UPDATE **
I now have this Makefile
# project name
TARGET = my_prog
CC = gcc -c
CFLAGS = -Wall -I.
LINKER = gcc -o
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): $(OBJECTS)
$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
$(OBJECTS): $(SOURCES) $(INCLUDES)
$(CC) $(CFLAGS) $(SOURCES)
clean:
$(rm) $(TARGET) $(OBJECTS)
Question : Why is $(CC) $(CFLAGS) $(SOURCES) being executed n times, where n is the number of source files ?
** UPDATE 2 **
Would this be a good way to solve this (seems to work...) ?
$(TARGET): obj
$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
obj: $(SOURCES) $(INCLUDES)
$(CC) $(CFLAGS) $(SOURCES)

The command $(CC) $(CFLAGS) $(SOURCES) is executed n times, because the rule is executed n times, because there are n objects to be built, because the $(TARGET) rule has that many objects as prerequisites. If you want the command to be run only once, replace all those prerequisites with a single PHONY prerequisite, whose rule executes the command.
But there's no reason to do it that way. You can just make the command more selective, so that it builds only the one object that was the actual target. That way Make doesn't waste time rebuilding the same objects over and over, and if one or two source files have been changed, Make will rebuild only the relevant objects, not all of them:
$(OBJECTS): %.o : %.c $(INCLUDES)
$(CC) $(CFLAGS) $<
This rule is conservative-- it assumes that every object depends on every header, so it will sometimes rebuild things unnecessarily. You can make it better, either by hand if you know the real dependencies or automatically with a more advanced technique.
EDIT:
Your "update 2" is a decent solution, but I would suggest you add the line
.PHONY: obj
to tell Make that there will be no file called "obj". Otherwise Make will run the obj rule every time, trying to build that file.
This still has the problem that if you change one source file, e.g. foo.c, Make will rebuild all the objects.
The $< I used above is an automatic variable. It means "the first prerequisite". So when Make tries to build foo.o, it will evaluate to foo.c.
EDIT:
Jack Kelly (curse him!) has pointed out that I am wrong about how PHONY targets work: the obj rule will always run, and so will the TARGET rule, whether any source files have changed or not. So the "update 2" method is effective, but crude.

I think the output is coming from generating the .o files, not geverating my_prog
Looks like you don't have a rule for creating the .o files, so make is using the default one.
Try putting this:
#echo "starting compilation"
on the line before your line 11 build command
And you can see that "starting compilation" is output after the gcc line.
Perhaps line 10 should read:
$(TARGET): $(SOURCES)
?

Related

Makefile: no rule to make target '%.o', needed by '%'. Stop

I got the following error:
make: *** No rule to make target cardemo.o, needed by cardemo.exe. Stop
Trying to make this makefile
#Makefile for djgpp
#ALLEG =-lalleg
CC =gcc
OBJECTS = cardemo.o
all: cardemo.exe
#executables
cardemo.exe:$(OBJECTS)
$(CC) $(OBJECTS) $(ALLEG) -o $#
clean:
del *.o
del cardemo.exe
This is my first time creating a makefile with the help of Tutorials and Templates from Google just some days ago so excuse me if you find other mistakes thanks.
According to [GNU]: Catalogue of Built-In Rules:
Compiling C programs
n.o is made automatically from n.c with a recipe of the form $(CC) $(CPPFLAGS) $(CFLAGS) -c.
Example:
cardemo.c:
int main()
{
return 0;
}
Makefile:
#Makefile for djgpp
#ALLEG = -lalleg
#CC = gcc
OBJECTS = cardemo.o
all: cardemo.exe
#executables
cardemo.exe: $(OBJECTS)
$(CC) $(OBJECTS) $(ALLEG) -o $#
clean:
del *.o
del cardemo.exe
Output:
(qaic-env) [cfati#cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q075071635]> ~/sopr.sh
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
[064bit prompt]> ls
Makefile cardemo.c
[064bit prompt]> make
cc -c -o cardemo.o cardemo.c
cc cardemo.o -o cardemo.exe
[064bit prompt]> ls
Makefile cardemo.c cardemo.exe cardemo.o
Everything went fine, so the only logical conclusion one could draw is that you don't have a file called cardemo.c in the same directory.
If you modify OBJECTS related line (to OBJECTS = cardemo_notexist.o), you will get the same error.
To get past this, either:
Rename the source file from whatever name has now (could it be carddemo.c ?) to cardemo.c
Note: as #Mopower mentioned in a comment, original was Cardemo.c
Rename the object name so it has the source file stem name: OBJECTS = sourcefile_name.o
If renaming any of the 2 items above is not an option (or maybe cardemo.c is located in a different directory), add a compilation rule that will build cardemo.o from sourcefile_name.c:
cardemo.o: sourcefile_name.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
The problem is that you have putted $(OBJECTS) in the dependencies spot, which means makefile will need to make that file first (if it doesn't exist), so you should add a rule to make objs from c file like this:
%.o: %.c
$(CC) -o $# -c $<
$# means the target name, $< means the first dependency (You can also use $^ here, $^ means all the dependencied).

Makefile ignoring included rules

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!

Attempt to link objects makes them recompile even if up-to-date

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!

Makefile not executing to the end

I have the following makefile but it just executes the 1st command where it builds me the .o files and not the .so files. What am I doing wrong?
Thanks,
SHELL = /bin/sh
CC = gcc
CFLAGS = -g -Wall
LDFLAGS = -shared
TARGET = Stepper.so
SOURCES = $(shell echo ./*.c)
HEADERS = $(shell echo ./*.h)
OBJECTS = $(SOURCES:.c=.o)
LIBS = liblua523.a
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
clean:
rm $(OBJECTS)
Unless you specify a different target on the command line, make always builds the first real target found in the makefile. In this case, the first real target is the first object file, so that's all that's built.
This is why you typically see makefiles with a first target of all or similar, which just depends on the various other targets you want built during a standard invocation of "make" with no arguments.
However, your makefile is really not right, in a number of ways. The fact that it's running it all means you actually only have one source file. As soon as you have >1 it will fail.
This:
SOURCES = $(shell echo ./*.c)
is not very efficient; you should use wildcard here:
SOURCES = $(wildcard ./*.c)
This rule:
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
Tells make, "for every object file, if any source file or any header file has changed, recompile it". Basically, it means that if you change ANYTHING in the directory, EVERYTHING will rebuild. If you want that you might as well write a shell script and not bother with make at all.
Further, the compiler will fail when you have >1 source file, as it will try to run:
gcc -g -Wall -c foo.c bar.c -o foo.o bar.o
which is not right.
You don't need to define this rule at all; make has a built-in rule which knows how to build an object file from a source file. Just replace it with this:
$(OBJECTS): $(HEADERS)
(no recipe) so make knows that the objects depend on the headers as well as the source. Note this is not ideal since all objects rebuild if any header changes but it's fine for a simple program.

makefile linking issue

I have a trivial problem.. I am trying to modify a working Makefile to link a function I decided to add in my code simpletrial.cpp (The function is IniFile.cpp)
My old working Makefile is:
include Makefile.arch
TESTS := simpletrial.cpp
TESTO := $(TESTS:.C=.o)
TEST := simpletrial
OBJ = $(TESTO)
PROGRAMS = $(TEST)
CXXFLAGS +=
CXXFLAGS +=
GLIBS +=
.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)
all: $(PROGRAMS)
$(TEST): $(TESTO)
$(LD) $(LDFLAGS) $^ $(GLIBS) $(OutPutOpt)$#
#echo "$# done"
clean:
#rm -f $(OBJ) $(TESTO) core *~ src/*~ include/*~
.$(SrcSuf).$(ObjSuf):
$(CXX) $(CXXFLAGS) -c $< -o $#
I have tried without success to compile and link IniFile.cpp but I always receive the error "undefined reference to 'IniFile:: etc etc
thanks!
Your link line is the following:
$(LD) $(LDFLAGS) $^ $(GLIBS) $(OutPutOpt)$#
Here you link with $^ which is all of the pre-reqs for the rule, which in this case is $(TESTO) and that is simpletrial.o, you don't appear to have IniFile.cpp in there, so it won't link with it. To fix it just add IniFile.cpp to your TESTS as follows:
TESTS := simpletrial.cpp InFile.cpp
Then it should compile and link both files together and produce simpletrial as a result.
Additionally I think that your TESTO line might need to change as well:
TESTO := $(TESTS:.cpp=.o)
That should take the values in the $(TESTS) variable and change the suffix from .cpp to .o, the current definition will only change .C to .o...

Resources