Program Translation text Compilation Linking 1 C program

  • Slides: 18
Download presentation
Program Translation text Compilation & Linking 1 C program (p 1. c) Compiler (gcc

Program Translation text Compilation & Linking 1 C program (p 1. c) Compiler (gcc -S) text Asm code (p 1. s) Assembler (gcc or as) binary Object code (p 1. o) Linker (gcc or ld) binary CS@VT Static libraries (. a) Executable program (p 1) Computer Organization I © 2005 -2019 WD Mc. Quain

Typical C Program Organization // single file Compilation & Linking 2 For very small

Typical C Program Organization // single file Compilation & Linking 2 For very small programs, code is often organized in a single source file; the most common convention uses the extension c for C source files. For more interesting C programs, the code is typically organized into a collection of header files (extension h) and source files. In most cases, the header files contain only type declarations and function prototypes, while the c files contain the corresponding implementations. // a. h // b. h // main. c // z. h . . . // a. c // b. c // z. c #include directives are used within both h and c files to “import” declarations as necessary. CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Build Process: Pre-processing Compilation & Linking 3 The C pre-processor will load the

The Build Process: Pre-processing Compilation & Linking 3 The C pre-processor will load the contents of #include'd header files into the. c files: // A. h // B. h // C. h #include "B. h" void B(); void C(); void A(); // main. c // A. c // B. c // C. c #include "A. h" #include "B. h" #include "C. h". . . From this point, the. h files are of no concern to the compiler (or later stages). CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Build Process: Inclusions Compilation & Linking // main. c // A. c //

The Build Process: Inclusions Compilation & Linking // main. c // A. c // B. c // C. c void A(); void B(); void C(); void B(); void B() { void C(); void G(); // definition void A() { . . . // definition void F() { B(); // call A(); // call B(); // call C(); // call G(); // call } 4 // definition } } } void G() { // definition Why would B. c #include B. h? } - perhaps B. h #includes standard headers needed in B. c - perhaps B. h defines a type needed in B. c CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Build Process: Compilation & Linking 5 The compiler processes each. c file separately

The Build Process: Compilation & Linking 5 The compiler processes each. c file separately from the others. // main. c // A. c // B. c // C. c void A(); void B(); void C(); void B(); void B() { void C(); void G(); // definition void A() { . . . // definition void F() { B(); // call A(); // call B(); // call C(); // call G(); // call } // definition } } } void G() { main. o A. o B. o C. o // definition } From each. c file the compiler produces an object file (. o). CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Build Process: Function Calls Compilation & Linking 6 The compiler needs to see

The Build Process: Function Calls Compilation & Linking 6 The compiler needs to see a valid declaration for each called function: // main. c // A. c void A(); void B(); void C(); void G(); void A() { . . . // definition void F() { B(); // call A(); // call B(); // call C(); // call G(); // call } void G() { } Solution: the inclusions solve that need // definition } CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Build Process: Function Calls Compilation & Linking 7 Each function call must be

The Build Process: Function Calls Compilation & Linking 7 Each function call must be bound to the definition of the called function: // main. c // A. c // B. c // C. c void A(); void B(); void C(); void B(); void B() { void C(); void G(); // definition void A() { . . . // definition void F() { B(); // call A(); // call B(); // call C(); // call G(); // call } void G() { // definition } } Problem: for some calls, we must bind to code that's actually in a different object file: } main. o CS@VT A. o Computer Organization I B. o C. o © 2005 -2019 WD Mc. Quain

The Build Process: External References Compilation & Linking 8 How do we bind a

The Build Process: External References Compilation & Linking 8 How do we bind a call in one file to a function definition in another? // main. c // A. c void A(); void B(); void C(); void G(); void A() { . . . // definition void F() { B(); // call A(); // call B(); // call C(); // call G(); // call } void G() { // definition } } main. o A. o compiler leaves a "tag" for each call from main. c to an "external" function: compiler leaves a "tag" for each call from B. c to an "external" function: A() B() CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Build Process: Linking Compilation & Linking 9 It's the job of the linker

The Build Process: Linking Compilation & Linking 9 It's the job of the linker to combine the separate object files into an executable: main. o A. o B. o C. o executable The linker also has to resolve any external references that were tagged by the compiler. CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 10 Controlling Access Often, a. c file includes some functions (and

Compilation & Linking 10 Controlling Access Often, a. c file includes some functions (and other things) that are needed only in that file: // B. c #include "B. h" Here, B() calls Helper(), but no other functions outside of the file B. c do so… static void Helper(); int 32_t B(int 32_t x) { // do stuff So, we put the declaration of Helper() inside B. c, before any calls to it… and make it static… Helper(); … and we do NOT declare Helper() in B. h: } static void Helper() { // B. h . . . int 32_t B(int 32_t x); } CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

The Multiple Inclusion Problem Compilation & Linking 11 It is possible to create some

The Multiple Inclusion Problem Compilation & Linking 11 It is possible to create some unfortunate situations: // main. c #include "A. h" #include "B. h" // A. h #include "B. h" Here, the preprocessor will copy the text of B. h into main. c twice, once due to the inclusion in A. h and once due to the explicit inclusion in main. c. This scenario is difficult to avoid in large projects involving many individuals or teams. However, there is a simple fix using preprocessor directives: // B. h void foo(); #ifndef B_H #define B_H void foo(); . . . #endif CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 12 Example: Fibonacci Here's a short program with a test driver,

Compilation & Linking 12 Example: Fibonacci Here's a short program with a test driver, a Fibonacci function in a second file, and a header file containing the declarations needed for the Fibonacci function: #ifndef RFIBONACCI_H #define RFIBONACCI_H #include <stdint. h> #include <stdio. h> #include <inttypes. h> #include "r. Fibonacci. h" uint 64_t r. Fibonacci(uint 64_t n); int main() { for (int i = 0; i < 50; i++) { #endif printf("Fibo(%d) = %"PRIu 64"n", i, r. Fibonacci(i)); } return 0; } #include "r. Fibonacci. h" uint 64_t r. Fibonacci(uint 64_t n) { if ( n < 2 ) return 1; return r. Fibonacci(n - 1) + r. Fibonacci(n - 2); } CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 13 Compilation We can compile either c file without the other

Compilation & Linking 13 Compilation We can compile either c file without the other (but not produce an executable): Cent. OS> gcc -o driver -std=c 99 -Wall -W Cent. OS> ls -l total 24 -rwxrw-r--. 1 wmcquain comporg 8578 Sep -rw-rw-r--. 1 wmcquain comporg 216 Sep -rw-rw-r--. 1 wmcquain comporg 154 Sep -rw-rw-r--. 1 wmcquain comporg 104 Sep 1029 wmcquain in ~/2505/notes/T 08/v 1> driver. c r. Fibonacci. c 25 25 10: 21 10: 19 10: 20 driver. c r. Fibonacci. h OK: the function call matches this declaration; compiler doesn't need to see function definition. #include <stdio. h> #include <inttypes. h> #include "r. Fibonacci. h" int main() { for (int i = 0; i < 50; i++) { The compiler notes that this call "binds" to this declaration. printf("Fibo(%d) = %"PRIu 64"n", i, r. Fibonacci(i)); } return 0; } CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 14 Compilation -c switch tells gcc to compile and exit Cent.

Compilation & Linking 14 Compilation -c switch tells gcc to compile and exit Cent. OS> gcc -c -std=c 99 -Wall -W driver. c Cent. OS> ls -l total 16 -rw-rw-r--. 1 wmcquain comporg 216 Sep 25 -rw-rw-r--. 1 wmcquain comporg 1616 Sep 25 -rw-rw-r--. 1 wmcquain comporg 154 Sep 25 -rw-rw-r--. 1 wmcquain comporg 104 Sep 25 10: 19 10: 24 10: 20 driver. c driver. o r. Fibonacci. c r. Fibonacci. h If compilation is successful, an object file is created; this is a partial translation of the C source file into machine code. CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 15 Linking Cent. OS> ls -l total 20 -rw-rw-r--. 1 -o

Compilation & Linking 15 Linking Cent. OS> ls -l total 20 -rw-rw-r--. 1 -o switch tells gcc what to call executable wmcquain wmcquain comporg 216 Sep 25 10: 19 comporg 1616 Sep 25 10: 24 comporg 154 Sep 25 10: 20 comporg 104 Sep 25 10: 20 comporg 1424 Sep 25 10: 26 driver. c driver. o r. Fibonacci. c r. Fibonacci. h r. Fibonacci. o Cent. OS> gcc -o fibo -Wall -W driver. o r. Fibonacci. o Cent. OS> ls -l total 32 -rw-rw-r--. 1 -rwxrw-r--. 1 -rw-rw-r--. 1 wmcquain wmcquain comporg 216 Sep 25 10: 19 driver. c comporg 1616 Sep 25 10: 24 driver. o comporg 8578 Sep 25 10: 27 fibo comporg 154 Sep 25 10: 20 r. Fibonacci. c comporg 104 Sep 25 10: 20 r. Fibonacci. h comporg 1424 Sep 25 10: 26 r. Fibonacci. o can invoke gcc with object files to link them and produce executable CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 16 Compilation Errors The compiler will generate error messages if it

Compilation & Linking 16 Compilation Errors The compiler will generate error messages if it cannot resolve the references it encounters: #include <stdio. h> #include <stdint. h> #include <inttypes. h> //#include "r. Fibonacci. h" Omit this include directive and the compiler cannot find a declaration that matches the call to r. Fibonacci(). int main() { for (int i = 0; i < 50; i++) { printf("Fibo(%d) = %"PRIu 64"n", i, r. Fibonacci(i)); . . . Cent. OS> gcc -c -std=c 99 -Wall -W driver. c: In function ‘main’: driver. c: 9: 7: warning: implicit declaration of function ‘r. Fibonacci’ [-Wimplicit-function-declaration] printf("Fibo(%d) = %"PRIu 64"n", i, r. Fibonacci(i)); ^ driver. c: 9: 7: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘int’ [-Wformat=] CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain

Compilation & Linking 17 Linker Errors The linker may also produce error messages: #ifndef

Compilation & Linking 17 Linker Errors The linker may also produce error messages: #ifndef RFIBONACCI_H #define RFIBONACCI_H #include <stdint. h> #include <stdio. h> #include <stdint. h> #include "r. Fibonacci. h" uint 64_t r. Fibonacci(uint 64_t n); int main() { for (int i = 0; i < 50; i++) { #endif OK printf("Fibo(%d) = %lldn", i, r. Fibonacci(i)); } return 0; } #include "r. Fibonacci. h" uint 64_t Fibonacci(uint 64_t n) { if ( n < 2 ) return 1; return r. Fibonacci(n - 1) + r. Fibonacci(n - 2); } CS@VT Computer Organization I Now, linker cannot find a definition (implementation) that matches the function declaration the compiler matched the call to… that's an error. © 2005 -2019 WD Mc. Quain

Compilation & Linking 18 Linker Errors Unfortunately, linker error messages are less direct than

Compilation & Linking 18 Linker Errors Unfortunately, linker error messages are less direct than compiler error messages: Cent. OS> gcc -o driver -std=c 99 -Wall -W driver. c r. Fibonacci. c /tmp/cc. Hhmn 0 D. o: In function `main': driver. c: (. text+0 x 1 a): undefined reference to `r. Fibonacci' /tmp/cc. Ycs. MDA. o: In function `Fibonacci': r. Fibonacci. c: (. text+0 x 27): undefined reference to `r. Fibonacci' r. Fibonacci. c: (. text+0 x 3 a): undefined reference to `r. Fibonacci' collect 2: error: ld returned 1 exit status The message does not refer to a specific line of source code. But, it does name a specific function and it implies there's a difference between the declaration of that function and the definition (implementation) of that function. CS@VT Computer Organization I © 2005 -2019 WD Mc. Quain