Makefile: Explanation of circular dependencies on .o files - makefile

Consider the following makefile:
all : a.vo a.glob
a.gl%b a.v% : a.v
touch a.glob a.vo
When I run make -j2, I get:
$ rm -f a.vo a.glob; make -j2
make: Circular a.v.o <- a.v dependency dropped.
touch a.glob a.vo
I see why a.v.o depends on a.v, but I don't see how a.v depends on a.v.o. Where does this dependency come from (and is there a way to disable it)?

GNU make uses Implicit Rules when no rule is defined. In particular,
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
As you can see:
~ $ cat Makefile
all: a.v
echo "foo"
a.v.o:
echo "bar"
~ $ make
echo "bar"
bar
cc a.v.o -o a.v
gcc: error: a.v.o: No such file or directory
gcc: fatal error: no input files
compilation terminated.
<builtin>: recipe for target 'a.v' failed
make: *** [a.v] Error 1
cc is executed.

Related

Makefile 'missing separator' for ifneq

I know there are other issues with similar titles, but they don't seem to hold the solution.
Heres my makefile:
# Compiler Command
CC = mpiCC
CFLAGS = -c -I./header
# collecting object file names
src = $(wildcard source/*.cpp)
src1 = $(src:.cpp=.o)
objects := $(src1:source/%=bin/%)
# Compile object files into binary
all : $(objects)
$(CC) -o run $(objects)
ifneq($(n),) // <- error location , line 15
mpirun -np $(n) run
endif
# Generate object files by compiling .cpp and .h files
bin/%.o : source/%.cpp
$(CC) $(CFLAGS) $?
mv *.o bin
# Clean Recipe
.PHONY : clean
clean :
rm -rf all $(objects)
The goal of the ifneq is to have the binary run whenever it finishes compiling.
for example, a user runs the command:
make <- builds without running
make n=5 <- builds and runs on 5 processes
Whenever I use either of these, I get the error:
makefile:15: *** missing separator. Stop.
I've used cat -e -t -v to verify everything is tabbed instead of spaced. according to (https://www.gnu.org/software/make/manual/make.html#Conditional-Example) this conditional should function.
#MadScientist solved it. You need to put a space in between ifneq and its argument. For example:
ifneq($(n),0) is invalid.
ifneq ($(n),0) is valid.

Cross compiling hello world module

I am trying to cross compile a simple hello world program. The cross compiler I am using is for Buildroot Linux on a RPI4. I am trying to do the compilation on my Ubuntu machine.
I get this error:
make[2]: *** No rule to make target '/home/j_sizzle/Documents/Lab11-2/hello1.o', needed by '/home/j_sizzle/Documents/Lab11-2/hello1.mod'. Stop.
make[1]: *** [Makefile:1825: /home/j_sizzle/Documents/Lab11-2] Error 2
make[1]: Leaving directory '/home/j_sizzle/Documents/buildroot/buildroot-2021.11.1-rpi/output/build/linux-custom'
make: *** [Makefile:7: default] Error 2
My Makefile looks like this:
obj-m += hello1.o
KDIR := /home/j_sizzle/Documents/buildroot/buildroot-2021.11.1-rpi/output/build/linux-custom/
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) ARCH=arm CROSS_COMPILE=/home/j_sizzle/Documents/buildroot/buildroot-2021.11.1-rpi/output/host/bin/arm-buildroot-linux-uclibcgnueabihf- modules
clean:
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) clean
rm -f *~cd
I'm not really sure what I need to do here and I am somewhat new to makefiles so sorry if I am doing something dumb. I do know that this cross compiler works when just compiling a c program, but this is my first time trying to use it for modules.

make[1]: Command not found

I am getting below error while building some set of files. Would someone give some pointers on why do I get this error? Am I missing installation of some package?
Snippet of error log:
make[1]: MMD: Command not found
CC drivers/usb/usbhid.libc.o
make[1]: MMD: Command not found
CC drivers/usb/usbmsc.libc.o
make[1]: MMD: Command not found
CC drivers/hid.libc.o
make[1]: MMD: Command not found
AR build/libc.a
make[1]: invalidar: Command not found
Makefile.inc:89: recipe for target 'build/libc.a' failed
Snippet of my makefile:
# macro to define template macros that are used by use_template macro
define create_cc_template
# $1 obj class
# $2 source suffix (c, S)
# $3 additional compiler flags
# $4 additional dependencies
ifn$(EMPTY)def $(1)-objs_$(2)_template
de$(EMPTY)fine $(1)-objs_$(2)_template
$(obj)/$$(1).$(1).o: $$(1).$(2) $(obj)/libpayload-config.h $(4)
#printf " CC $$$$(subst $$$$(obj)/,,$$$$(#))\n"
$(CC) $(3) -MMD $$$$(CFLAGS) -c -o $$$$# $$$$<
en$(EMPTY)def
end$(EMPTY)if
endef
It looks to me as if the CC variable is not defined to anything when you invoke this macro, and the third argument is empty. This means that the recipe make internalizes after the eval is expanded is:
-MMD $$(CFLAGS)...
A quick fix is to escape the variable for CC:
$$(CC) $(3) -MMD ...
I think your expansion model for this is very odd, and probably incorrect in other ways. But, without seeing how this macro is used it's hard to say.
One easy way to debug eval issues is to duplicate the context where the eval appears and replace the eval with the info function. This will print exactly what make will parse, and it should be completely normal and understandable makefile syntax; e.g., change something like:
$(foreach X,$(STUFF),$(eval $(call FOO,$X)))
to:
$(foreach X,$(STUFF),$(info $(call FOO,$X)))
$(foreach X,$(STUFF),$(eval $(call FOO,$X)))

How to create a makefile that will place object code in different folder

I am very new to Makefile. I had build the following makefile(Which don't work).I wan't put genarated object codes in differnt folder(the folder is in current directory).
$ ls
main.cpp Makefile object_code Time.cpp Time_.h
how can I do this ??
VER = Debug
CC = g++
OBJECTFIELS = ./object_code/main.o ./object_code/Time.o
../$(VER)/main: $(OBJECTFIELS)
$(CC) $(OBJECTFIELS) -o $#
$(OBJECTFIELS): Time_.h
./object_code/main.o: main.cpp
./object_code/Time.o: Time.cpp
clean:
rm $(OBJECTFIELS) main
this is error.
$ make
g++ ./object_code/main.o ./object_code/Time.o -o ../Debug/main
g++: error: ./object_code/main.o: No such file or directory
g++: error: ./object_code/Time.o: No such file or directory
g++: fatal error: no input files
compilation terminated.
Makefile:8: recipe for target '../Debug/main' failed
make: *** [../Debug/main] Error 1
please this is last question.
I don't see how you can possibly get that output given the makefile you've posted here.
Either the object files already exist in which case the link will succeed rather than printing that error.
Or the object files don't exist in which case make will complain because it doesn't know how to make them. There must be some difference between the makefile you're using and the one you've posted here.
In any event, make knows how to build a file foo.o from a file foo.cpp for any string foo. There's a built-in rule that tells it how to do that.
But, make doesn't know how to build a file ./object_code/foo.o from a file foo.cpp, regardless of foo. There's no built-in rule that tells make how to build object files in some random other directory. If you want make to do that, you'll have to tell it how. You should remove the lines:
./object_code/main.o: main.cpp
./object_code/Time.o: Time.cpp
and replace them with a pattern rule describing how to build object files into the object_code directory (I'm using CXX as the compiler variable here: by convention CC is the C compiler and CXX is the C++ compiler, and you should always stick with convention unless there's a good reason not to):
VER = Debug
CXX = g++
OBJECTFIELS = ./object_code/main.o ./object_code/Time.o
../$(VER)/main: $(OBJECTFIELS)
$(CXX) $(OBJECTFIELS) -o $#
$(OBJECTFIELS): Time_.h
./object_code/%.o : %.cpp
$(CXX) -c -o $# $<
clean:
rm $(OBJECTFIELS) main

Makefile pattern rule either ignores phony rule or spontaneously deletes output file

I'm trying to write a makefile to produce several output files for each of several sources, using pattern rules.
I have the following Makefile (GNU Make 3.8.1):
all : foo.all bar.all
%.all : %.pdf %.svg
#echo Made $*
%.pdf :
touch $#
%.svg :
touch $#
.PHONY: foo.all bar.all
Since *.all do not represent real output files, I tried marking them as .PHONY. However, running make then doesn't work:
$ ls
Makefile
$ make
make: Nothing to be done for `all'.
According to make -d:
No implicit rule found for `all'.
Considering target file `foo.all'.
File `foo.all' does not exist.
Finished prerequisites of target file `foo.all'.
Must remake target `foo.all'.
Successfully remade target file `foo.all'.
Considering target file `bar.all'.
File `bar.all' does not exist.
Finished prerequisites of target file `bar.all'.
Must remake target `bar.all'.
Successfully remade target file `bar.all'.
Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
make: Nothing to be done for `all'.
which seems to be pretending to run the %.all rules, but skipping the bodies.
But with the .PHONY line commented out, Make runs the targets, but then spontaneously decides to delete the output files:
$ make
touch foo.pdf
touch foo.svg
Made foo
touch bar.pdf
touch bar.svg
Made bar
rm foo.pdf foo.svg bar.pdf bar.svg
According to make -d, it says:
Removing intermediate files...
Minimal example
A minimal example giving anomalous behavior:
%.all: %.out
#echo Made $*
%.out:
touch $#
I expect running make somefile.all to cause it to create the file somefile.out, but it gets deleted:
$ make somefile.all
touch somefile.out
Made somefile
rm somefile.out
Keeping make from deleting intermediary files
I recommend against using .PRECIOUS (see below as to why). Using .SECONDARY would preserve the .out files:
TARGETS=foo bar
all: $(TARGETS:=.all)
%.all: %.out
#echo Made $*
%.out:
touch $#
.SECONDARY: $(TARGETS:=.out)
$(TARGETS:=.all) just appends .all to all names in TARGETS. $(TARGETS:=.out) appends .out. We apparently cannot use %.out as a target of .SECONDARY. These just save having to relist all targets individually.
I prefer to not use .PRECIOUS for this because the documentation says
if make is killed or interrupted during the execution of their recipes, the target is not deleted.
This can leave corrupted files in the file system. Here's an example.
all: foo.all bar.all
%.all: %.out
#echo Made $*
%.out:
sh -e -c 'echo "{1, 2, 3" > $#; FAIL!; echo "}" >> $#'
.PRECIOUS: %.out
The FAIL! command simulates a tool that crashes in the middle of its work. Here's a shell session working with the Makefile above:
$ ls
Makefile
$ make
sh -e -c 'echo "{1, 2, 3" > foo.out; FAIL!; echo "}" >> foo.out'
sh: 1: FAIL!: not found
make: *** [foo.out] Error 127
$ cat foo.out
{1, 2, 3
Yikes... my foo.out file is incomplete. Let's try making again:
$ make
Made foo
sh -e -c 'echo "{1, 2, 3" > bar.out; FAIL!; echo "}" >> bar.out'
sh: 1: FAIL!: not found
make: *** [bar.out] Error 127
$ cat *.out
{1, 2, 3
{1, 2, 3
Make is none the wiser about files left around by earlier runs so when you run make again, it will take the corrupted files at face value. foo.out was not remade (despite the "Made foo" message) because it already exists and the Makefile went straight to trying to make bar.
.SECONDARY makes it so that:
The targets which .SECONDARY depends on are treated as intermediate files, except that they are never automatically deleted.
This means they are never automatically deleted just because they are intermediate files. The default make behavior of deleting targets that were being rebuilt if the tool rebuilding them crashed is not affected.
Using .PHONY with pattern rules
It seems though that .PHONY works only for targets that are explicit, not inferred. I've not found documentation confirming this. However, this works:
TARGETS:=foo bar
TARGETS_all:=$(TARGETS:=.all)
.PHONY: all
all: $(TARGETS_all)
.PHONY: $(TARGETS_all)
$(TARGETS_all): %.all: %.out
#echo Made $*
%.out:
touch $#
.SECONDARY: $(TARGETS:=.out)
In this rule $(TARGETS_all): %.all: %.out $(TARGETS_all): gives the list of targets to which the pattern can be applied. It makes foo.all and bar.all explicit targets. Without this, they would be inferred targets.
You can test that it works by creating file called foo.all in your directory and run make over and over. The foo.all file has no effect on make.
Your somefile.out files are considered intermediate by GNU make, which is why they are automatically deleted in your example. You can instruct GNU make to preserve these files by use the of .PRECIOUS special target, like this:
%.all: %.out
#echo Made $*
%.out:
touch $#
.PRECIOUS: %.out

Resources