Compilation Process
Compilation Process
● Pre-Processor
○ $ gcc -E [flags] [filenames]
● Compiler
○ $ gcc -S [flags] [filenames]
● Assembler
○ $ gcc -c [flags] [filenames]
○ $ objdump -d [filenames]
● Linker
○ $ gcc -o [exename] [flags] [filenames]
C Code to Machine Code
Pre-Processor
● Peculiar to the C family; other languages
don’t have this
● Processes #include, #define, #if, macros
○ Combines main source file with
headers (textually)
○ Defines and expands macros
(token-based shorthand)
○ Conditionally removes parts of the
code (e.g. specialize for Linux, Mac, …)
● Removes all comments
● Output looks like C still
Before and after preprocessing
#include <limits.h> # 1 "test.c"
# 1 "/usr/lib/gcc/x86_64-linux-gnu/10/include/limits.h" 1 3 4
#include <stdio.h> ...
# 1 "/usr/include/stdio.h" 1 3 4
int main(void) { ...
extern int fprintf (FILE *__restrict __stream,
// Report the range of `char` on this system const char *__restrict __format, ...);
printf("CHAR_MIN = %d\n" extern int printf (const char *__restrict __format, ...);
...
"CHAR_MAX = %d\n", # 874 "/usr/include/stdio.h" 3 4
CHAR_MIN, CHAR_MAX); # 3 "test.c" 2
return 0;
int main(void) {
} printf("CHAR_MIN = %d\n"
"CHAR_MAX = %d\n",
● Contents of header files inserted inline # 6 "test.c" 3 4
(-0x7f - 1)
● Comments removed
# 6 "test.c"
● Macros expanded , 0x7f);
● “Directive” lines (beginning with #) return 0;
}
communicate things like original line numbers
Compiler
● The compiler translates the preprocessed
code into assembly code
○ This changes the format and structure
of the code but preserves the
semantics (what it does)
○ Can change lots of details for
optimization, as long as the overall
effect is the same
Before and after compilation
extern int printf (const char *__restrict .file "test.c"
__format, ...); .section .rodata.str1.1,"aMS",@progbits,1
.LC0:
int main(void) { .string "CHAR_MIN = %d\nCHAR_MAX = %d\n"
printf("CHAR_MIN = %d\n" .text
"CHAR_MAX = %d\n", .globl main
(-0x7f - 1), 0x7f); main:
return 0; subq $8, %rsp
movl $127, %edx
}
movl $-128, %esi
leaq .LC0(%rip), %rdi
xorl %eax, %eax
● C source code converted to assembly language call printf@PLT
● Textual, but 1:1 correspondence to machine xorl %eax, %eax
language addq $8, %rsp
ret
● String out-of-line, referred to by label (.LC0)
.size main, .-main
● printf just referred to, not declared
Assembler
● Parses assembly code and mainly
translates into bits
○ There is some flexibility to
generate the most efficient
version of machine code
Before and after assembling
.file "test.c" $ objdump -s -r test.o
.section .rodata.str1.1,"aMS",@progbits,1 test.o: file format elf64-x86-64
.LC0:
.string "CHAR_MIN = %d\nCHAR_MAX = %d\n" RELOCATION RECORDS FOR [.text]:
.text OFFSET TYPE VALUE
.globl main 0000000000000011 R_X86_64_PC32 .LC0-0x0000000000000004
main: 0000000000000018 R_X86_64_PLT32 printf-0x0000000000000004
subq $8, %rsp
movl $127, %edx Contents of section .rodata.str1.1:
movl $-128, %esi 0000 43484152 5f4d494e 203d2025 640a4348 CHAR_MIN = %d.CH
leaq .LC0(%rip), %rdi 0010 41525f4d 4158203d 2025640a 00 AR_MAX = %d..
xorl %eax, %eax
call printf@PLT Contents of section .text:
xorl %eax, %eax 0000 4883ec08 ba7f0000 00be80ff ffff488d H.............H.
addq $8, %rsp 0010 3d000000 0031c0e8 00000000 31c04883 =....1......1.H.
ret 0020 c408c3 ...
.size main, .-main
output_dir:
mkdir output_dir
● Run mkdir output_dir if output_dir does not exist
● If it does exist, no action
Normal rule without commands
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
● To create an .o file from a .c file with the same base name, use this command
● Special variables $@ and $< give the name of the .o and .c files respectively
● Variables CC and CFLAGS can be set to customize behavior
● This rule is implicit — built into Make — you don’t have to write it yourself
Phony rule example
clean:
rm -f bomb bomb-solve *.o
.PHONY: clean
● When asked to create “clean”, run this command
○ Which deletes bomb, bomb-solve, and all object files
● Does not create a file named “clean”
The make command
● Running make in the shell will cause the shell to look for a Makefile in the current
directory. If it finds one, it will attempt to create the first target listed in the Makefile.
● You can also run make <target_name> to indicate exactly which target you want to
create.
● By convention, the first target is a phony target named all
○ so make and make all do the same thing
○ as the name implies, this is to create everything that the makefile knows how to create
● Phony rules serve as entry points into the Makefile
○ make all creates everything, make clean deletes all generated files, make check runs
tests, …
○ But you can also make bomb.o if that’s the only thing you want
A complete Makefile
CC = gcc ● OK to use undefined variables
CFLAGS = -std=c99 -g -O2 -Wall -Werror
○ LDFLAGS, LIBS
all: bomb bomb-solve
bomb: bomb.o phases.o util.o ○ Found in environment or treated as empty
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) ● Don’t need to give commands to create object
bomb-solve: bomb.o phases-solve.o util.o files from C source
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
○ But do need to list header file dependencies
bomb.o: bomb.c phases.h support.h
phases.o: phases.c phases.h support.h for each object file
phases-solve.o: phases-solve.c phases.h support.h ● Do need to give commands to create
util.o: util.c support.h
executables (missing feature)
clean:
rm -f bomb bomb-solve *.o ● all rule at the top, clean rule at the bottom
.PHONY: all clean ● One .PHONY annotation for all phony rules
all clean
LD_LIBRARY_PATH = “~/my/path”
● If you are interested in creating a dynamic library, follow the steps here:
○ Shared Libraries: https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
○ Dynamic Libraries: https://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html
Resources
https://missing.csail.mit.edu/2020/metaprogramming/
https://www.cs.cmu.edu/~15131/f17/topics/makefiles/
https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
https://makefiletutorial.com/
https://www.oreilly.com/library/view/programming-embedded-systems/0596009836/ch04.html
https://gcc.gnu.org/onlinedocs/gcc/
https://daveparillo.github.io/cisc187-reader/build-tools/make.html