Make target variable causes not input files - makefile

I am trying to use the following in a makefile, but when I type make filter_test it gives me the error below, and I can not figure out why. Note the spaces where the input files should be.
CXX=g++
CXXFLAGS=-O1 -pedantic -Wall -Werror -g
DEPS=p2.o recursive.o $#.cpp
p2.o: p2.cpp ; $(CXXFLAGS) -c p2.cpp
recursive.o: recursive.cpp ; $(CXXFLAGS) -c recursive.cpp
filter_test: p2.o $#.cpp recursive.o ; $(CXX) $(CXXFLAGS) recursive.o p2.o $#.cpp -o aaa
Output:
g++ -O1 -pedantic -Wall -Werror -g -o .cpp
g++: fatal error: no input files
compilation terminated.
make: *** [.cpp] Error 4

$# only has a value inside the recipe, so when make sees $# in the prerequisite list, it treats it as an empty string. So make is trying to build the pre-requisite .cpp and using the default rule to build it. To fix this just write:
filter_test: p2.o filter_test.cpp recursive.o
Leave the recipe blank and let make use default rules.

Related

Why recipe for target 'mykernel.bin' failed?

I'm trying to create a simple mykernel.bin file using Ubuntu.
GPPPARAM = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exception -fno-leading-underscore
ASPARAMS = --32
LDPARAMS = -m elf_i386
objects = loader.o kernel.o
%o: %.cpp
g++ $(GPPPARAM) -o $# -c $<
%o: %.s
as $(ASPARAMS) -o $# $<
mykernel.bin : linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
the output is:
make mykernel.bin
ld -m elf_i386 -T linker.ld -o mykernel.bin loader.o kernel.o
ld: i386:x86-64 architecture of input file loader.o' is incompatible with i386 output
ld: i386:x86-64 architecture of input filekernel.o' is incompatible with i386 output
Makefile:13: recipe for target 'mykernel.bin' failed
make: *** [mykernel.bin] Error 1
If you were to show the complete output, including the compile lines for your object files, then it would be clear that your compiler flags are not being used to compile your source code. As a result, the object files being generated are for your native operating system which is most likely 64bit, when you want 32bit.
The reason for this is as I described above: your pattern rule is wrong. You have written %o : %.cpp when you wanted to write %.o : %.cpp. The pattern rule you've written tells make that if it wants to build a file loader.o (so the stem of the pattern %o matches loader.) it can do so by compiling a file loader..cpp (because the pattern character % in %.cpp is replaced with the stem loader.). Since there's no loader..cpp file, your pattern is discarded as not matching and make proceeds to look for another pattern and it finds one, as a built-in rule.
But since you are using non-standard variable names GPPPARAM instead of the standard CXXFLAGS, none of your flags are used by the default rule.
You have two choices: you can either fix your pattern rules so they're correct:
%.o: %.cpp
g++ $(GPPPARAM) -o $# -c $<
%.o: %.s
as $(ASPARAMS) -o $# $<
Or you can get rid of your own pattern rules and use make's built-in rules, and set the standard variables to ensure your options are used:
CXX := g++
CXXFLAGS := -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exception -fno-leading-underscore
AS := as
ASFLAGS := --32

Some implicit makefile?

I am trying to understand makefile.
I took atmega168 bootloader's makefile and simplified it to this:
CC = avr-gcc
override CFLAGS = -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600
atmega328: ATmegaBOOT_168_atmega328.hex
%.elf: ATmegaBOOT_168.o
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o $# $<
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
%.hex: %.elf
avr-objcopy -j .text -j .data -O ihex $< $#
When I ran $ make atmega328 I get:
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -c -o ATmegaBOOT_168.o ATmegaBOOT_168.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o
avr-objcopy -j .text -j .data -O ihex ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168_atmega328.hex
rm ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o
Why cannot I remove CC or CFLAGS?
I understand some basics of makefile. I read a lot on the internet, plus went through gnu manual, but I cannot understand the very first output with ATmegaBOOT_168.c. What/How has generated first command?
Was there used some second makefile? If yes, how to find its location?
UPDATE:
If I rename ATmegaBOOT_168.c to ATmegaBOOT_1681.c. Running $ make atmega328 gives:
make: *** No rule to make target 'ATmegaBOOT_168_atmega328.hex', needed by 'atmega328'. Stop.
but the rule is present.
CC and CFLAGS are variables used in the built in implicit rules of GNU make. When you run make, it reads your makefile a bit like:
No target given, so we'll make the first: atmega328. This requires a .hex file.
The .hex file can be generated from a .elf file per the last rule.
.elf files can be generated by the %.elf rule (which here looks like you've broken the pattern, as there's no % in the dependencies).
There's no rule for .o in this file, so the default recipe $(CC) $(CPPFLAGS) $(CFLAGS) -c is used. Since a .c file is found, this rule is applicable and generates the first command. The rule could have been written (as shown in suffix rules):
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
Backtrack up this list, now that the source has been found, and run the commands.
If the implicit rule variables are left unset, you will typically get programs built for your host system using cc.

Run a command for the nth target with the nth dependancy

I am having some confusion about how the '$<' and '$#' macros can be used with a list of elements. My ultimate goal is to compile a directory of C source files into executables with the same name, no extensions. Also I do not want to make object files.
Here is a simple makefile which I would like to upgrade using the macros.
CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
all : progA progB progC
progA : progA.c
$(CC) $(CCFLAGS) $< -o $#
progB : progB.c
$(CC) $(CCFLAGS) $< -o $#
progC : progC.c
$(CC) $(CCFLAGS) $< -o $#
This works fine, but I don't like the redundancy of the commands. I have found a workaround that works, and a near solution, but was hoping there might be a clear option.
workaround:
CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
PRGS := $(patsubst %.c,%,$(wildcard *.c))
all :
make $(PRGS)
% : *.c
$(CC) $(CCFLAGS) $#.c -o $#
What I don't like here is the call to make within the command. Running 'make' delivers a message in my terminal that looks something like this:
make[1]: Entering directory '/path/to/dir'
...actual commands...
make[1]: Leaving directory '/path/to/dir'
I am assuming this has to do with opening the same makefile and the [1] refers to the second file descriptor in the open file table (or something along those lines).
near solution:
CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
SRCS := $(wildcard *.c)
PRGS := $(patsubst %.c,%,$(SRCS))
all : $(PRGS)
$(PRGS) : $(SRCS)
$(CC) $(CCFLAGS) $< -o $#
This almost works, except it is always grabbing the first dependancy!
..... progA.c -o progA
..... progA.c -o progB
..... progA.c -o progC
So, does anyone have a cleaner method to my 'workaround' or perhaps a solution to my 'near solution'? Is there anyway to match the nth target to the nth dependency when running the command?
Thanks!
The $(PRGS): $(SRCS) change is just incorrect. It lists every source file as the prerequisites of every target.
You want to set the prerequisites of the all target to be every program you want built by default. To do that you want to use all: $(PRGS). Not a recipe of calling make again like you had originally.
(If you did want to keep the manual recursive call to make you could use make --no-print-directory on that call to avoid the message but that is still the wrong approach (and if you were going to do that you'd want to use $(MAKE) to handle arguments to the original make correctly.)
A second problem with your original makefile is the use of *.c in the prerequisite list of the % target. That sets the prerequisites of every target to be every *.c file in the directory. That's not what you want. You want each target to have its own .c file as its prerequisite.
You want:
all: $(PRGS)
%: %.c
$(CC) $(CCFLAGS) $#.c -o $#
That being said make has a built-in rule for exactly that foo.c -> foo compilation so you should just use that. That rule uses the $(CC) and $(CFLAGS) variables. So just set those to what you want and you are done.
So this makefile should do what you want. (Note how I moved some arguments to CFLAGS instead of CC. CC should generally, to my knowledge, by the compiler itself and not any arguments.)
CC = gcc
CFLAGS = -ansi -std=c99 -Wall -pedantic -O3
PRGS := $(patsubst %.c,%,$(wildcard *.c))
all : $(PRGS)

makefile which get also the name of the file compile

I need a makefile which get also the name of the file compile
For example:
make foo
and the makefile should compile foo.c to foo.
This is my makefile. How to change it?
all: out
out: out.o
gcc -g -m32 -Wall -o out out.o
out.o: out.c
gcc -m32 -g -Wall -ansi -c -o out.o out.c
.PHONY: clean
#Clean the build directory
clean:
rm -f *.o out
There is no direct way where you can pass arguments to the Makefile but instead you can take advantage of variables to achieve what you want. Check the modifications done to the Makefile below
NAME ?=out #Default binary generated is out if you dont pass any argument
${NAME}: ${NAME}.o
gcc -g -m32 -Wall -o ${NAME} ${NAME}.o
${NAME}.o: ${NAME}.c
gcc -m32 -g -Wall -ansi -c -o ${NAME}.o out.c
.PHONY: clean
#Clean the build directory
clean:
`rm -f *.o ${NAME}`
And you should call the Makefile by typing
$ make NAME=foo
$ make clean NAME=foo
Passing arguments directly to Make is trivially easy.
Your current makefile can be invoked with make foo, and will compile foo.c to produce foo, because Make has implicit rules for handling cases like foo.c => foo; there will be no error even though "foo" is not the target of any rule. (At least, this is the case with GNU Make 3.81, which is what I am using.)
If you want to control the choice of compiler and flags (as in your out rule), there is more than one way to do it. The simplest (though not strictly the best) is to modify a couple of variables in the makefile:
CC = gcc
CFLAGS = -g -m32 -Wall -ansi
Another option is to override the implicit rule with a pattern rule of your own:
%: %.c
gcc -g -m32 -Wall -ansi -o $# $<
If you want it to build foo.o in a separate step, you must split the rule into two rule-- and also put in a rule with no recipe to cancel Make's implicit rule:
%: %.o
gcc -g -m32 -Wall -o $# $^
%.o: %.c
gcc -m32 -g -Wall -ansi -c -o $# $<
%: %.c
Further refinements are possible, once you have mastered the basics.

Adding functionality to Makefile gives error :- "multiple definitoon here ..."

I have been given an already working Makefile which is actually working fine.
Makefile Contents can be found here in this post ...
Questions about Makefile - what is "$+" & where are .c files/dependencies called here ?
I am asking this question separately from my previous post mentioned above as it involves a different issue and adding it to that question would unnecessarily increase its length.
Now I have added one more functionality which is being used quite frequently at many places so I thought creating a separate file would be a nice idea so I created linklayer.c and added linklayer.o to $LIBOBJS.
I added this ...
LIBOBJS= linklayer.o csum.o compact.o protoname.o headers.o
parseargs.o cryptomod.o crc32.o
and this
linklayer.o: linklayer.c
$(CC) -o $# -c -I. $(CFLAGS) $+
I have declared function in sendip_module.h which is already declared and accessed in each of the module present in the project.
But now this multiple definition error is coming ... Have I done something wrong or misunderstood something?
Note: "ipv6_opts" is defined in ipv6.h
$ make all
for subdir in mec ; do \
cd $subdir ;\
make ;\
cd .. ;\
done
make[1]: Entering directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
gcc-4.4 -o ipv6.so -fPIC -fsigned-char -pipe -Wall -Wpointer-arith
-Wwrite-strings -Wstrict-prototypes -Wnested-externs -Winline -Werror
-g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared ipv6.c
libsendipaux.a libsendipaux.a
libsendipaux.a(linklayer.o):(.data.rel.local+0x0)
: multiple definition of `ipv6_opts'
/tmp/ccxa4tMX.o:(.data.rel.local+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [ipv6.so] Error 1
and why this libsendipaux.a libsendipaux.a two times ? Is there something wrong with the Makefile itself.
Do I first need to manually compile it and then add it to libsendipaux.a ?
I am new to this Makefile stuff, so please help me understand how this is all working out here ?
Thanks.
Edit :
Remake debugging output -
remake -x
Reading makefiles...
Updating goal targets....
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:33 File `all' does not exist.
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 File `subdirs' does not exist.
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 Must remake target `subdirs'.
for subdir in mec ; do \
cd $subdir ;\
make ;\
cd .. ;\
done
make[1]: Entering directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 Successfully remade target file
`subdirs'.
File `ipv6.so' does not exist.
Must remake target `ipv6.so'.
gcc-4.4 -o ipv6.so -fPIC -fsigned-char -pipe -Wall -Wpointer-arith
-Wwrite-strings -Wstrict-prototypes -Wnested-externs -Winline -Werror
-g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared ipv6.c
libsendipaux.a libsendipaux.a
libsendipaux.a(linklayer.o):(.data.rel.local+0x0)
: multiple definition of `ipv6_opts'
/tmp/ccb0oaXR.o:(.data.rel.local+0x0): first defined here
collect2: ld returned 1 exit status
remake: *** [ipv6.so] Error 1
#0 ipv6.so at ??
#1 all at /home/udit/Desktop/sendip-2.5-mec-2/Makefile:33
33rd line -> all: $(LIBS) subdirs sendip $(PROTOS) sendip.1 sendip.spec
I guess it could not help me out .... actual problem is with my understanding of scenario itself. Please help me bring out of the mess.
the problem you are facing, is that you are linking together several objects where at least two of them define de function ipv6_opts.
since there are two implementations of the function, your linker cannot decide which one to use and throws an error.
the problem most likely comes from the fact that you are linking libsendipaux.a twice into your final binary.
the reason why this happens is here:
%.so: %.c $(LIBS)
$(CC) -o $# $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS)
in this target, $+ will expand to all the dependencies of your target (that is: %.c $(LIBS), which will in turn be resolved to ipv4.c libsendipaux.a
the actual call to the compiler can then be read as $(CC) -o $# $(CFLAGS) $(LIBCFLAGS) ipv4.c $(LIBS) $(LIBS), and $(LIBS) $(LIBS) will expand to libsendipaux.a libsendipaux.a, which will produce the erroneous double linkeage.
so the solution is to remove extraneous $(LIBS) from the .so target:
%.so: %.c $(LIBS)
$(CC) -o $# $(CFLAGS) $(LIBCFLAGS) $+
btw, the errors you get in remake about non-existing files, are because all and subdirs are indeed no files, but phony targets (targets that do no generate files called after the target-name).
to prevent those warnings, add something like the following to your makefile:
.PHONY: all subdirs

Resources