Makefile for AVR - gcc

I have folder "I2C AtMega32":
and I have my simply Makefile:
all: main.hex program clean
main.o: main.cpp BMP280_driver-master\bmp280.c
avr-gcc -Wall -Os -mmcu=atmega32 -c $< -o $#
main.elf: main.o
avr-gcc -Wall -Os -mmcu=atmega32 -o main.elf main.o
main.hex: main.elf
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size --format=avr --mcu=atmega32 main.elf
program:
#program uC
.PHONY: clean
clean:
rm main.o main.elf
During the makefile working there is some errors:
Why it is no working?

The main issue is it looks like you are trying to compile two different compilation units into one object file. I would be surprised if GCC supports that, since I've never seen it before. Compile an object with gcc for each C source file, then compile an object with g++ for each C++ source file, then link them all together.
Also note that $< is just the name of the first prerequisite (main.cpp) so you never even attempted to compile the bmp280 code. Pay attention carefully to the commands your Makefile is running when you want to debug your build.
By the way, the all target should just build your HEX file. You can run make program or make clean separately to perform those tasks, and the program target should of course depend on main.hex.

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)

Compiling SDL project on Raspberry Pi

I am trying to build a project with make (gcc on Raspbian)
Here is the makefile (I removed some unnecessary parts):
objects = 3d.o Affichage.o [...]
cflags = -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
poly : %(objects)
gcc $(cflags) $(objects) -o poly
($objects) : types.h
[...]
When running Make, I got:
cc -c -o Affichage.o Affichage.c
fatal error: SDL.h: No such file or directory
#include <SDL.h>
I checked the folders, everything seems ok. SDL.h is indeed in /usr/local/include/SDL2. I tried to remove options one by one in cflags, no luck...
What am I missing?
Make told you exact command it tried to execute:
cc -c -o Affichage.o Affichage.c
This don't have -I path, which is the source of an error.
You have target for your resulting executable but not for object files. Make have builtin rule to compile object files from C sources, but it isn't aware of your cflags variable. So far your options are:
Define your own pattern rule
e.g:
%.o: %.c
gcc $(cflags) -c $< -o $#
However, your cflags contains -lSDL2, which is linking flag, which should be specified only on linking phase (so technically it isn't cflag). Move it to separate variable (usually LIBS, which may then be enfolded into make's semi-standard LDFLAGS).
Use variables that make is aware of
In that case, it is CFLAGS:
CC:=gcc
CFLAGS:=-I/usr/local/include/SDL2
LIBS:=-lSDL2
LDFLAGS:=-L/usr/local/lib $(LIBS)
objects:=3d.o Affichage.o
poly: $(objects)
$(CC) $^ -o $# $(LDFLAGS)
$(objects): types.h
The rest will be done by implicit rules.

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.

Creating a makefile for CUDA programs

I want to automate the compilation of a toy library using CUDA and C++. Then I write a Makefile as follows
CC=g++
NVCC=nvcc
CXXFLAGS= -fopenmp -O3 -Wextra -std=c++11
CUDAFLAGS= -std=c++11 -c -arch=sm_20
LIBS= -lopenblas -lpthread -lcudart -lcublas
LIBDIRS=-L/usr/local/cuda-7.5/lib64
INCDIRS=-I/usr/local/cuda-7.5/include
matrix_cuda.o: marix_cuda.cu
$(NVCC) $(CUDAFLAGS) matrix_cuda.cu
all: matrix_cuda.o
$(CC) -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o $(LIBDIRS) $(INCDIRS) $(LIBS) $(CXXFLAGS)
clean:
rm -rf test *.o
Typing make I get
make: *** No rule to make target `marix_cuda.cu', needed by `matrix_cuda.o'. Stop.
I never wrote a Makefile before. Where did I go wrong?
I think you have a typo in the CUDA file name
matrix_cuda.o: marix_cuda.cu
$(NVCC) $(CUDAFLAGS) matrix_cuda.cu
IMHO it should be
matrix_cuda.o: matrix_cuda.cu
$(NVCC) $(CUDAFLAGS) matrix_cuda.cu
This may take a couple of iterations.
1) First try this:
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu
If that works (and produces matrix_cuda.o, I presume), remove matrix_cuda.o and
2) try this makefile:
matrix_cuda.o: matrix_cuda.cu
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu
If that works,
3) try this:
g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11
If that works, remove test and
4) try this makefile:
test: matrix_cuda.o
g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11
matrix_cuda.o: matrix_cuda.cu
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu
If that works, remove test and matrix_cuda.o and
5) try that makefile again.
If that works, there are further refinements we can make.
Also your first make rule corresponds to compiling the object file matrix_cuda.o. The all make rule should come first since the first rule in the make file is the one that gets updated first when invoking the command make. GNU Make has great documentation explaining how to make simple to complex makefiles. You can check it out here:
https://www.gnu.org/software/make/manual/make.html.
Also another issue you are going to run into is that in your make recipe for the all rule, you are supposed to be linking together only object files to create the final executable. However you are trying to include matrix_blas.cpp alg.cpp test.cpp in this linking step. Instead of .cpp versions of these files they need to be .o versions (the compiled objects). Make can generate these object files for you. You just need to have a make rule and recipe for each one. For example:
matrix_blas.o: matrix_blas.cpp
$(CC) $(CXXFLAGS) -c matrix_blas.cpp -o matrix_blas.o
I want to add some commentary on this Makefile for future reference and better automation :
1. NVCC=nvcc environment variable is superfluous. There is only one compiler for NVIDIA GPUs and you would nonetheless have to change a lot of flags to compile for other architectures like AMD.
-arch=native is better suited if you want to deploy your code on multiple machines with GPUs having different architectures
-dc is the flag for separate compilation. The architecture must be specified before -dc see (with a generic Makefile): https://developer.nvidia.com/blog/separate-compilation-linking-cuda-device-code/
You should add automatic rule to avoid these typos errors :
%.o: %.cu
nvcc -dc $(CUDAFLAGS) $< -o $#
The Makefile will look for all dependencies ending by .o. If it needs to build one, it looks if it has the corresponding .cu file. I would actually remove the -dc from flags and be explicit here that I want to build object files.
$# is the name of the rule target. $< is the first prerequisite. Only one file at a time can be passed to nvcc with the -dc flag, so here $< is better than $^.
You may add the name of the executable in a variable so that you delete the same executable that you generated (and facilitate name change).
I added a .PHONY rule. This only removes the confusion that happens whenever someone writes a file named clean in the directory.
The Makefile can not differenciate between the file and the make clean rule.
CC=g++
CXXFLAGS= -fopenmp -O3 -Wextra -std=c++11
CUDAFLAGS= -std=c++11 -arch=sm_20
LIBS= -lopenblas -lpthread -lcudart -lcublas
LIBDIRS=-L/usr/local/cuda-7.5/lib64
INCDIRS=-I/usr/local/cuda-7.5/include
PROGRAM= test
%.o: %.cu
nvcc -dc $(CUDAFLAGS) $< -o $#
all: matrix_cuda.o
$(CC) -o $(PROGRAM) matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o $(LIBDIRS) $(INCDIRS) $(LIBS) $(CXXFLAGS)
.PHONY: clean
clean:
rm -rf $(PROGRAM) *.o

Compile C++ with Cygwin

How do I compile my C++ programs in Cygwin. I have gcc installed. What command should I use? Also, how do I run my console application when it is in a .cpp extension. I am trying to learn C++ with some little programs, but in Visual C++, I don't want to have to create a seperate project for each little .cpp file.
You need to use a command like:
g++ -o prog prog.cpp
That's a simple form that will turn a one-file C++ project into an executable. If you have multiple C++ files, you can do:
g++ -o prog prog.cpp part2.cpp part3.cpp
but eventually, you'll want to introduce makefiles for convenience so that you only have to compile the bits that have changed. Then you'll end up with a Makefile like:
prog: prog.o part2.o part3.o
g++ -o prog prog.o part2.o part3.o
prog.o: prog.cpp
g++ -c -o prog.o prog.cpp
part2.o: part2.cpp
g++ -c -o part2.o part2.cpp
part3.o: part3.cpp
g++ -c -o part3.o part3.cpp
And then, you'll start figuring how to write your makefiles to make them more flexible (such as not needing a separate rule for each C++ file), but that can be left for another question.
Regarding having a separate project for each C++ file, that's not necessary at all. If you've got them all in one directory and there's a simple mapping of C++ files to executable files, you can use the following makefile:
SRCS=$(wildcard *.cpp)
EXES=$(SRCS:.cpp=.exe)
all: $(EXES)
%.exe: %.cpp
g++ -o $# $^
Then run the make command and it will (intelligently) create all your executables. $# is the target and $^ is the list of pre-requisites.
And, if you have more complicated rules, just tack them down at the bottom. Specific rules will be chosen in preference to the pattern rules:
SRCS=$(wildcard *.cpp)
EXES=$(SRCS:.cpp=.exe)
all: $(EXES)
%.exe: %.cpp
g++ -o $# $^
xx.exe: xx.cpp xx2.cpp xx3.cpp
g++ -o $# $^
echo Made with special rule.
You will need g++. Then try g++ file.cpp -o file.exe as a start. Later you can avoid much typing by learning about Makefiles.
if you want to use cygwin you should use the normal gcc syntax
g++ -o foobar foobar.cpp
but that doesn't really play well with Visual C++. I advise you to take a look into Eclipse CDT if you prefer using GCC over the visual C++ compiler.
What I do to compile a cpp program:
g++ -Wall Test.cpp -o Test
-Wall enables warning and error messages to be shown
-o Test creates an Test.exe after compilation
If you want to compile files separately:
g++ -Wall -c File1.cpp
g++ -Wall -c File2.cpp
Now create an executable with the combined object files as:
g++ -Wall File1.o File2.o -o File.exe
This way you can compile your header files and you can include in your application programs.

Resources