Why recipe for target 'mykernel.bin' failed? - makefile

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

Related

Can't use LAPACK in makefile

I have program (in fortran) where I'm using three custom modules, which make use of LAPACK. Until now I've compiled my program using the following shell script:
filestring="main"
gfortran -c mod_exp.f90 mod_genmat.f90 mod_print.f90 $filestring.f90
gfortran mod_exp.o mod_genmat.o mod_print.o $filestring.o -llapack -lblas
rm mod_exp.o mod_genmat.o mod_print.o $filestring.o exponentiate.mod genmat.mod printing.mod printing_subrtns.mod
mv a.out $filestring
Since I've been using more and more modules and different programs using them, I've decided to start using makefiles. Following a tutorial, I managed to write the following:
FC = gfortran
FFLAGS = -Wall -Wextra -llapack -lblas #-fopenmp
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ)
clean:
#rm -f *.o *.mod main
However, when executing make, it says that the LAPACK functions are not recognized. One such mistake is the following:
/usr/bin/ld: mod_exp.o: in function `__exponentiate_MOD_diagun':
mod_exp.f90:(.text+0x37f): undefined reference to `zgees_'
...
collect2: error: ld returned 1 exit status
One possible mistake I've seen is that I need to specify the location of the libraries. However, it would seem strange since I didn't need to do it before; also, I don't know how to find it.
Please show the link command that make invoked, that caused the error to be generated.
I'm confident that if you cut and paste that exact command line to your shell prompt, you will get the same error you see when make runs it. So the problem is not make, but your link command.
The problem is that you have put the libraries before the objects in the link line. Libraries should come at the end, after the objects, else when the linker examines the libraries it doesn't know what symbols will need to be included (because no objects have been parsed yet to see what symbols are missing).
This is why LDLIBS is traditionally a separate variable:
FC = gfortran
FFLAGS = -Wall -Wextra #-fopenmp
LDLIBS = -llapack -lblas
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ) $(LDLIBS)

Makefile not invoking rule dependencies

So here's my question: Why is the following makefile failing to build the only .c file in the directory? I have a fairly simple makefile for building my operating system kernel, and for some reason, it's not building the .c files required for the kernel rule to build.
The directory only contains a single .c file and the following Makefile:
GCCPARAMS = -m32 -ffreestanding -Wall -Wextra -nostdinc -nostdlib
GPPPARAMS = -m32 -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti -nostdinc -nostdlib
ASPARAMS = --32
LDPARAMS = -m32 -ffreestanding -O2 -nostdlib
C_FILES := $(wildcard *.c)
CPP_FILES := $(wildcard *.cpp)
S_FILES := $(wildcard *.s)
OBJ_FILES := $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o) $(S_FILES:.s=.o)
all: kernel
%.o: %.cpp
g++ $(GPPPARAMS) -c $< -o $#
%.o: %.c
gcc $(GCCPARAMS) -c $< -o $#
%.o: %.s
as $(ASPARAMS) $< -o $#
kernel: $(C_FILES) $(CPP_FILES) $(A_FILES)
ld -r $(OBJ_FILES) -o ../kernel.o
As you can see, I clearly have $(C_FILES) in the list. However, running make all or make kernel yields the following output:
ld -r core.o -o ../kernel.o
ld: cannot find core.o: No such file or directory
Makefile:23: recipe for target 'kernel' failed
make: *** [kernel] Error 1
Now, I've called even added to the kernel rule a print routine to test the C_FILES variable which does, in fact, print core.c (The one .c file in the directory), and the linker clearly received the OBJ_FILES list, so why is it not building core.c?
You need to define your object files as prerequisite to the kernel rule, because the kernel rule depends on them. It only depends indirectly from the source files.
kernel: $(C_FILES) $(CPP_FILES) $(A_FILES) $(OBJ_FILES)
ld -r $(OBJ_FILES) -o ../kernel.o

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.

Resources