These are the files after edit, now the makefile works fine:
//a.h
#ifndef A_H
#define A_H
#include <stdio.h>
int fun(int i);
#endif
//a.c
#include "a.h"
int fun(int i){
if(i%2==0){
return 1;
}
printf("%d\n",i);
}
//b.h
#ifndef B_H
#define B_H
#include "a.h" //included a.h as fun2() uses fun() in a.h
int fun2(int i);
#endif
//b.c
#include "b.h"
#include <stdio.h>
int fun2(int i){
if(i%2==0){
return 1;
}
printf("%d\n",fun(2));
}
//c.c
#include "b.h" //b.h becauses fun2() in this, and a.h is in this header, explanation in b.h
#include "a.h" //I have now included a.h also as this uses fun(), multiple inclusions don't matter as these headers have include guards
#include <stdio.h>
int main(){
int a=1;
a=fun(1);
printf("%d %d\n",a,fun(1));
int b=1;
b=fun2(2);
printf("%d %d\n",b,fun2(1));
}
I don't need .c files or definitions of external functions I use in something.c, I just need their headers (or declarations) to create .o (object files).
Therefore, to create, b.o from b.c, I have included a.h and b.h for function definitions and gcc -c b.c creates b.o
Similarly, c.o is made using gcc -c c.c , I have included a.h and b.h in c.c as I use their functions.
lastly, just link them together, gcc -o main a.o b.o c.o
This is the new make file, I ws making it wrong, was including .c of the external function while making their .o, this time I just include headers and do gcc -c a.c, b.c or c.c (separately for these 3), after this I link a.o b.o c.o to make a dynamically linked exec named main:
CC=gcc
all:main
main: a.o b.o c.o
$(CC) $^ -o $@
c.o: c.c a.h b.h
cc -c $<
b.o: b.c b.h a.h
cc -c $<
a.o: a.c a.h
cc -c $<
.PHONY:clean
clean:
rm -rf *.o
rm -rf main
This is the output of make:
─# make
cc -c a.c
cc -c b.c
cc -c c.c
gcc a.o b.o c.o -o main
I did nm on these .o files, and figured out the undefined functions marked by U.
─#nm a.o
0000000000000000 T fun
U printf
─#nm b.o
U fun
0000000000000000 T fun2
U printf
─#nm c.o
U fun
U fun2
0000000000000000 T main
U printf
The symbols marked with U are undefined.In b.o fun() is marked U as it is in a.o.
I tried combining them with ld:
─#ld -relocatable a.o b.o -o ab.o
─# ls ab.o
ab.o
─# file !:1
file ab.o
ab.o: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), not stripped
─# nm ab.o
0000000000000000 T fun
000000000000003c T fun2
U printf
//This ab.o has fun defined, and is therefore marked with T
─# ld -relocatable ab.o c.o -o abc.o
─# nm abc.o
0000000000000000 T fun
000000000000003c T fun2
0000000000000080 T main
U printf
//fun, fun2 are marked with T in abc.o, they were U in c.o
─# gcc abc.o -o abc
─# ./abc
1
1
2 2
1
1 2