Federico Gentile
Federico Gentile

Reputation: 5940

How to set up correctly makefile and get the right results in this C program

I wrote a C code which is formed by these files: main.c, kernel.c, funzione.c, funzione.h and struttura.h. Here are the files:

main.c:

#include <math.h>
#include "stdio.h"

#include "struttura.h"
#include "funzione.h"

struttura o;

#include "kernel.c"

int main(void){

  pincopallo();
  return 0;
}

kernel.c

void pincopallo(void){  
printf("o.x=%f\n",o.x);
printf("o.y=%f\n",o.y);
}

funzione.cu

#include "struttura.h"

void funzione(struttura* a){
  (*a).x  = 450;
  (*a).y  = 150;
}

funzione.h

#include "struttura.h"
void funzione(struttura* a);

struttura.h

#ifndef STRUTTURA_H
#define STRUTTURA_H

typedef struct{
  float x;
  float y;  
}struttura;

#endif /* STRUTTURA_H */

My goal is to display the values contained inside of the funzione.c file (which I don't want to modify at all just as struttura.h). However when I compile it with the makefile I wrote myself, I get the following results:

o.x=0.000000
o.y=0.000000

instead of the values 450 and 150.

Here is the make file:

enter CC=gcc
CFLAGS=-Wall
OBJS = main.o funzione.o 

all: eseguibile

eseguibile: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o eseguibile -lm

main.o: main.c funzione.h struttura.h
    $(CC) -c $(CFLAGS) main.c

funzione.o: funzione.c funzione.h struttura.h
    $(CC) -c $(CFLAGS) funzione.c

clean:
    rm -rf *.o eseguibilecode here

(watch out for the tabs). I know for sure that the makefile is not completely correct: as a matter of fact, if run it the first time, it compiles all the way. However if I modify something in kernel.c (for example I change printf("o.x=%f\n",o.x); into printf("o.x=%d\n",o.x);) and I try to compile again, the terminal will show the following message: make: Nothing to be done for all. In such case I need to do make clean and compile again in order to get the obvious error message: error: ‘struttura’ has no member named ‘z’ printf("o.x=%f\n",o.z);

So basically my questions are 2:

Upvotes: 0

Views: 70

Answers (4)

user3629249
user3629249

Reputation: 16540

Note: including a .c file in a .c file is a very bad practice

It would be much better to organize the make file like the following

and remove the #include "kernel.c" from the main.c file

beyond the following, it would be good, especially as the projects get larger, to also generate the dependency files See notes at end for a method to do that.

name = eseguibile
CC=gcc
CFLAGS :=-Wall
LIBS := -lm

SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
HDR := $(wildcard *.h)

.PHONY: all clean

all: $(name)

$(name): $(OBJ)
    #
    # ======= $(name) Link Start =========
    $(CC) -o $@ $(OBJ) $(LIBS)
    # ======= $(name) Link Done ==========
    #

%.o: %.c $(HDR)
    #
    # ========= START $< TO $@ =========
    $(CC) $(CCFLAGS) -c $< -o $@ -I.
    # ========= END $< TO $@ =========
    #

clean:
    rm -rf *.o $(name)



dependency notes:  only use the following after understanding it

#
#create dependancy files -- inference rule
# (gcc has parameters that do not require the sed utility)
#
%.d: %.c
    #
    # ========= START $< TO $@ =========
    $(CC) -M $(CPPFLAGS) $< > $@.$$$$;                      \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;     \
    rm -f $@.$$$$
    # ========= END $< TO $@ =========


#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d makefile
    #
    # ========= START $< TO $@ =========
    $(CC) $(CCFLAGS) -c $< -o $@ -I.
    # ========= END $< TO $@ =========
    #

clean: rm -rf *.o *.d $(name)

# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif

Upvotes: 0

Egor
Egor

Reputation: 33

  1. fix errors:

    void funzione(struttura* a)

is not called and values to o.x is not assigned. Call this function before calling

pincopallo();

in main.c write like this:

funzione(&o);
pincopallo();
return 0;
  1. include *.c files is not very good practice. *.h files used to include. Create kernel.h file and add into main.c and kernel.c

#include "kernel.h"

write into kernel.h declaration of pincopallo() :

void pincopallo(void);

Upvotes: 0

slugonamission
slugonamission

Reputation: 9642

main.c should be recompiled if kernel.c changes, since you #include kernel.c inside it, but make doesn't know about the dependency. You can add it to main.o too, like this:

main.o: main.c funzione.h struttura.h kernel.c
    $(CC) -c $(CFLAGS) main.c

Upvotes: 1

unwind
unwind

Reputation: 399959

You never call the funzione() function. You need to call it and pass it a pointer to o, somewhere.

Also, you really shouldn't use #include on C files, only on headers.

You need to add a dependency from somewhere to funzione.c, so Make can pick that up and re-build the file when needed. Something like:

eseguibile: main.o funzione.o

Upvotes: 1

Related Questions