Makefile: header dependency and multiple inclusion - makefile

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.

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

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

Related

Why does the definition of makefile not take effect using -D?

I wrote a simple c++ code. I wanted to choose to execute one of the codes through the -D option of makefile, but it didn't execute? For example, code1 and code2.
1.main.cpp
#include "./common.h"
#include "./ns_api.h"
int TestFunc3(void)
{
}
int test = 10;
int main(int argv, char **argc)
{
extern int b;
int a = b;
printf("This is a test!\n");
#ifdef TEST_ADD
printf("test_add!\n"); //code1
#endif
#if TEST_SUB
printf("test_sub!\n"); //code2
#endif
return 0;
}
int b;
2.makefile
root#cat makefile
GPP = g++
CFLAGS += -O3
objects = *.o
src = *.cpp
test:$(objects)
$(GPP) $(CFLAGS) -o test $(objects)
$(objects):$(src)
$(GPP) -c $(src)
.PHONY:clean
clean:
rm test *.o
3.compile
root#make CFLAGS=-DTEST_ADD CFLAGS+=-DTEST_SUB=1
g++ -c *.cpp
g++ -DTEST_ADD -DTEST_SUB=1 -o test *.o
4.result:
root#./test
This is a test!

Makefile simple rule how to

Is there a simple way to achieve the following with a simple suffix rule (or other way)?
SRC = a.c b.c c.c d.c e.c
ASM = a.s b.s c.s d.s e.s
$(ASM) : $(SRC)
gcc -S -O0 a.s a.c
gcc -S -O0 b.s b.c
...
gcc -S -O0 e.s e.c
You should probably split the target for every assembly output, something along the lines of (not tested):
SRC = a.c b.c c.c d.c e.c
ASM = $(SRC:.c=.s)
%.s: %.c
gcc -S -O0 $<
Considering that gcc -S x.c produces an x.s by default (see gcc(1)).

makefile fails - implicit rule compiles one object file but doesn't compile the rest

Makefile isn't using implicit rules correctly. I am following this guide here.
Here's my makefile:
objects = main.o hello.o
hello : $(objects)
cc -o hello $(objects)
hello.o : defs.h
main.o : defs.h hello.h
.PHONY : clean
clean :
-rm hello $(objects)
I get the following error:
cc: error: main.o: No such file or directory
It creates the object code hello.o, but does not do it for main.c. If I swap lines and main is above, it'll create main.o but not hello.o.
Here's my main.c file:
#include "defs.h"
#include "hello.h"
int main(int argc, char** argv) {
display_hello();
return (EXIT_SUCCESS);
}
Here's my hello.c file:
#include "defs.h"
void display_hello()
{
printf("Hello!\n");
}
My hello.h file:
#ifndef HELLO_H
#define HELLO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* HELLO_H */
void display_hello();
Here's my defs.h file:
#ifndef DEFS_H
#define DEFS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* DEFS_H */
#include <stdio.h>
#include <stdlib.h>
Works fine for me, I created the files as https://gist.github.com/boyvinall/f23420215707fa3e73e21c3f9a5ff22b
$ make
cc -c -o main.o main.c
cc -c -o hello.o hello.c
cc -o hello main.o hello.o
Might be the version of make like #Beta said, but even an old version of GNU make should work just fine for this.
Otherwise, ensure you're using tabs to indent in the makefile, not spaces.

make: *** [main.o] Error 1

I am executing a simple makefile that contait 3 parts but it does not work well these are details of my files .h and .c:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "hello.h"
int main (void)
{
hello();
return EXIT_SUCCESS;
}
hello.h
#ifndef hello
#define hello
void hello (void);
#endif
hello.c
#include <stdio.h>
#include <stdlib.h>
void hello (void)
{
printf("Hello World\n");
}
makefile
all: hello
hello: hello.o main.o
gcc -o hello hello.o main.o
hello.o: hello.c
gcc -o hello.o -c hello.c -W -Wall -ansi -pedantic
main.o: main.c hello.h
gcc -o main.o -c main.c -W -Wall -ansi -pedantic
clean:
rm -rf *.o
mrproper: clean
rm -rf hello
I get this error:
When you write #define hello you define hello to be an empty token. Thus the function declaration on the next string effectively becomes this:
void (void);
which is not valid C code.
What you are trying to do is probably the Include guard, its purpose is to avoid multiple inclusion of one header. The name of the guard have to differ from any other token you use. Usual naming is FILENAME_H:
#ifndef HELLO_H
#define HELLO_H
void hello(void);
#endif
In hello.h, line 2 you are defining 'hello' as an empty token. Remove that line.

Does not compile with a preprocessor value on the command-line

Where am I going wrong; I want to define a preprocessor value on the command-line for g++ but it fails. Below is sample code that replicate my problem:
[edit] I'm using:g++ (Debian 4.3.2-1.1) 4.3.2GNU Make 3.81
test.h
#ifndef _test_h_
#define _test_h_
#include "iostream"
#if defined(MY_DEFINED_VALUE)
#if (MY_DEFINED_VALUE != 5)
#undef MY_DEFINED_VALUE
#define MY_DEFINED_VALUE 3
#endif //(MY_DEFINED_VALUE != 5)
#else //defined(MY_DEFINED_VALUE)
#error Error - MY_DEFINED_VALUE is not defined
#endif //defined(MY_DEFINED_VALUE)
class test
{
public:
int val;
test() {}
void show() { std::cout << "val = " << val << "\n"; }
};
#endif //_test_h_
test.cpp
//#define MY_DEFINED_VALUE 5
#include "test.h"
int main()
{
test t;
t.val = MY_DEFINED_VALUE;
t.show();
return 0;
}
Makefile
#=====
CC = g++
LD = g++
USERDEFINES = -DMY_DEFINED_VALUE
CFLAGS = -Wall
LDFLAGS =
RM = /bin/rm -f
SRCS = test.cpp
OBJS = test.o
PROG = test
#=====
$(PROG): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROG)
#=====
%.o: %.c
$(CC) $(USERDEFINES) $(CFLAGS) -c $<
#=====
clean:
$(RM) $(PROG) $(OBJS)
If I uncomment the #define in test.cpp, all is well (prints 5). If I comment it I get the #error.
The problem is in your Makefile. The %.o: %.c rule doesn't match a .cpp file, so GNU Make's built-in %.o: %.cpp rule is being triggered instead.
If you change %.o: %.c to %.o: %.cpp, it'll run fine.

Resources