'make' does not recompile when source file has been edited - c

I'm writing a little implementation of Conway's Game of Life in C. The source code is split in three files: main.c and functions.c/functions.h, where I put my functions definitions and declarations.
Now, to create a grid of cell, I have a matrix of this type:
Cell grid[GRID_HEIGHT][GRID_WIDTH];
where GRID_HEIGHT and GRID_WIDTH are constants defined in functions.h:
#define GRID_HEIGHT 10
#define GRID_WIDTH 10
The program runs fine, compiled with make and Makefile. But the problem is: if I try to change GRID_HEIGHT or GRID_WIDTH, when I run again my Makefile it says that all files are up-to-date!
I've tried to compile using the good ol' way gcc main.c etc. and it runs as it should. So, why make does not recompile the source?
This is my Makefile:
CC = gcc
OBJECTS = main.o functions.o
Game\ of\ Life : $(OBJECTS)
$(CC) $(OBJECTS) -o Game\ of\ Life -lncurses
%.o : %.c
$(CC) -c $<

Because you haven't told it that recompilation depends on functions.h.
Try adding this to your Makefile:
%.o : functions.h
Alternatively, modify your existing rule to be:
%.o : %.c functions.h
$(CC) -c $< -o $#

You've told make that .o files don't depend on .h files, so it doesn't recompile anything when a header changes.
Getting it to work right is hard (you need to generate dependencies for each .c file), but an easy way is just to define HEADERS which contains all your header files and make each .o file depend on all your headers.

If you're using GCC (well, you are), then it can be solved generically by passing -MD option to the compiler, GCC will generate a file containing Make dependencies on included headers:
CC = gcc
OBJECTS = main.o functions.o
%.o : %.c
$(CC) -MD -c $<
-include $(OBJECTS:.o=.d)
Some headers-related information can also be found in this question.

Related

Makefile object file generation, variable substitution, and other questions

I'm currently trying to create a Makefile for a c university project, but reading through the tutorials hasn't quite helped me (also, the makefile is not part of the evaluation process, and we aren't taught how to do it)
My objective is making the makefile automatic, so it automatically creates object files from .c files in src (src/*.c), puts the object files in the bin folder, and links them into an executable in the main directory.
project/
bin/
(object files)
src/
(source files)
executable
Makefile
So far, I've roughly put together this makefile and test source code, but it doesn't work the way I intend it to, which I'll explain how just ahead:
#compiler used
COMPILER = gcc
#flags for individual object file compilation
FLAGS = -Wall -ansi -g
#RELEASE
# -Wall -ansi -O3
#DEVELOPMENT
# -Wall -ansi -g
#source .c files
SOURCE = $(wildcard src/*.c)
#object files created
OBJECTS = $(SOURCE:.c=.o)
OBJECTS = $(SOURCE: src/=bin/)
#executable name
EXECUTABLE = app
############################################################
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(COMPILER) $(FLAGS) -o $(EXECUTABLE) $(OBJECTS)
%.o: %.c
$(COMPILER) $(FLAGS) -c %< -o %#
The result is the following command:
user#user-lenovo:~/Desktop/C Projects/AED/project$ make
gcc -Wall -ansi -g -o app src/main.c src/test.c
Ironically, it works, but really shouldn't. It also defeats the purpose of having a makefile, as everything is compiled again once one change is detected.
First of all, what I noticed is OBJECTS directly copied SOURCE, and didn't substitute .c for .o, or src/ for bin/. I've tried substituting the '=' for ':=' but the result is the same, and I don't quite understand what the difference between them is in the first place. My idea would be src/main.c becoming bin/main.o, for example.
%.o: %.c
$(COMPILER) $(FLAGS) -c %< -o %#
This part is my also failed attempt at generating all the object files individually with a single target. I tried reading up on it, but couldn't figure out how these work: '%<', '%#' or the '%.o' and '%.c'
I do believe it isn't being run at all though, since no object files showed up.
I hope you can help me fix this mess up, thanks in advance!
OBJECTS = $(SOURCE:.c=.o)
OBJECTS = $(SOURCE: src/=bin/)
You're assigning to OBJECTS twice there - the first result gets overwritten by the second which doesn't work. You want to combine them into one statement like this
OBJECTS=$(SOURCE:src/%.c=bin/%.o)
Your next problem is you need to tell make that "bin/whatever.o" is built from "src/whatever.c". Currently it'll look for "whatever.c" in "bin/"
So your recipe for building .o files needs the directories added
bin/%.o: src/%.c
$(COMPILER) $(FLAGS) -c $< -o $#
You also should have $# instead of %# and $< instead of %<
Automatic variables are expanded with the $ prefix, as any other variable, not %.
As your object and source files are in different directories you cannot simply %.o: %.c.
Try:
CC = gcc
CFLAGS = -Wall -ansi -g
OBJECTS = $(patsubst src/%.c,bin/%.o,$(SOURCE))
bin/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $#
Note: the standard make variable for the C compiler is CCand CFLAGS for the flags. It is better to use them.

Avoiding unecessary recompilation with makefile

I'm using makefile with gcc. Every c file has an accompanying header:
main.c main.h
test.c test.h
main.c includes main.h and test.h
test.c includes test.h
I want to avoid recompiling every c file. Makefile is ran without -B argument.
I can write the whole makefile manually and specify every dependency. When editing headers only the necessary c files get recompiled. An edit in test.h will recompile both c files and a change in main.h will only recompile main.c. As it should.
This doesn't work when I switch to the more automated approach:
OBJ = main.o test.o
%.o: %.c %.h
$(CC) -c -o $# $<
main: $(OBJ)
$(CC) -o main $(OBJ)
A change in test.h will only recompile test.c. Leaving main.c in the old with the old version of test.h header. I'm forced to run makefile with -B, if I want to use this approach.
I can specify the headers manually:
DEPS = main.h sort.h
%.o: %.c $(DEPS)
$(CC) -c -o $# $<
Then a change in main.h recompiles both main.c and test.c, the latter being unnecessary.
Updating every change in the makefile is unwieldy if I have a lot of files, and using the automated approach will increase compilation times.
Is there a better solution, one that only recompiles the needed files, or is specifying everything manually the only way?
You can specify additional dependencies of main.o using another line:
OBJ = main.o test.o
main.o: test.h
If you decide to specify manually, though, you're doing it wrong; you don't want to add the dependencies to the pattern where it takes effect for every object file. You define it separately for each object file so they're only rebuilt when the right ones change:
OBJ = main.o test.o
%.o: %.c
$(CC) -c -o $# $<
main: $(OBJ)
$(CC) -o main $(OBJ)
main.o: main.h test.h
test.o: test.h
Maintaining those last lines is what the automated dependency generation does, if you decide you want to try to use it.

Creating a Makefile in Raspbian

I'm trying to create a Makefile for my C program in Raspbian (Raspberry Pi).
My program consists of a bunch of .c and .h Files. I've looked at countless Makefiles, but I just don't unterstand how it works with multiple files. There are always .o files in the Makefile but as I understand object files are the result of compiling, so I dont have any o. Files as I am trying to compile my .c Files.
Please explain to me how this works.
Edit:
Thank you. So I tried this and it starts compiling but there are errors 'multiple definition'. Example:
These are my Files:
main.c main.h
calibration.c calibration.h
file.c file.h
frame.c frame.h
gamepad.c gamepad.h
gpio.c gpio.h
uart.c uart.h
types.h
this is my makefile:
all: main
main: main.o calibration.o file.o frame.o gamepad.o gpio.o uart.o
%.o: %.c
gcc -c -std=c99 -Wall $< -o $# -lncurses
Where can i put 'types.h'?
With every file I get errors 'multiple definitions'
A very simple but typical makefile could look like this
SOURCES = source1.c source2.c source3.c
OBJECTS = $(SOURCES:%.c=%.o)
TARGET = myExecutable
$(TARGET): $(OBJECTS)
gcc $^ -o $#
%.o: %.c
gcc -c $< -o $#
The complicated parts:
SOURCES = source1.c source2.c source3.c This is a variable definition, it assigns the string "source1.c source2.c source3.c to the variable SOURCES.
$(SOURCES:%.c=%.o) This is a shorthand for the patsubst text function. It takes all text from the $(SOUCES) variable, and replaces the pattern %.c with %.o, i.e. it takes e.g. the string source1.c and replace it with source1.o.
$(TARGET): $(OBJECTS) This makes myExecutable depend on all object files, meaning if one object file is modified then the command in the rule will be executed.
gcc $^ -o $# This calls the gcc command, passing all dependencies ($^) as arguments (that is, all object files), and tells gcc to output a file with the name of the target ($#).
%.o: %.c This is the rule that makes object files depend in their source file. So if you have source1.c then source1.o will depend on that source file.
gcc -c $< -o $# This is the command that compiles the source file (the first dependency, $<) to an object file (with the -c option) and name it as the target of the rule ($#).
Also note that if you invoke make without a specific target, then the first rule will be selected. In the case of the above makefile, it will be the $(TARGET): $(OBJECTS) rule which will make sure that all object files are build from the source files, and then link the object files into the resulting executable.
The basic syntax of a make rule is:
target … : prerequisites …
recipe
…
…
On the left of the semicolon are the targets. The targets are your object files(.o). On the right of the semicolon are the files that you will need to create this file. Those files are the source files(.c).
Lets give a basic example of what such a rule could look like.
%.o: %.c
gcc -c $< -o $#
The % sign is a wildcard. %.o means everything that ends with .o. So, if you want to make an object file, you can say make file.o, and make will try to find a rule with which it can make this target. This happens to be the rule I just showed as an example, because file.o matches %.o.
Then the recipe. This is what will be executed. Usually it's about invoking the compiler(gcc), and feeding it the source file to generate the object file. That's what we do with gcc -c $< -o $#. The $< and $# mean target and prerequisites respectively.
So, what happens when you 'just' want to build your program? You usually will type make, and it will build. The default rule that's used when you type make, is all. So, if you make a rule about all, then you can specify what files you want to create to build your program. Example of such a rule:
all: main
Then, when make is invoked, it will find that rule and finds out it needs main. To create main you need another rule:
main: file.o
This rule says that to build main, you need file.o. So, when you put all of the example rules together you get this:
all: main
main: file.o
%.o: %.c
gcc -c $< -o $#
Note that you can specify more than one file, so instead of file.o, you can say file.o main.o other_file.o etc. Every prerequisite that you specify will be made, if they can find a rule to make it.

Makefile for multiple executables with common files

I need help in writing a makefile that creates two separate executables that depend on a common file. So, I have three source files: Master.c Common.c Worker.c, and three corresponding header files. Now, Master.c includes Master.h and Common.h. Similarly, Worker.c includes Worker.h and Common.h. I would like to create two executables, namely Master and Worker, using the same makefile. I have the following makefile, but it's not functioning properly because for each global variable declared in Common.h, I get the error "Multiple declarations" when I type make. Note that I do use #indef, #define, and #endif in all the header files.
CC = gcc
CFLAGS= -g -I -pthread -lpthread -std=c99
DEPS = Common.h
OBJ1 = Master.o Common.o
OBJ2 = Worker.o Common.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: Master Worker
Master: $(OBJ1)
gcc -o $# $^ $(CFLAGS)
Worker: $(OBJ2)
gcc -o $# $^ $(CFLAGS)
clean:
rm -f *.o
Can you please help
Don't put the definitions of global variables into headers; instead, put them in one of the source files and only declare the variables in the header:
Common.h:
extern int foo; /* declaration only */
Common.c:
#include "Common.h"
int foo; /* definition */
Otherwise including the header in more than one translation unit violates the one-definition rule.
is the makefile above flawless?
No. I can see several issues, if you fix them then it would be "state-of-the-art":
(a bug) all targets should at least depend on $(MAKEFILE)
MAKEFILE := $(lastword $(MAKEFILE_LIST))
you will then also need to filter the $^ in the recipe: $(filter %.o, $^), which is a good practice anyway
use := instead of =, it is more efficient and makes the logic in your code easier to understand in general, should always be used by default, unless = is necessary
you are defining CC to be gcc then not using it but using gcc instead
consider generating dependencies automatically (grep the manual), in this small case not needed perhaps, but for a larger case you will need it - there is good support in gcc for that nowadays
use a "canned recipe" (grep the manual) for the repeating recipe
.PHONY: all clean
clean does not remove everything

What is the proper standard for Makefiles?

I'm currently writing small simple C programs. As of now my Makefiles have consisted of text something along the lines of:
program_name:
clang -o program_name program_name.c
Is this all I need? I wasn't sure if I needed to establish dependencies between .o and .h files, even if they don't necessarily exist in my project.
You are working too hard. You should simplify your Makefile to 2 lines:
CC=clang
program_name: some.h
There is no need to specify the dependency on program_name.o or program_name.c, since those are implied. There is also no need to give the rule explicitly, since you are using the default rule. Dependencies on header files do need to be spelled out, however.
I use GNU Make myself. Not sure what you're using. For GNU Make, refer to:
http://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html#Makefile-Conventions
http://www.gnu.org/software/make/
Is this all I need?
No.
I wasn't sure if I needed to establish dependencies between .o and .h files
Generally, you should, especially if you're using custom data types (and even if not: a change in a function signature can break the whole program if the ABI/calling conventions on your platform consist of black magic).
The template I'm using is usually:
CC = gcc
LD = $(CC)
CFLAGS = -c -Wall
LDFLAGS = -lwhatever -lfoo -lbar
TARGET = myprog
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(LD) $(LDFLAGS) -o $# $^
%.c: %.h
%.o: %.c
$(CC) $(CFLAGS) -o $# $^

Resources