I'm trying to write a makefile that goes through compilation step by step, the issue is on the fourth step, linking.
The program consists of multiple files, starting with main.c:
#include "file1.h"
#include "file2.h"
int main() {
printout1("Print one");
printout2(5);
return 0;
}
file1.h
#include <stdio.h>
void printout1(char *str);
file1.c
#include "file1.h"
void printout1(char *str) {
printf("%s\n", str);
}
file2.h
#include <stdio.h>
#include "file1.h"
void printout2(int);
file2.c
#include "file2.h"
void printout2(int val) {
printf("%d\n", val);
printout1("Print two");
}
I'm trying to compile this program with the following makefile:
all:
cpp main.c main.i
gcc -S main.i
as -o main.o main.s
ld -o main.o
The following error occurs:
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
main.o: in function 'main':
main.c:(.text+0xa): undefined reference to 'printout1'
main.c:(.text+0x14): undefined reference to 'printout2'
makefile:2 recipe for target 'all' failed
make:***[all] Error 1
I'm fairly new to this sort of thing and I know the problem are the header files, I just don't know how to include them in this.
Two main issues:
gcc
is a frontend for all the required steps -- don't try to call the other tools of your toolchain directly, always use gcc
. This will make sure it always adds the required options for these other tools.
You have functions in different compilation units (file1 and file2), but never compile and link these.
A sensible Makefile for GNU make with your structure would look like this:
CC ?= gcc
all: main
main: main.o file1.o file2.o
$(CC) -o$@ $^
%.o: %.c
$(CC) -c -o$@ $<
.PHONY: all
This compiles all .c
files directly to object files, and finally links them (using $(CC)
, so, e.g. gcc
) to your final executable. The rule all
is marked as .PHONY
because it doesn't create a file named all
-- you should let make
know about that.
You can of course add additional steps explicitly, but it doesn't make much sense.