Makefile for multiple executables with common files - c

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

Related

Understand the dependency levels of makefiles

Assume that the project has the following files, where the first files is dependent on the files under it's category in the unordered list:
main.c
global.h (contains enumerations and #define macros)
sdlevent.h (generic header file)
sdlevent.c (contains implementations of sdlevent.h)
sdlshape.h (generic header file)
sdlshape.c (contains implementations of sdlshape.h)
Now, I have the following makefile:
CC = gcc
CFLAGS = -g -w -std=c99
LIBS = -lSDL2 -lSDL2_image -lSDL2_ttf
SRCS = main.c sdlshape.c sdlevent.c
OBJS = $(SRCS:.c=.o)
EXE = play
all: $(EXE)
.c.o:
$(CC) -c $(CFLAGS) $<
$(EXE): $(OBJS)
$(CC) -o $(EXE) $(OBJS) $(LIBS)
$(OBJS): global.h sdlevent.h sdlshape.h
run : all
./$(EXE)
clean:
rm -f *.o *~ $(EXE)
The target $(EXE) is dependent on the target .c.o. Do I absolutely need to define the target $(EXE) after the target .c.o?
I don't think so, because even though the target $(EXE) is dependent on the target $(OBJS), the target ($EXE) is declared before $(OBJS).
Do I absolutely need to define the target $(EXE) after the target .c.o?
First, .c.o is not a target, it's a suffix rule.
Second, make does not care what sequence targets are written in, so the answer is "no". The whole makefile is read and when a target is missing, a lookup is performed for a rule to create the target. Technically, make creates a directed acyclic graph (DAG) of targets and dependencies before it considers building anything. Variable references are replaced when they are used, not when they are read (exception: GNU make's := assignment operator).
Try playing around with the order of targets. You can even move the variable assignments to the bottom.
I'm sure there are a few esoteric corners in GNU make where things work slightly differently, but in a simple makefile as yours, not straying too far from a POSIX makefile, that's how it works.

Makefile: "ld: can't link with a main executable file" in C

I am trying to compile two c files, calutil.c and calutil.h into one executable. Here is my makefile:
CC = gcc
CFLAGS = -Wall -std=c11 -DNDEBUG
all: caltool
caltool: calutil.o caltool.o
$(CC) $(CFLAGS) calutil.o caltool.o
caltool.o: caltool.c
$(CC) $(CFLAGS) caltool.c -o caltool.o
calutil.o: calutil.c
$(CC) $(CFLAGS) -c calutil.c -o calutil.o
clean:
rm -rf *.o *.out
calutil.c has no main, while caltool.c has a main. I get the error
ld: can't link with a main executable file when I make. What is the cause of this?
The main problem is that some your recipe for linkage is missing the output file, and that your compilation is missing -c.
In case you're using GNU make, the following Makefile would be sufficient to do what you want to do:
CFLAGS:=-Wall -std=c11
CPPFLAGS:=-DNDEBUG
.PHONY: all
all: caltool
caltool: caltool.o calutil.o
.PHONY: clean
clean::
$(RM) *.o
Explanation:
When you're not using target-specific variables, you should use := instead of = to assign variables so that they're expanded at assignment and not at evaluation.
When your Makefile grows and you split it, you might want to have multiple targets called clean which all would be executed. In that case use clean:: instead of clean:.
There's a predefined variable to call rm, it is $(RM) and it includes the -f flag to prevent the Makefile from failing in case one or more of the files to be removed do not exist in the first place.
The pattern for clean should be *.[adios] (that's really easy to remember, adios is Spanish for goodbye) so that it removes intermediate archives (.a when you build your own static libraries), dependency files (.d), preprocessor output (.i) and assembler files (.s) in case you use -save-temps to see what the compiler is doing.
GNU make has built-in rules to compile and link, see http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=3.81
The built-in rule for compilation calls $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $# $< so you don't need to write your own rule.
The built-in rule for linkage calls $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $#
Targets which are not files themselves should be declared .PHONY to prevent confusion when a user creates a file with the same name, like all or clean.
I do not see how any of your commands would create a file matching the glob pattern *.out, so I removed that part of the clean rule.
Flags for the preprocessor should go into CPPFLAGS instead of CFLAGS. Preprocessor flags typically are all those -D and -I flags and would also be passed to other tools that use a C preprocessor in the same project, like splint or PC-Lint.
When the Makefile is run, it is looking how to make all, and it finds that for all it has to make caltool. For caltool it finds that it has to first make calutil.o and caltool.o. When it tries to make calutil.o and caltool.o, it finds that it can make them from calutil.c and caltool.c and will do so. Then it will link caltool.o and calutil.o into caltool.
From your naming I guessed that it's caltool.c that contains the main() function. It is helpful to place the object which contains main() first once you use static link libraries.
Edit: Here's some more magic for you. I assume that you have a header file calutil.h which is included by caltool.c to access extern symbols provided by calutil.c. You want to rebuild all objects that depend on these header files. In this case, add the following lines to your Makefile:
CPPFLAGS+=-MMD
-include caltool.d calutil.d
In order to not have the list of objects multiple times, you could add a variable objects like this:
objects:=caltool.o calutil.o
You would then build the application with this rule:
caltool: $(objects)
And include the dependency files like this:
-include $(objects:.o=.d)
In case you keep your working tree "clean", i.e. do not "pollute" it with "alien" code, i.e. you always want to include all .c files in your project, you can change the definition of objects as follows:
sources:=$(wildcard *.c)
objects:=$(sources:.c=.o)
In case you wonder why it is CPPFLAGS (uppercase) but objects (lowercase): it is common to use uppercase for all variables which configure the recipes of rules and control the built-in behavior of make, tools built on top of it, and classic environment variables, and lowercase variables for everything else.
I just removed the .o files from the directory, and edited my makefile to add -c to the caltool.o line.

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.

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 $# $^

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

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.

Resources