Linux Make & Makefile

about me

EE degree back in 1982

Z80 was the most popular CPU

Pascal/Fortran/COBOL were popular languages

Apple ][ + BASIC and CP/M

intel 80386SX PC mother board designer

......

Interested in Linux since 2016

Z80 CPU

intel 80386SX CPU

 

photo source: wikipedia.org

Apple ][

marconi.jiang@gmail.com

References

WHAT ARE MAKE & MAKEFILE

Make & Makefile

make (Reminder: Linux is case sensitive. "Make" will be treated as Command not found.)

- A compiler tool embedded in Linux Shell (GNU project)

- Usually stored in /usr/bin/

- To prepare to use make, user must create a file called "makefile" that describes the relationships among files in your program and provides commands for updating each file.

makefile

- A user created file for make to follow compiler instructions

- Makefile is saved in the same directory of the source files you intend to compiler. Users might create one or many Makefile's for different projects

- By default, when make looks for the makefile, it tries the following names, in order: GNUmakefile, makefile and Makefile.

- You can also specify your own makefile by -f parameter

 

$ make
$ make -f MyMakefile

Example of C Code

- Let me use the following C code (show_byes.c) as an example to demonstrate the use of makefile.

    Example : show_byes.c accept your input in 'int' (decimal) format, and display in hex format in int, (type cast to) float, and physical address

    Usage: ./show_byes int_number

#include <stdio.h>
#include <unistd.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len) {
    int i;
    for (i = 0; i < len; i++)
        printf(" %.2x", start[i]);
    printf("\n");
}

void show_int(int x) {
    show_bytes((byte_pointer) &x, sizeof(int));
}

void show_float(float x) {
    show_bytes((byte_pointer) &x, sizeof(float));
}

void show_pointer(void *x) {
    show_bytes((byte_pointer) &x, sizeof(void *));
}

int main(int argc, char *argv[]) {

    int ival = atoi(argv[1]);

    float fval = (float) ival;
    int *pval = &ival;

    show_int(ival);
    show_float(fval);
    show_pointer(pval);

    return 0;
}

Using gcc w/o makefile

$ gcc -Wall -o main show_bytes.c
$ ./main  65537
 01 00 01 00
 80 00 80 47
 2c ca 54 51 ff 7f 00 00
$

* the 3rd lines will be different each time you run the program, as the program address changes

 

It is simple and straight forward....

... for a single program,

but maybe not for complex programs when you don't want to waste time to re-compile all source codes if you only modify few of the programs

make + makefile is smart enough to decide what (modified) needs re-compile and what not (unchanged)

C Example for makefile

#include <stdio.h>
#include <unistd.h>

extern void show_int(int x);

extern void show_float(float x);

extern void show_pointer(void *x);

int main(int argc, char *argv[]) {

    int ival = atoi(argv[1]);

    float fval = (float) ival;
    int *pval = &ival;

    show_int(ival);
    show_float(fval);
    show_pointer(pval);

    return 0;
}

Split into 2 files to demonstrate makefile usage

main.c

 

 

 

 

 

show_byte.c

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len) {
    int i;
    for (i = 0; i < len; i++)
        printf(" %.2x", start[i]);
    printf("\n");
}

void show_int(int x) {
    show_bytes((byte_pointer) &x, sizeof(int));
}

void show_float(float x) {
    show_bytes((byte_pointer) &x, sizeof(float));
}

void show_pointer(void *x) {
    show_bytes((byte_pointer) &x, sizeof(void *));
}

Makefile Template

#compiler 
CC = gcc 
#cflags 
CFLAGS = -Wall -ansi -g 
#source 
SRCS = main.c show_bytes.c 
#object 
OBJS = $(SRCS:.c=.o) 

all: main

main: $(OBJS)
	$(CC) $(OBJS) -o $@ 

main.o: main.c

show_bytes.o: show_bytes.c

clean: 
	-rm -f *.o

Using gcc w/ makefile

$ make
gcc -Wall -ansi -g -c -o show_bytes.o show_bytes.c
gcc main.o show_bytes.o -o main 
$ ./main  65537
 01 00 01 00
 80 00 80 47
 2c 1a 86 5e ff 7f 00 00
$

* the 3rd lines will be different each time you run the program, as the program address changes

 

Using 'make' is more efficient when you get familiar with it

makefile Rules

Rule #1: "Tab" is a must  multiple "spaces"

#compiler 
CC = gcc 
#cflags 
CFLAGS = -Wall -ansi -g 
#source 
SRCS = main.c show_bytes.c 
#object 
OBJS = $(SRCS:.c=.o) 

all: main

main: $(OBJS)
	$(CC) $(OBJS) -o $@ 

main.o: main.c

show_bytes.o: show_bytes.c

clean: 
	-rm -f *.o

Linux Make

By Marconi Jiang

Linux Make

Personal user guide of Linux Make

  • 259