I get error make: *** No rule to make target `puff'
My makefile code is
puff: puff.c puff.h
cc -DTEST -o puff puff.c
test: puff
puff zeros.raw
clean:
rm -f puff puff.o
And in my directory I have files puff.c, puff.h, zeros.raw, makefile.
Please help — I'm stuck on it.
you should write the command on the next line with a tab. The files on the same line as of target name are the dependencies. It should be like this
puff: puff.c puff.h
CC -DTEST -o puff puff.c
and similarly other rules. Don't forget to put a tab on the second line. These are not spaces but a tab. and also its CC I think, not cc.
Remove all characters after "puff:".
puff:
gcc -DTEST -o puff puff.c
test: puff
puff zeros.raw
clean:
rm -f puff puff.o
Related
I was given a makefile that looks like this, and told not to change it.
all: clean flex scanner.lex bison -d parser.ypp g++ -std=c++11 -o hw2 *.c *.cpp clean: rm -f lex.yy.c rm -f parser.tab.*pp rm -f hw2
I am trying to run this makefile in a folder with files named: scanner.lex, parser.ypp, output.hpp and output.cpp
I copied it to a file like this:
all:
clean flex scanner.lex bison -d parser.ypp g++ -std=c++11 -o hw2 *.c *.cpp
clean:
rm -f lex.yy.c rm -f parser.tab.*pp rm -f hw2
When I run the make command in my terminal I get an error:
clean flex scanner.lex bison -d parser.ypp g++ -std=c++11 -o hw2 *.c *.cpp
/bin/sh: clean: command not found
make: *** [all] Error 127
Am I doing something wrong? Again, I was given this line and told not to change it.
Thanks a lot.
Line breaks are essential in most computer environments. If you were given a Makefile without the line breaks and you try to cut it randomly you will have difficulties before if finally works. Try this, maybe:
all: clean
flex scanner.lex
bison -d parser.ypp
g++ -std=c++11 -o hw2 *.c *.cpp
clean:
rm -f lex.yy.c
rm -f parser.tab.*pp
rm -f hw2
And use tabs to indent the indented lines, not spaces.
Explanations: all and clean are what is called a target in make parlance. They are the names of the things you want make to do. clean to delete some files, all to do everything else. The
target: prerequisite1 prerequisite2...
recipe1
recipe2
...
template is the basic make template. It means that target depends on prerequisite1, prerequisite2 and that in order to build it make shall pass recipe1 to the shell for execution, then recipe2...
Note that this Makefile is poorly written. As all and clean are not real file names they should be declared as phony, such that, if a file with that name exists make does the job anyway. As is, it wouldn't. Give it a try:
$ make all
$ touch clean
$ make clean
make: 'clean' is up to date.
See? Because a file named clean exists you cannot make clean anymore, make considers that there is nothing to do for clean. Add this at the beginning of your Makefile:
.PHONY: all clean
A second issue is that make works by comparing last modification times of targets and prerequisites to decide if targets must be rebuilt or not. With your Makefile make will always recompile everything, even if the inputs did not change and the outputs are up-to-date. This is a waste. A better (but untested) Makefile would be something like:
.PHONY: all clean
CFILES := $(filter-out lex.yy.c,$(wildcard *.c))
CPPFILES := $(filter-out parser.tab.cpp,$(wildcard *.cpp))
all: hw2
hw2: lex.yy.c parser.tab.cpp $(CFILES) $(CPPFILES)
g++ -std=c++11 -o $# $^
lex.yy.c: scanner.lex
flex $<
parser.tab.cpp: parser.ypp
bison -d $<
clean:
rm -f lex.yy.c
rm -f parser.tab.*pp
rm -f hw2
Understanding it and why it is better is left as an exercise.
when I try to do make for the makefile it shows me (makefile error missing separator. stop)
my make file is
PROGS = $(patsubst %.c,%,$(SRCS))
all: $(PROGS)
%: %.c
arm-linux-gnueabihf-gcc --static $< -o $#
clean:
rm -f $(PROGS)
I try to use the following command but I could not solve my problem
cat -e -t -v Makefile
SRCS^I=^I$(wildcard^I*.c)^I$
PROGS^I=^I$(patsubst^I%.c,%,$(SRCS))$
all:^I$(PROGS)^I$
%:^I%.c^I$
arm-linux-gnueabihf-gcc^I--static^I$<^I-o^I$#^I$
clean:^I$
rm^I-f^I$(PROGS)^I$ ```
Crazy. You have TAB characters in all the places you don't need them, and you don't have TAB characters in any of the (two) places you must have them. I don't know how you managed that.
In your makefile above the places you MUST have TAB chars are the recipe lines. In other words, your makefile should look like this from cat -e -t -v Makefile:
SRCS = $(wildcard *.c)$
PROGS = $(patsubst %.c,%,$(SRCS))$
all: $(PROGS)$
%: %.c$
^Iarm-linux-gnueabihf-gcc --static $< -o $#$
clean:$
^Irm -f $(PROGS)$
As for configuring your text editor, there are a ton of text editors out there, even on Ubuntu, and we have no idea which one you are using.
I recommend you use a programmer's editor, which has a special mode that understands makefile syntax.
I have the following files in a directory:
FP01.c:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
long double ld = 0.1L; // long double constant (L or l suffix)
scanf("%Lf", &ld);
return 0;
}
makefile:
MAKEFLAGS += -rR
# the default target
.PHONY: all
all: FP01.elf
%.elf: %
cp $< $#
# prevents non-terminal match-anything rules from matching target '%.c'
# see section 10.5.5 of GNU make manual
%.c:
# a non-terminal match-anything rule
%: %.c
gcc -Wall -g $< -o $#
If FP01 does not exist, running make gives the following output:
make: *** No rule to make target 'FP01.elf', needed by 'all'. Stop.
However, if I run the following commands before make, then everything works as expected:
$ touch FP01
$ touch FP01.c
$ make
gcc -Wall -g FP01.c -o FP01
cp FP01 FP01.elf
Am I missing something or there is a bug in GNU make?
make --version gives the following output:
GNU make 4.1
Built for i686-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Fundation, Inc.
License GPLv3+: ...
...
EDIT:
It seems that making match-anything rule terminal somehow fixes the problem, but I want to use built-in rule to generate FP01 if possible and unfortunately it is non-terminal.
Another thing is that I believe that non-terminal rule should work so using terminal rule doesn't actually solve the problem as I still don't know whether the bug is in make or in my "mental makefile parser".
I'm not sure if this is a bug or not, I'd have to look more deeply into it. But the simple way to fix your problem is to set the match-anything pattern rule that compiles from the .c file as terminal, which is how it should be (unless you're generating the source files from somewhere else):
%:: %.c
cp $< $#
$ make
cp FP01.c FP01
cp FP01 FP01.elf
rm FP01
I think you should use :: on the % : %.c rule because you actually want that to be a terminal match-anything rule (since you don't need the .c file to be built):
MAKEFLAGS += -rR
.PHONY: all
all: FP01.elf
%.elf: % ; cp $< $#
% :: %.c ; gcc -Wall -g $< -o $#
Note that I used the ; form for the recipes here because it's easier to copy and paste because no need to worry about tabs.
Adding FP01 as a prerequisite of .INTERMEDIATE (special built-in target) seems to make it work (no need to modify the match-anything rule). Just another workaround.
MAKEFLAGS += -rR
# the default goal
.PHONY all
all: FP01.elf
%.elf: % ; cp $< $#
# prevents non-terminal match-anything rules from matching target '%.c'
# see section 10.5.5 of GNU make manual
%.c:
# a non-terminal match-anything rule
%: %.c ; gcc -Wall -g $< -o $#
.INTERMEDIATE: FP01
I have 2 makefiles that crash when I use the command make re if the program (or library) is not yet previously built, because make re calls fclean, which should remove the file and crashes if the file is not found. Here is one of the makefiles for a library
NAME = lib.a
CC = cc
CFLAGS = -Wall -Wextra -Werror
SRC = *.c
OBJ = $(SRC:.c=.o)
INC = Includes
all: $(NAME)
$(NAME):
#$(CC) -I $(INC) $(CFLAGS) -c $? $(SRC)
#ar rc $(NAME) $? $(OBJ)
#ranlib $(NAME)
clean:
#/bin/rm -f $(OBJ)
fclean: clean
#/bin/rm $(NAME)
re: fclean all
.PHONY: all clean fclean re
when I call make re and lib.a still doesnt exist I get
rm: lib.a: No such file or directory
make: *** [fclean] Error 1
Is there anyway to get it to just ignore the fclean command if lib.a is not found?
thanks
See the Errors in Recipes section of the GNU make manual for how to deal with this at the make level.
In this instance, however, you can also deal with this at the rm level. The -f flag to rm will cause it ignore non-existent files (as well as not prompting for deletion and in basically all other ways not stopping or returning a failure... ever).
That being said it shouldn't, in general, ever be necessary to clean before a new build. That generally seems necessary when a makefile is incorrectly written (as yours is) to not properly teach make what the dependencies between sources and targets are (and/or by not using targets essentially at all and always just building from scratch as you are).
I am still figuring out why in the below Makefile, when I execute it in the command like make clean all it runs twice the "clean all" target part?
FLAGS = -g -Wall -Wextra -Werror
a.out : check.cpp
$(CXX) $(CFLAGS) -o $# $<
clean all:
rm -rf *.o *.out *.txt
The target "clean all:" is equivalent to:
clean:
rm -rf *.o *.out *.txt
all:
rm -rf *.o *.out *.txt
You can't have spaces in target names, each word would be considered a target. So when you do make clean all, make thinks you want to build target "clean" and target "all" and so you have 2 targets being executed. It does look like a mistake in the makefile since having all doing the same as clean is weird.