Banka Don
Banka Don

Reputation: 43

Trouble with making a makefile

So I made a program that contains the files header.h, main.c, printd.c and printd.h. I've been trying to create a Makefile to compile it all together but I'm having trouble understanding it.

header.h

#ifndef SPOVAJA1_HEADER_H
#define SPOVAJA1_HEADER_H
typedef struct {
    int size;
    char* tag[3][3];
    char* text[3][128];
} header;
#endif //SPOVAJA1_HEADER_H

printd.h

#ifndef SPOVAJA1_PRINTD_H
#define SPOVAJA1_PRINTD_H

#include "header.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void printd(header* format, int i, char* niz);
#endif //SPOVAJA1_PRINTD_H

printd.c

//
// Created by Admin on 9. 03. 2021.
//

#include "printd.h"
void printd(header* format, int i, char* niz){

   char *messageOutput;

   messageOutput = (char *) malloc(sizeof(niz) + 2*sizeof(char*) +sizeof(format->text[i][0]));
   strcpy(messageOutput, format->text[i][0]);
   strcat(messageOutput, niz);

   printf("%s", messageOutput);
   free(messageOutput);
}

main.c

#include "header.h"
#include "printd.h"

header format = {
       .size = 3,
       .tag[0] = "INF",
       .tag[1] = "DBG",
       .tag[2] = "ERR",
       .text[0] = "INFO: ",
       .text[1] = "DEBUG: ",
       .text[2] = "ERROR: "
};
int main() {
   printd(&format, 2, "oops, error");
   return 0;
}

I used CLion to generate the function and header files on windows. Now I wanted to make my own Makefile to run it on Linux and I can't seem to get it right.

Makefile

CC=gcc
CFLAGS=-m32 

all: main printd

demo_printd: main.c printd.c
   gcc -o main main.c printd.c -I

clean: 
   rm demo_printd

Upvotes: 0

Views: 60

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12708

If you want your makefile to make the minimum number of compilations then you need to first think what are your dependencies.

  • Your executable is called demo_printd, which should depend on the object files (just linked only) main.o and printd.o (in case one of these files is modified, you should recreate the program by linking
cc -o demo_printd main.o printd.o
  • Main.o depends on main.c, header.h and printd.h (if any of these files gets modified, you need to compile main) with:
cc -c main.c
  • and printd.c depends on printd.h only. So in case you change printd.h or printd.c then printd.c needs to be recompiled.
cc -c printd.c
  • there's a #include <header.h> in printd.h that makes that everything that depends on printd.h will also need recompiling if header.h is modified, so anything that depends on printd.h will also depend on header.h.

So we have already all the data necessary to build our rule set. The rules will be:

  • demo_printd: main.o printd.o. To handle this rule, we execute the linker.
  • main.o: main.c header.h printd.h. To handle this rule, we recompile main.c.
  • printd.o: printd.c printd.h header.h (remember that everything that depends on printd.h also depends on header.h). This means recompiling printd.c.

So our minimum Makefile should be:

demo_printd: main.o printd.o
    cc -o demo_printd main.o printd.o
main.o: main.c header.h printd.h
    cc -c main.c
printd.o: printd.c printd.h header.h
    cc -c printd.c

Now, you'll see that the include files are dependencies in all the compilations, so as their names are repeated, we can store the list of includes in a makefile variable... this also happens with the object files list, so we can rearrange this into (we will introduce some very useful variables here):

demo_printd_objs = main.o printd.o
headers = printd.h header.h

demo_printd: $(demo_printd_objs)
    $(CC) $(LDFLAGS) -o demo_printd $(demo_printd_objs)
main.o: main.c $(headers)
    $(CC) $(CFLAGS) -c main.c
printd.o: printd.c $(headers)
    $(CC) $(CFLAGS) -c printd.c

And this is only the beginning. For a full text on using make I recommend you to continue reading on make, with some very good online references (one is the GNU MAKE textinfo documentation, that you can also get straight from your linux system, or the book on BSD's pmake, which you can get from the FreeBSD.Org site

Upvotes: 0

MadScientist
MadScientist

Reputation: 101041

You want to understand that makefile so tather than just rewrite your makefile for you, I'll try to help you understand it. Let's look at it:

 CC=gcc
 CFLAGS=-m32 

Here you're setting two variables CC and CFLAGS. Why? What is the goal of setting these variables?

all: main printd

Here you're telling make that there's a target all and it depends on two targets main and printd. Why? What do you expect this to do?

demo_printd: main.c printd.c

Here you are saying that a target demo_printd depends on two files main.c and printd.c, which is fine. However:

gcc -o main main.c printd.c -I

What does this compile line do? What output file does it generate? If you type that into your shell prompt (which is basically what make is going to do, except in an automated way) what happens?

Upvotes: 2

Related Questions