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

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).

Related

How to write Make rules for *.h files as dependencies

I'm trying to understand how to handle header file dependencies in Make rules. Let me give you a specific example.
I'm building application called myap using GNU Make. It consists of various *.h and *.c files.
Directory inc/ contains defs.h and util.h header files.
Directory src/ contains main.c, cmd.c and win.c files.
Directory obj/ contains all generated object files.
I have multiple applications that need different build options. So I don't want to rely on any implicit rules and would like to specify my own rules for all object files, etc.
I would like to specify the following rules:
Object files depend on specific *.h and *.c files. If any of them change, all object files must be regenerated. However, even though *.h files are part of the prerequisites list, I don't want to pass them to the compiler. I only want to compile *.c files.
Executable myapp depends on specific *.o files. If any of them change, executable file must be regenerated.
So far, the following Makefile with a static pattern rule seems to work correctly:
myapp_inc := inc/defs.h inc/util.h
myapp_src := src/main.c src/cmd.c src/win.c
myapp_obj := $(patsubst src/%.c,obj/%.o,$(myapp_src))
myapp_bin := obj/myapp
.PHONY: all
all:
# Create obj/main.o obj/cmd.o and obj/win.o from various *.c files
# If any *.h files in $(myapp_inc) list change, all objects are regenerated.
# If any *.c files in $(myapp_src) list change, all objects are regenerated.
$(myapp_obj): obj/%.o: src/%.c $(myapp_inc) $(myapp_src)
gcc -c -o $# $<
# Create obj/myapp from various *.o files
# If any *.o files in $(myapp_obj) list change, executable is regenerated.
$(myapp_bin): $(myapp_obj)
gcc -o $# $^
all: $(myapp_bin)
.PHONY: clean
clean:
rm -f obj/*
I don't quite understand how Make rules should be written correctly in order to handle such use case. Is the above static pattern rule, the only way that works correctly?
Specifically, I have tried the following combinations, as given in various simple examples on the Internet, and they all failed for various reasons.
This rule causes $< to always pass the name of the first prerequisite, which doesn't work with multiple *.c files:
$(myapp_obj): $(myapp_src) $(myapp_inc)
gcc -c -o $# $<
$ make
gcc -c -o obj/main.o src/main.c
gcc -c -o obj/cmd.o src/main.c
gcc -c -o obj/win.o src/main.c
gcc -o obj/myapp obj/main.o obj/cmd.o obj/win.o
/bin/ld: obj/cmd.o: in function `main':
main.c:(.text+0x0): multiple definition of `main'; obj/main.o:main.c:(.text+0x0): first defined here
/bin/ld: obj/win.o: in function `main':
main.c:(.text+0x0): multiple definition of `main'; obj/main.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:18: obj/myapp] Error 1
This rule causes $^ to always pass the names of all prerequisites, which fails:
$(myapp_obj): $(myapp_src) $(myapp_inc)
gcc -c -o $# $^
$ make
gcc -c -o obj/main.o src/main.c src/cmd.c src/win.c inc/defs.h inc/util.h
gcc: fatal error: cannot specify ‘-o’ with ‘-c’, ‘-S’ or ‘-E’ with multiple files
compilation terminated.
make: *** [Makefile:13: obj/main.o] Error 1
Now I understand the difference between $< and $^ variables, but a lot of documentation is not clear on how they should be used when dealing with a list of multiple *.c and *.h files as prerequisites.
What are the recommended usage pattern for this?
Why is it that when using $< only *.c files get passed to the recipe, but not *.h files? Is Make doing some internal filtering? Is this documented anywhere? Is it possible to modify this behavior for custom suffixes?
Is the above static pattern rule, the only way to make objects depend on *.h and *.c files, but exclude *.h files during compilation?
I don't understand the goal of trying to avoid implicit rules. But in any event, it doesn't matter to the recipe you write whether the rule was implicit or explicit: the same automatic variables are set either way. The $< automatic variable is always the first prerequisite, so if you write your rules such that the first prerequisite is the appropriate .c file then you can always use $< in your recipe to mean the .c file and no other files. All the following will work:
%.o : %.c $(headers)
gcc -c -o $# $<
foo.o: foo.c $(headers)
gcc -c -o $# $<
foo.o : %.o : %.c $(headers)
gcc -c -o $# $<
%.o : %.c
gcc -c -o $# $<
$(srcs) : $(headers)
and others.
Does this mean that all of the prerequisites apply, but only those that match the pattern get passed to the recipe?
I don't understand the question, really. The value of variables and the expansion of the recipe happens only AFTER make has decided to run the rule and is not really related (except for some special automatic variables like $?). Once make has decided that the target is out of date and the recipe needs to be run, it will assign the appropriate automatic variables, expand the recipe, then pass the recipe to the shell to be run.
The automatic variables are assigned as described in the manual: $# is the target, $< is the first prerequisite, $^ is all the prerequisites, etc.
ETA
You still haven't really explained why you don't want to use static pattern rules. They are a perfectly fine and reasonable way to do things.
If you explain what you don't like about static pattern rules, or what you wish you could do differently, then we can probably suggest alternatives that meet those requirements.
Specifically, I have tried the following combinations, as given in various simple examples on the Internet,
$(myapp_obj): $(myapp_src) $(myapp_inc)
Wherever you found this as a recommended example on the Internet, you should immediately delete from any bookmarks as that site doesn't know anything about make.
We see this paradigm at least once a week on SO. I've never really understand why people think it will work: I guess they think make is much more "magical" than it is. Consider, what does the above expand to? Suppose myapp_obj contained foo.o bar.o biz.o and myapp_src contained foo.c bar.c biz.c and myapp_inc contained foo.h bar.h, then make sees:
foo.o bar.o biz.o: foo.c bar.c biz.c foo.h bar.h
I suppose some people think make will intuit that the ".o" files should somehow match up with the ".c" files and will generate a bunch of rules that make that true. That's not what make does. The above line is exactly identical to writing this:
foo.o: foo.c bar.c biz.c foo.h bar.h
bar.o: foo.c bar.c biz.c foo.h bar.h
biz.o: foo.c bar.c biz.c foo.h bar.h
That is, if you have multiple targets make creates one copy of the rule for each target, with the same prerequisites and recipe.
This is obviously not what you want, and that's why none of the examples that try to do things this way can ever work properly.
Why is it that when using $< only *.c files get passed to the recipe, but not *.h files? Is Make doing some internal filtering? Is this documented anywhere? Is it possible to modify this behavior for custom suffixes?
None of that is the case. As I described above, the $< expands to the first prerequisite. That's all. It doesn't matter whether the first prerequisite is a .c file, a .h file, or some other file; whatever it is, $< will be that value. If you write your rule as:
foo.o : foo.c foo.h ; $(CC) -c -o $# $<
then your compiler will be invoked with foo.c. If you write your rule as:
foo.o : foo.h foo.c ; $(CC) -c -o $# $<
then your compiler will be invoked with foo.h. There's no magic here.

What is the syntax for copying in makefile [duplicate]

CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
What do the $# and $< do exactly?
$# is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.
For example, consider the following declaration:
all: library.cpp main.cpp
In this case:
$# evaluates to all
$< evaluates to library.cpp
$^ evaluates to library.cpp main.cpp
From Managing Projects with GNU Make, 3rd Edition, p. 16 (it's under GNU Free Documentation License):
Automatic variables are set by make after a rule is matched. They
provide access to elements from the target and prerequisite lists so
you don’t have to explicitly specify any filenames. They are very
useful for avoiding code duplication, but are critical when defining
more general pattern rules.
There are seven “core” automatic variables:
$#: The filename representing the target.
$%: The filename element of an archive member specification.
$<: The filename of the first prerequisite.
$?: The names of all prerequisites that are newer than the target,
separated by spaces.
$^: The filenames of all the prerequisites, separated by spaces. This
list has duplicate filenames removed since for most uses, such as
compiling, copying, etc., duplicates are not wanted.
$+: Similar to $^, this is the names of all the prerequisites separated
by spaces, except that $+ includes duplicates. This variable was
created for specific situations such as arguments to linkers where
duplicate values have meaning.
$*: The stem of the target filename. A stem is typically a filename
without its suffix. Its use outside of pattern rules is
discouraged.
In addition, each of the above variables has two variants for
compatibility with other makes. One variant returns only the directory
portion of the value. This is indicated by appending a “D” to the
symbol, $(#D), $(<D), etc. The other variant returns only the file
portion of the value. This is indicated by appending an “F” to the
symbol, $(#F), $(<F), etc. Note that these variant names are more than
one character long and so must be enclosed in parentheses. GNU make
provides a more readable alternative with the dir and notdir
functions.
The $# and $< are called automatic variables. The variable $# represents the name of the target and $< represents the first prerequisite required to create the output file.
For example:
hello.o: hello.c hello.h
gcc -c $< -o $#
Here, hello.o is the output file. This is what $# expands to. The first dependency is hello.c. That's what $< expands to.
The -c flag generates the .o file; see man gcc for a more detailed explanation. The -o specifies the output file to create.
For further details, you can read this article on linoxide about Linux Makefiles.
Also, you can check the GNU make manuals. It will make it easier to make Makefiles and to debug them.
If you run this command, it will output the makefile database:
make -p
The $# and $< are special macros.
Where:
$# is the file name of the target.
$< is the name of the first dependency.
The Makefile builds the hello executable if any one of main.cpp, hello.cpp, factorial.cpp changed. The smallest possible Makefile to achieve that specification could have been:
hello: main.cpp hello.cpp factorial.cpp
g++ -o hello main.cpp hello.cpp factorial.cpp
pro: very easy to read
con: maintenance nightmare, duplication of the C++ dependencies
con: efficiency problem, we recompile all C++ even if only one was changed
To improve on the above, we only compile those C++ files that were edited. Then, we just link the resultant object files together.
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
main.o: main.cpp
g++ -c main.cpp
hello.o: hello.cpp
g++ -c hello.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
pro: fixes efficiency issue
con: new maintenance nightmare, potential typo on object files rules
To improve on this, we can replace all object file rules with a single .cpp.o rule:
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
.cpp.o:
g++ -c $< -o $#
pro: back to having a short makefile, somewhat easy to read
Here the .cpp.o rule defines how to build anyfile.o from anyfile.cpp.
$< matches to first dependency, in this case, anyfile.cpp
$# matches the target, in this case, anyfile.o.
The other changes present in the Makefile are:
Making it easier to changes compilers from g++ to any C++ compiler.
Making it easier to change the compiler options.
Making it easier to change the linker options.
Making it easier to change the C++ source files and output.
Added a default rule 'all' which acts as a quick check to ensure all your source files are present before an attempt to build your application is made.
in exemple if you want to compile sources but have objects in an different directory :
You need to do :
gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...
but with most of macros the result will be all objects followed by all sources, like :
gcc -c -o <all OBJ path> <all SRC path>
so this will not compile anything ^^ and you will not be able to put your objects files in a different dir :(
the solution is to use these special macros
$# $<
this will generate a .o file (obj/file.o) for each .c file in SRC (src/file.c)
$(OBJ):$(SRC)
gcc -c -o $# $< $(HEADERS) $(FLAGS)
it means :
$# = $(OBJ)
$< = $(SRC)
but lines by lines INSTEAD of all lines of OBJ followed by all lines of SRC

How can I have a step in a makefile to generate preprocess files and compile from those files?

I took a makefile from a previous project that compiles programs for an avr microcontroller. I ran into some problems with what IO ports/data directional addresses I was setting which was causing the microcontroller to fault and reset. Because of this I wanted to add a step in my makefile to have it generate the pre-proccessed files and then compile from these preprocessed files. I'm not too familiar with how rules/dependencies work in makefiles so I've made, what I believe is, a simple mistake in my understanding of how makefiles work. My rules to make the preprocessed files/object files and eventually the .elf file must be wrong. Up until I added the steps which attempted to create the preprocessed files creating the .elf file work fine. What is my simple mistake/understanding in how rules/dependencies work in make?
How I view this working is when I ask to make all it sees that it has a dependency of led.elf. To create this it has the dependency of the preprocessed files based on the line of $(OUTPUT).elf: $(PROCESS_FILES) so it starts with this line. When I try to make all however I get the error make: *** No rule to make target 'main.c', needed by 'main.e'. Stop. and I don't understand why. Can anyone help my understanding in make files?
SRC_FILES=\
main.c led.c comm.c
#Object files
PROCESS_FILES=$(SRC_FILES:.c=.e)
OBJ_FILES=$(PROCESS_FILES:.e=.o)
#Directories where to look for include files
INC_DIRS=\
-I. \
#Output file name
OUTPUT=led
#Programmer and port
PROG=dragon_isp
PORT=usb
#Debugging host and port
DHOST=localhost
DPORT=6423
#Compiler related params
MCU=atmega2560
CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS= -mcall-prologues -std=gnu99 -funsigned-char -funsigned bitfields \
-fpack-struct -fshort-enums -mmcu=$(MCU) -Wall -Wstrict-prototypes \
$(INC_DIRS)
#Optimization level
CFLAGS+=-Os
#Debug info
CFLAGS+=-gdwarf-2
#Generate hex file ready to upload
all: $(OUTPUT).elf
$(OBJCOPY) -R .eeprom -O ihex $(OUTPUT).elf $(OUTPUT).hex
#Link output files
$(OUTPUT).elf: $(PROCESS_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
#Create object files
$(PROCESS_FILES): %.e : %.c
$(CC) -E $(CFLAGS) $< -o $#
$(OBJ_FILES): %.o : %.e
$(CC) -x $(CFLAGS) $< -o $#
#Create assembler file of a C source
%.s: %.c
$(CC) -S $(CFLAGS) $< -o $#
#Cleans all generated files
clean:
rm -f $(OBJ_FILES)
rm -f $(OUTPUT).elf
rm -f $(OUTPUT).hex
rm -f $(OUTPUT).map
Edit: I'm away from my computer now so I can't check this but thinking about my issue I'm starting to think I don't have a file named main.c in that directory. Even if I did I still think the makefile would not work correctly because I don't fully understand rules in makefiles.
My error was coming from the fact that I did not have a main.c file in my directory. Make sure you backup files when you're messing with the OBJ_FILES or similar variable and have a line that will delete whatever is in that variable upon a make clean.
As for the rules, I had to make one small fix to achieve what I wanted. I changed
$(OUTPUT).elf: $(PROCESS_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
to
$(OUTPUT).elf: $(OBJ_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
This then sees it needs the object files which in turn needs the preprocessed files.
Edit: I also changed OBJ_FILES=$(PROCESS_FILES:.e=.o) to OBJ_FILES=$(SRC_FILES:.c=.o). I also added $(PROCESS_FILES) to $(OUTPUT).elf: $(OBJ_FILES) so the rule would generate both the preprocessed files and object files independently. I had to change $(OBJ_FILES): %.o : %.e to $(OBJ_FILES): %.o : %.c to make this work.

Makefile - a command in a command?

I have an embarrassingly simple makefile question but I can't google it due to lack of knowledge - I don't know the words for things I don't know.
Basically, I want to run the makefile in the current directory, look into the ./SRC directory for source files and when everything is finished, move the object files into the ./OBJ directory.
Makefile:
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj
I want to call "move_obj" after compiling the source files but since I don't know what
result: dependency
evaluation
actually represents (and all makefile introduction guides I've found state "This is what a makefile looks like, off you go then"), I don't know why this isn't working. I assume I need some evaluate command or need to define a function or...?
Thanks for any help in advance.
You can do this by creating another rule for example move, like below
all: $(EXECUTABLE) move
$(EXECUTABLE): $(OBJECTFILES)
$(CC) -o $# $<
$(OBJECTFILES): $(SOURCEFILES)
$(CC) $(CFLAGS) -c -o $# -I $(INCLUDE_PATH) $<
# Move the .o to Object directory #
move:
$(MV) $(OBJECTFILES) $(OBJECT_PATH)
But by doing the above, you will defeat the purpose of the Makefile.
Since your rule is dependent on .o, Make will look for .o in current directory and not find it (because you've moved it) and thus rebuild.
To avoid this, you should output it to ./obj directory and use it from there.
Something like
gcc -g -Wall -o obj/foo.o -c src/foo.c -I ./include
gcc -g -Wall -o obj/main.o -c src/main.c -I ./include
gcc -o exe obj/foo.o obj/main.o -lanylibrary
Below is the makefile doing the same.
C_FLAGS := -g -Wall -Wextra
CC := gcc
RM := rm
LINKFLAGS := -lanylibrary
.PHONY: $(TARGET) clean
VPATH:= ./src/ ./obj/ ./include/
# Path for .c , .h and .o Files
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INC_PATH := -I ./include
# Executable Name
TARGET := exe
# Files to compile
OBJ1 := foo.o \
main.o
OBJ := $(patsubst %,$(OBJ_PATH)%,$(OBJ1))
# Build .o first
$(OBJ_PATH)%.o: $(SRC_PATH)%.c
#echo [CC] $<
#$(CC) $(C_FLAGS) -o $# -c $< $(INC_PATH)
# Build final Binary
$(TARGET): $(OBJ)
#echo [INFO] Creating Binary Executable [$(TARGET)]
#$(CC) -o $# $^ $(LINKFLAGS)
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -rfv $(TARGET)
Refer to this answer for a better understanding
EDIT:
You can also output your executable to directory, add the following changes to your Makefile.
Ensure that the bin directory is created beforehand, and not deleted by clean.
# Path for .c , .h and .o Files, and ./bin directory
BIN_PATH := ./bin
# Executable Name
TARGET := $(BIN_PATH)/exe
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -fv $(TARGET)
If you want to build a target(move_obj) after another(file.o), add the move_obj to the dependency list of file.o so that the commands under the move_obj will be executed.
So your Makefile should be:
file.o: other_file.h move_obj
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
As Colonel Thirty Two mentioned in the comment section, instead of compiling and then move, you can build the object files in the required directory
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o ./$(OBJ_FILES)/$#
This is flawed in various ways.
result normally is an actual file that should be present after the recipe is executed. If the file is already there and is not older than any of its dependencies, make does nothing. So instead of creating a file somewhere and then moving it around with another rule, make sure the rule creates it where it should FINALLY be. Otherwise make can never check whether it has to rebuild it (and always will). In this case, use the -o flag of the compiler to directly create it where it should be (e.g. -o $(OBJ_DIR)/file.o)
dependency should list ALL files that are needed to build the result, so make really rebuilds it if ANY of these files changed. In your case, at least file.c is missing from the dependency list
In order to place files in a directory, you should make sure it exists. you could do it like this:
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/file.o: $(OBJ_DIR) file.c other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o $(OBJ_DIR)/file.o
Your move_obj recipe, although not suitable in this case, would be a PHONY target, meaning it does not create a file. If you need such rules, mark them accordingly by mentioning them as dependency of the special target .PHONY:
.PHONY: move_obj
The reason for this is that you could (by accident) have a file named move_obj in your working directory. In that case, make would decide there's nothing to do for move_obj, and this is not what you want. Marking it as phony tells make that this rule does not create its target and the recipe must be executed no matter what.
All in all, your question comes down to misunderstanding a Makefile as kind of a script. It is not. It's a declarative file that tells make what has to be done in order to build files (your evaluation block) and when this needs to be done (your dependency block). It's better not to try to misuse a Makefile as a script.

Makefile runs over C file twice

I have two files: assign1.c and ports.h.
FYI: I am using avr-gcc.
I built the following makefile, which I also use for another project (and other TARGET) where it works fine.
TARGET = assign2
LIB=
INCLUDE=ports.h
CFLAGS =-mmcu=atmega32 -Wall
CC = avr-gcc
SRC= $(TARGET).c
OBJ= $(SRC:.c=.o)
OBJCOPY = avr-objcopy
FORMAT = ihex
MSG_COMPILING = Compiling:
MSG_LINKING = Linking:
MSG_FLASH = Creating load file for flash:
all:elf hex
elf: $(TARGET).elf
hex: $(TARGET).hex
%.hex: %.elf
#echo $(MSG_FLASH) $#
#echo
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $#
$(RM) *.elf $(TARGET)
#echo
%.elf: $(OBJ) $(LIB)
#echo $(MSG_LINKING) $#
#echo
$(CC) $(CFLAGS) $^ -o $#
#echo
%.o: $(SRC) $(INCLUDE)
#echo $(MSG_COMPILING) $<
#echo
$(CC) $(CFLAGS) -c $<
#echo
.PHONY : clean
clean:
$(RM) *.o *.hex *.elf $(TARGET)
The terminal prints the following output.
C:\Project>make
Compiling: assign2.c
avr-gcc -mmcu=atmega32 -Wall -c assign2.c
In file included from assign2.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"
Linking: assign2.elf
avr-gcc -mmcu=atmega32 -Wall assign2.o -o assign2.elf
Compiling: assign2.c
avr-gcc -mmcu=atmega32 -Wall -c assign2.c
In file included from assign.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"
avr-gcc elf.o assign2.elf -o elf
avr-gcc: elf.o: No such file or directory
make: *** [elf] Error 1
rm assign2.o
C:\Project>
For some reason it seems to compile the first file, a second time and doing so crashes.
Can anyone correct me on my errors?
The problem is your pattern rules. You are writing pattern rules like this (after make expands the variables):
%.o: assign2.c ports.h
What this rule tells make is that ANY target it wants to build that matches the %.o pattern, can be built by compiling assign2.c. That's obviously not true: this rule build exactly one target: assign2.o.
So make reads your makefile and wants to build a file named elf. It sees that elf depends on $(TARGET).elf, so it builds that (that's the first compile and link, that works). Then make wants to build elf itself. You haven't declared it to be .PHONY, so make assumes it might be a real target.
Make looks through its built-in rules to find one that will let it build elf, and it finds a built-in rule: % : %.o which it can use to compile a program from a .o file with the same prefix. So now for target elf make wants to try to build a file elf.o. Oho! It sees there's a pattern rule that lets it build any .o file based on the assign2.c source file, so it runs that rule (that's the second compile) expecting it to build elf.o... which it doesn't, obviously.
Then make runs the built-in link recipe, using elf.o which doesn't exist, and fails.
The solution to your problem is two things:
First, you should always declare all your makefile targets that you don't actually want to build as .PHONY so make won't try to build them:
.PHONY: all elf hex
Second, you should never use pattern rules where the prerequisite is not also a pattern (this can be useful in certain very specific situations, but not in general). You should either change those pattern rules to explicit rules:
assign2.elf: $(OBJ) $(LIB)
...
$(OBJ): $(SRC) $(INCLUDE)
...
Or make them into full pattern rules by using the pattern in the prerequisites list as well:
%.elf : %.obj $(LIB)
...
%.o: %.c $(INCLUDE)
...

Resources