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
- C example code from Computer Systems - A Programmer's Perspective
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- 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;
}$ 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)
#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 *));
}
#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$ 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
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