SOURCES = server.c
TARGET = Server
CC = gcc
all: $(SOURCES) $(TARGET)
$(CC) $(SOURCES) -o $(TARGET)
clean:
rm -rf $(TARGET)
Above is the Makefile of my web server. Though server.c file is in the directory this gives the fallowing error
make: *** No rule to make target `Server', needed by `all'. Stop.
What is the mistake I've made and how to solve it.
I think your makefile got garbled somewhere between your machine and the post, but there is a simple fix that I think will work:
all: $(SOURCES)
That will (probably) solve the problem and make the error go away-- if that's all you want then you can stop reading. But there are still things wrong with this makefile, so we can make some more improvements.
First, a little adjustment to make it match what I think your makefile really says:
SOURCES = server.c
TARGET = Server
CC = gcc
all: $(SOURCES) $(TARGET)
$(CC) $(SOURCES) -o $(TARGET)
clean:
rm -rf $(TARGET)
The first three lines and the clean rule are all right, we'll ignore those. Now we give TARGET its own rule and straighten out the prerequisites:
all: $(TARGET)
$(TARGET): $(SOURCES)
$(CC) $(SOURCES) -o $(TARGET)
Now we make all PHONY (since it doesn't really make a file called "all"), and introduce automatic variables to make the TARGET rule more robust and less redundant:
.PHONY: all
all: $(TARGET)
$(TARGET): $(SOURCES)
$(CC) $< -o $#
There's more to learn if your codebase gets more complicated, but that'll do for now.
just do "make clean" to clean all links, then run make again. Everything should be good.
My issues was I had the name and the command on the same line. Make: sure you are using tabs and not spaces. (no pun intended)
BEFORE (Broken)
build: docker build...
AFTER
build:
docker build...
Related
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).
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 :|
I have no idea how to express this little problem other than by "VPATH Failure", and searching for that brought me nowhere, so now I'm giving it a go, throwing my issue into the pool.
I'm working on a simple makefile here and I ran into a problem, that I am completely stumped by.
I made a first original version, that I got working all fine and dandy:
// Variable pre-processing stuff up here
VPATH = ./src/ ./include/
// Usual phony targets in here
$(OBJF)Utilities$(R).o: Utilities.cpp Utilities.hpp
#echo Building $#
#echo $<
#$(CXX) $(FLAGS) -Iinclude -c $< -o $#
$(OBJF)Settings$(R).o: Settings.cpp Settings.hpp
#echo Building $#
#echo $<
#$(CXX) $(FLAGS) -Iinclude -c $< -o $#
// More file targets down here
As proven by the make output
lex#Lex-Laptop:~/Dev/LHArch$ make RELEASE=STATIC rebuild
Removing object files and outputs...
Cleaning done.
Building objs/Release/Static/Utilities.o
./src/Utilities.cpp
Building objs/Release/Static/Settings.o
./src/Settings.cpp
That's nice.
For the sake of removing some redundancy with the dependencies, I thought it to be a good idea to put the code into their own targets, in this manner:
$(OBJF)Utilities$(R).o: Utilities.cpp
#echo Building $#
#echo $<
#$(CXX) $(FLAGS) -Iinclude -c $< -o $#
Utilities.cpp: Utilities.hpp
$(OBJF)Settings$(R).o: Settings.cpp
#echo Building $#
#echo $<
#$(CXX) $(FLAGS) -Iinclude -c $< -o $#
Settings.cpp: Settings.hpp
That is all I changed. I expected it to work as perfectly as it did before, but it only partially did:
lex#Lex-Laptop:~/Dev/LHArch$ make RELEASE=STATIC rebuild
Removing object files and outputs...
Cleaning done.
Building objs/Release/Static/Utilities.o
./src/Utilities.cpp
Building objs/Release/Static/Settings.o
Settings.cpp
g++: error: Settings.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
Makefile:101: recipe for target 'objs/Release/Static/Settings.o' failed
make: *** [objs/Release/Static/Settings.o] Error 1
It found and replaced the path of Utilities, but not for Settings apparently. They are in the same folder, the commands are the same for the both of them. I honestly have no clue what is wrong and it sort of ruins my plan.
Have you guys for any wise words on this?
Did I stumble upon something genuine here, or am I just a dumbbutt who hasn't read up on his homework?
There's this rule (link provided by Etan Reisner) that VPATH and vpath should only be used for prerequisites, not for targets.
In your case, VPATH behaves "unpredictably" as soon as you put your .cpp files both as targets and prerequisites. The good news is that there's no redundancy in your first version. You do want the .o to be rebuilt if either of the .cpp and .hpp is updated. In fact, you don't want
Utilities.cpp: Utilities.hpp
since this will try to rebuild the .cpp if you update the .hpp, for which there's no recipe.
I would therefore stick with your first version and, instead, consider using vpath for ease of maintenance
vpath %.cpp ./src/
vpath %.hpp ./include/
I have this Makefile which seems to be working, but I'm not sure how:
EXECUTABLE=hello
CC=gcc
OBJS = a.o
all: $(EXECUTABLE)
%.o : %.c
$(CC) -o $# -c $<
$(EXECUTABLE): $(OBJS)
$(CC) -o $# $<
I know the top 3 lines are local defines, and when I type "Make" it will build the all target. Now from here I'm a little lost... I'm guessing:
Make sees the $(EXECUTABLE) label and jumps the that build command
it sees the $(OBJS) label and since a.o doesn't exist in the local directory it jumps to the pattern matching rule
Make finds a.c and runs the rule to generate a.o
Now Make returns to the $(EXECUTABLE) command and runs the combination of .o files to make the "hello" program
Questions:
Is my understanding of that flow correct?
Is the placement of the "label"s in this file relevant?
Is there some GNU documentation that I'm missing which confirms my suspicions of how this is working?
Your flow is basically correct. Make will build the first target listed in the file if you do not explicitly pass one on the command line. In most makefiles people will have all as the first target so like in your example you can just type make and it will automatically build the all target. What make does internally is build a list of dependencies that you are defining in your Makefile. all is dependent on $(EXECUTABLE) which is dependent on $(OBJS). In order to satisfy the the creation of the all target it has to start at the bottom of that dependency list and work its way up. The make manual is actually very good if you want to take a look here: http://www.gnu.org/software/make/manual/ and notably to your specific question here: http://www.gnu.org/software/make/manual/make.html#How-Make-Works
I found a tool to help answer to one part of my question at least, so I'll post it for the reference of myself and others:
It is possible to "debug" a Makefile via $(warning <some string>) calls.
So in my example I used it as such:
all: $(warning All before exe call) $(EXECUTABLE)
$(warning All warning after call)
%.o : %.c
$(warning before pattern)
$(CC) -o $# -c $<
$(warning after pattern)
$(EXECUTABLE): $(warning before obj) $(OBJS)
$(warning after obj)
$(CC) -o $# $<
And got the output showing me the flow:
mike#mike-VirtualBox:~/C$ make
Makefile:6: All before exe call // started at all
Makefile:14: before obj // Jumped to EXECUTABLE label
Makefile:10: before pattern // Jumped to pattern matching
Makefile:10: after pattern
gcc -o a.o -c a.c
Makefile:15: after obj // back to EXECUTABLE label
Makefile:15: after build // back to build command
gcc -o hello a.o
Makefile:7: All warning after call
Using this I discovered that I could do this:
$(EXECUTABLE): $(warning before obj) $(OBJS)
but not:
$(EXECUTABLE):
$(warning before obj)
$(OBJS)
Which makes sense since white space is important in Makefiles
** 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)
?