Reputation: 23
I have these sources and headers. How do I make a make file for them?
//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"
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"
#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));
}
This is the makefile I have created:
//makefile
CC=gcc
all:main
main: c.c b.o
$(CC) c.c b.o -o $@
b.o: b.c a.o
cc -c b.c a.o
a.o: a.c
cc -c a.c
.PHONY:clean
clean:
rm -rf *.o
rm -rf main
b.c use function fun() defined in a.h (and therefore, fun() is declared in a.c).
c.c uses functions fun() from a.h and fun2() in b.h.
a.h is already included in b.h and I am including b.h in c.c.
Therefore, I have not included a.h again in c.c.
I am trying to make .o files of all of these a.c b.c and c.c, and then link them into a executable named main.
Upvotes: 0
Views: 64
Reputation: 23
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
Upvotes: 1
Reputation: 99094
First, trying to combine two source files (like a.c
and b.c
) into a single object file is unusual, awkward and pointless. Just build an object for every source; if you like, you can combine them into a library later.
b.o: b.c
cc -c b.c
Second, you're using object files (which is a good idea), so use object files. Don't make c
an exception.
main: a.o b.o c.o
$(CC) a.o b.o c.o -o $@
Third, Make already has an implicit rule for building object files from C source files, so you don't have to write those rules,
Fourth and last, there are more automatic variables than just $@
, and they're good tools to know:
main: a.o b.o c.o
$(CC) $^ -o $@
Upvotes: 1