What is causing the error `make: Nothing to be done for 'x.o'.` for some x? - makefile

I added a new target (main.o) to an existing project:
DATS_FILES = main.dats
HFILES = config.h es.h gc.h input.h prim.h print.h sigmsgs.h \
stdenv.h syntax.h term.h var.h
CFILES = access.c closure.c conv.c dict.c eval.c except.c fd.c gc.c glob.c \
glom.c input.c heredoc.c list.c c_main.c match.c open.c opt.c \
prim-ctl.c prim-etc.c prim-io.c prim-sys.c prim.c print.c proc.c \
sigmsgs.c signal.c split.c status.c str.c syntax.c term.c token.c \
tree.c util.c var.c vec.c version.c y.tab.c dump.c
src :
#echo ${OTHER} ${CFILES} ${HFILES} ${DATS_FILES}
list.o : list.c es.h config.h stdenv.h gc.h
main.o : main.dats
match.o : match.c es.h config.h stdenv.h
As can be seen above, I have tried to give the new source .dats file the same status as the .c files in the project, which have no problems building.
If I try to build the target directly I get:
make main.o
make: Nothing to be done for 'main.o'.
This happens even if I run touch main.dats. If I compile main.dats manually after make fails, then run make again, the project finishes building and the output executable runs without issue. Here is the complete Makefile.in.

you need to add a rule to specify to make how to re-create main.o starting from main.dats. For C files make knows what to do, but for .dats files it doesn't. In particular, you have to change:
main.o : main.dats
with
main.o : main.dats
(your-compiler) (your-compiler-options) -o main.o main.dats
(assuming that is the syntax in your compiler for specifying input and output files)
IMPORTANT: indentation of the second (and the following) lines have to be done with tabs and not spaces, because that's how make works.
In your case (assuming .dats is the extension for dynamic ATS language) I think it should be
main.o : main.dats
patscc -c -o main.o main.dats
edit: if you have more than one .dats file to compile you can add a generic rule that teach make to invoke the right compiler for them (thanks to Toby for the syntax)
%.o : %.dats
patscc -c -o $# $<
I am not sure what is the priority for application when both a main.c and main.dats are present.

Related

'make: nothing to be done for p1 and' no rule to make target 'clean''

I'm trying to create a makefile titled 'p1' for a project.
When I try the command make p1 it returns with make: nothing to be done for p1
Also, when I try the command make p1 clean it returns no rule to make p1 'clean.' Stop
Here is my makefile:
a.out: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o const_iterator.o iterator.o Node.o
main.o:
g++ -std=c++11 -c main.cpp
P1LinkedList.o:
g++ -std=c++11 -c P1LinkedList.cpp
iterator.o:
g++ -std=c++11 -c iterator.cpp
const_iterator.o:
g++ -std=c++11 -c const_iterator.cpp
Node.o:
g++ -std=c++11 -c Node.cpp
depend:
g++ -MM main.cpp > p1.dep
clean:
rm -f a.out *.o
What do I need to fix to have the makefile compile .o files from my .cpp files and how do I fix the issue with the clean command?
Edit:
Here are the commands I've used to compile manually:
Helens-Air:p1a helenade$ g++ -std=c++11 *.cpp
Helens-Air:p1a helenade$ ./a.out
^^ and this just continues with the program execution from there
We may have to take this in stages.
First, you seem to misunderstand the difference between a makefile name and a target name. This appears to have been a miscommunication between you and your teacher, but it's easy to clear up.
Suppose you have a makefile named "Makefile", containing the following:
foo:
#echo running the foo rule
bar:
#echo running the bar rule
If you make foo, you will get:
running the foo rule
The argument (foo) tells Make which target to attempt to build. And how did Make know which makefile to use? (After all, you could have a dozen makefiles in the working directory.) You can specify which makefile to use, but if you don't then by default Make will look for a makefile named Makefile (or makefile or GNUmakefile, don't worry about this for now). To specify a makefile with another name, like "Buildfile", you can use the -f flag:
make -f Buildfile
So "p1" ought to have been the name of a target, not a makefile. Within the makefile, rename your a.out rule to p1. Then rename the whole makefile to Makefile. Then
make p1
should work (or at least run).
Edit:
I'll go out on a limb. In the a.out rule (which should now be called the p1 rule), I notice that you have left P1LinkedList.o out of the list of object files to be linked. So try changing it:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o P1LinkedList.o const_iterator.o iterator.o Node.o
If that works, you can simplify it with an automatic variable:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 $^
And there will be other small improvements you can make.
If it doesn't work, try ls *.cpp and see if you've overlooked some other source file.

Makefile compiles all the files everytime

My Makefile compiles all the files everytime I run it though the files have not been changed. I know that this question has been asked several times but none of the provided solutions seem to work for me. I am new to Makefile and most of the times I do not understand the jargon used in the solution. Also, I want to save all the generated .o files under the folder 'obj'
Here is my folder structure
project (-)
gen (-)
display (-)
.c and .h files
logic (-)
.c and .h files
lib (-)
include (-)
.h files
.lib files
man (-)
.c and .h files
obj (-)
want to save all the .o files here
I am running this on Windows OS using MinGW
Here is my Makefile:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.o logic.o man.o
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
logic.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
man.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
clean:
#echo "Cleaning up.."
-rm -rf *.o
-rm *.exe
NOTE: glut and oglx files are present in the lib folder. Display.o, lib.o and man.o do not have corresponding .c files. They are just folder names with many c files in them.
I understand this could be the problem. As there are no display.o, logic.o and man.o files created, MAKE complies the rule associated with it eveytime. SO how do I tell it to check for the actual .o filename1.o, filename2.o etc for the timestamp and recompile ONLY if they are older than the corresponding c files and h files maybe even the lib files they depend on.
I tried the following to create dependencies and avoid compiling of files everytime. But this did not help.
%.d: %.c
#set -e; rm -f $#; \
$(CC) -M $(CFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
At a basic level, make is looking for lines like:
target: dependency
command
If target does not exist, it calls the rule for dependency and then runs command. If target does exist, it tests if dependency is newer or does not exist. If so, it calls the rule for dependency and then runs command. Otherwise, it stops.
Significantly, the rule for dependency will only be called if (a) dependency doesn't exist, or (b) dependency is newer than target.
In the question, assume we run make demo. Then make looks for the line that begins demo: and notices it declares dependencies. So it looks at each dependency in turn to see if they require action. It first discovers display.o. It notices that display.o: does not exist, so it runs the associated rule. It does the same for the other *.o.
To avoid the *.o rules always being run because no associated file exists, you could rewrite like:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.ts logic.ts man.ts
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.ts: gen/display/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > display.ts
logic.ts: gen/logic/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > logic.ts
man.ts: man/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > man.ts
clean:
#echo "Cleaning up.."
-rm -rf *.o *.ts
-rm *.exe
Problem is that your binary object targets (like display.o) do not actually match files produced by their rules. If you tell make it needs to make target display.o, it (normally, except for phony targets, but those always rerun) expect the corresponding file to be produced by the rule's recipe and it can track if the target needs to be remade. If no such file is produces, this target always evaluates as outdated and needing remaking.
A bit of a silly example of this would be the following tree:
.
├── Makefile
├── main.c
└── test
└── file.c
and Makefile:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -c test/*.c
There is no test.o file and target needs to be remade... the rule runs, produces file.o (again). Since this target was remade and is prerequisite of main... everything always gets remade.
Now with this small modification:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -o $# -c test/*.c
test.o target indeed produces test.o file and the rule needs no remaking if test.c does not change... and with test.o unchanged and main.c perhaps as well, we get:
$ make
make: 'main' is up to date.
It still is not entirely correct as it really should read:
main: test.o main.o
$(CC) -o main $+
test.o: test/*.c
$(CC) $(CFLAGX) -o $# -c $^
Where I declare depend prerequisites of test.o and reference both them and the target by automatic variable in the rule's recipe. And Same goes for prerequisites for linking. Of course in this simple example I could just rely on implicit pattern rules and do this:
main: test/file.o main.c
test/file.o: test/*.c
What does this mean for your makefile? When you compile your object files, have a look what do they actually produce and match your target to that or (with -o $# for instance) tell them to produce exactly the file matching your target.
I've extended the silly example a bit and there are now two files in test/:
.
├── Makefile
├── main.c
└── test
├── file.c
└── other.c
And the Makefile can look something like this:
main: obj/file.o obj/other.o main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $# $^
It now stores object files in obj/ and make still understand what needs what and can track changes. Of course your setup is more complex and will require more rules, perhaps also divining actual sources or intermediate targets from the directory tree and define few variables to work with that information, e.g.:
OBJS := $(patsubst test/%.c,obj/%.o,$(wildcard test/*.c))
main: $(OBJS) main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $# $^
But the principles remain the same.

What does this code mean in the makefile of pmoncfg tool?

BISON?= bison -y
PROG= pmoncfg
SRCS= files.c gram.y hash.c main.c mkheaders.c mkioconf.c mkmakefile.c
OBJS= files.o hash.o main.o mkheaders.o mkioconf.o mkmakefile.o pack.o
CFLAGS+=-I${.CURDIR} -I. -DYY_SKIP_YYWRAP
LEX=flex
CLEANFILES=gram.c scan.c gram.h pmoncfg.cat8
MAN= pmoncfg.8
.y.c:
${BISON} -d -o $# $<
${PROG}: ${OBJS}
${CC} -o $# ${OBJS} ${LIBS}
install:
cp ${PROG} ${DESTDIR}/bin
clean:
${RM} -rf ${OBJS} ${CLEANFILES} ${PROG}
".y.c: ${BISON} -d -o $# $<" What does this line mean? There's no .y file in the current folder. And the MAN and LEX variable,the makefile doesnot use it,either.Why declare them?
According to the latest implicit rules, Can I just write "${PROG}: ${OBJS} ${CC} -o $# ${OBJS} ${LIBS}"?
The source of confusion here seems to be due to the reliance on implicit rules for some of the targets. Looking at https://github.com/kisom/pmon/tree/master/tools/pmoncfg, the file pmoncfg.8 is manual page source (so will generate pmoncfg.cat8 through implicit rules) and scan.l is a Lex file (so scan.c will be generated with flex, as the standard implicit rule parametrizes the program to use in the variable LEX). And contrary to what you write, there is a file gram.y which is used to generate gram.c using bison.
The job of make is to find files which can be generated from other files. A pattern rule like .y.c means that if a .c file is required but is missing, but there is a corresponding .y file, here's how to generate the required .c file. If the file already exists (and is newer than the file it depends on), nothing is done. If a file already exists and there is nothing to generate it from, obviously nothing needs to be done (and if it's missing and there is no rule for how to generate it, make signals an error).

Switching from g++ to clang++ in makefile

I 've got following makefile:
all: xmltest
xmltest: xmltest.cpp tinyxml2.cpp tinyxml2.h
This works fine - after executing make all executable 'xmltest' is produced.
However, I want to switch compiler to clang++. So I've added this line at the beginning of the file:
CXX=clang++
and now executing make all produces an error:
clang++ xmltest.cpp tinyxml2.cpp tinyxml2.h -o xmltest
clang++.exe: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated
clang++.exe: error: cannot specify -o when generating multiple output files
<builtin>: recipe for target 'xmltest' failed
make: *** [xmltest] Error 1
How to fix this with minimal modifications to original make file?
You might as well just write a shell script: there's no advantage to using the makefile in your solution. Any time you change any file, the entire thing will be rebuilt, so you might as well just run:
clang++ -g -o xmltest xmltest.cpp tinyxml2.cpp
whenever you change anything and skip the makefile.
If you wanted a makefile which took advantage of some of the capabilities of make, you would write it something like this:
CXX = clang++
all: xmltest
xmltest: xmltest.o tinyxml2.o
xmltest.o tinyxml2.o: tinyxml2.h
Now you have something useful, where only the files that need to be rebuilt based on what you've changed will be rebuilt. If your program gets more complex, you can use even more make facilities to keep it manageable.
You shouldn't list the header file as a translation unit (those are the cpps)
You should usually make the .h prerequisites:
xmltest.cpp: tinyxml2.h
tinyxml2.cpp: tinyxml2.h
And compile/link the translation units:
all: xmltest
xmltest: xmltest.cpp tinyxml2.cpp
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
IIRC you /might/ also put the 'dependency only' items on the same line using |
xmltest: xmltest.cpp tinyxml2.cpp | tinyxml2.h
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
But I'm unable to check that right now

The makefile creates the object files in the src directory rather than objects folder

Thanks!, I have updated my makefile now. And the .o are created in the src directory.
here is the makefile and output. The makefile throws the error because all the .o are created in the src folders. I don't know why? I am new to Makefile so kindly please bear with my silly questions.
# This is the Vpath; as my source directory is in the src folder - all the .c files
#folder structure
#Gif_Utility
#-->src/*.c
#-->include/*.h
VPATH = src:include:objects
CFLAGS = -I ./include -g -Wall -DDEBUG
OBJS =./objects
# Look at the CFLAGS here; it has -DDEBUG because in my code, I have #ifdef DEBUG
# Look at the CFLAGS here; -Wall : To generate all the compiler warnings.
# include is required as my compilation depends on the .h files.
# The LD flags to link the shared objects
#LDFLAGS=
#in my mini-project, I am using maths library, Thus, I have lm.
# lc to link my main function with crt1.o
#what is the compiler, am I using.
#This is a good practice since I can modify these flags when cross-compiling.
cc= gcc
#PATH for the LIBS
#This might be useful while cross-compiling.
LIBS= -lm -lc
target: $(patsubst %.c,%.o,$(wildcard ./src/*.c))
#echo "making target"
#mkdir -p ./objects
$(cc) $(patsubst ./src/%.c,./objects/%.o,$(wildcard ./src/*.c)) $(LIBS) -o gif
./objects/%.o: ./src/%.c
#echo "making objects now"
$(cc) $(CFLAGS) $(LDFLAGS) -c $< -o $#
#It is always better to write a PHONY rule for a rules like clean.
#It may happen that in source sandbox, you have a clean file. This may invoke the clean file.
#In order to prevent invoking a clean file during make clean; We give this general rule as PHONY
#PHONY tells the MAKEFILE that there is a rule clean, not a file called clean.
#Generally use PHONY for all, install, clean, distclean,
.PHONY: clean
clean:
#echo "cleaning everything"
#rm -f *.o
#rm -f gif
#echo "clearning .o from src"
#rm -f ./src/*.o
#rm -f ./objects/*.o
$make target
cc -I ./include -g -Wall -DDEBUG -c -o src/sysm.o src/sysm.c
cc -I ./include -g -Wall -DDEBUG -c -o src/x86_main.o src/x86_main.c
src/x86_main.c:11:9: warning: second argument of ‘main’ should be ‘char **’ [-Wmain]
src/x86_main.c: In function ‘main’:
src/x86_main.c:16:9: warning: implicit declaration of function ‘display_init’ [-Wimplicit-function-declaration]
src/x86_main.c:19:9: warning: implicit declaration of function ‘Gif_Read’ [-Wimplicit-function-declaration]
making target
gcc ./objects/gif_display.o ./objects/gif_lzw.o ./objects/gif_read.o ./objects/sysm.o ./objects/x86_main.o -lm -lc -o gif
gcc: error: ./objects/gif_display.o: No such file or directory
gcc: error: ./objects/gif_lzw.o: No such file or directory
gcc: error: ./objects/gif_read.o: No such file or directory
gcc: error: ./objects/sysm.o: No such file or directory
gcc: error: ./objects/x86_main.o: No such file or directory
make: *** [target] Error
You need to fix your patsubst to change the directory part of the filenames as well as the suffixes:
$(patsubst ./src/%.c,./objects/%.o,$(wildcard ./src/*.c))
You have other issues in your makefile too, e.g. this target has the wrong prerequisite:
./objects/%.o: %.c
The source file should be something like ./src/%.c
And the rule for that target is wrong, it outputs to ./objects/$# which would expand to something like ./objects/./objects/x86_main.o

Resources