01 Introduction To GCC
01 Introduction To GCC
Introduction to gcc
Abhijit Das
Arobinda Gupta
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
What you do not know about gcc
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The four-stage compilation process
Preprocessing This involves the processing of the # directives. Examples:
• The #include’d files are inserted in your code.
• The #define’d macros are literally substituted throughout your code.
Compiling The input to this process is the preprocessed C file, and the output is an
assembly-language code targeted to the architecture of your machine.
Assembling The assembly-language code generated by compiling is converted to a
machine code called the object file. The external functions (like printf and
sqrt) are still undefined.
Linking The object file(s) is/are eventually converted to an executable file in this
process. At this point, the external functions from C runtime library and
other libraries are included in the executable file.
Loading Some functions available in shared (or dynamic) libraries are loaded during
runtime from shared object files.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The compilation process in a nutshell
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
An example of the four-stage compilation process
#define TEN 10
#define TWENTY 20
int main ( )
{
int a, b, c;
a = TEN;
b = a + TWENTY;
c = a * b;
printf("c = %d\n", c);
exit(0);
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Preprocessing
a = 10;
b = a + 20;
c = a * b;
printf("c = %d\n", c);
exit(0);
}
$
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Compiling
This needs invoking gcc with the –S flag. A file with extension .s is generated.
$ gcc -S demo.i
$ cat demo.s
.file "demo.c"
.text
.section .rodata
.LC0:
.string "c = %d\n"
.text
.globl main
.type main, @function
main:
.LFB6:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16 movl %eax, -4(%rbp)
.cfi_offset 6, -16 movl -4(%rbp), %eax
movq %rsp, %rbp movl %eax, %esi
.cfi_def_cfa_register 6 leaq .LC0(%rip), %rdi
subq $16, %rsp movl $0, %eax
movl $10, -12(%rbp) call printf@PLT
movl -12(%rbp), %eax movl $0, %edi
addl $20, %eax call exit@PLT
movl %eax, -8(%rbp) .cfi_endproc
movl -12(%rbp), %eax ...
imull -8(%rbp), %eax $
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Assembling
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Linking
• This is done by ld.
• This requires many libraries and is complicated.
• gcc does it transparently for you.
$ gcc demo.o
$ ./a.out
c = 300
$ nm a.out
...
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Runtime loading
• printf and exit are loaded from shared object(s) during runtime.
$ ldd a.out
linux-vdso.so.1 (0x00007ffe80ff2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f98b5e19000)
/lib64/ld-linux-x86-64.so.2 (0x00007f98b602d000)
$
• If you want these functions to be in your executable, compile with the –static flag.
• This creates a huge a.out.
• You can see printf and exit defined in the executable.
$ gcc -static demo.o
$ ldd a.out
not a dynamic executable
$ nm a.out | grep printf
...
0000000000410bb0 T printf
...
$
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Break your code across multiple files
• Modular programming is a good practice, and is needed in any large coding project.
• Large source files take huge time for recompilation.
• If the code is broken down in pieces, then only the pieces that are changed need
recompilation.
• Large software development is a two-stage process.
• Generate object files from individual modules.
• Merge the object files into a single executable file.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Staque: A multi-file stack-queue application
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The header file defs.h
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The header file stack.h
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The header file queue.h
typedef struct {
nodep front; // Pointer to the beginning of the linked list
nodep back; // Pointer to the end of the linked list
} queue;
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The file stack.c
#include <stdio.h>
#include <stdlib.h>
#include "defs.h"
#include "stack.h"
stack initstack ( )
{
stack S;
S = (stack)malloc(sizeof(node));
S -> data = 0; S -> next = NULL;
return S;
}
···
stack destroystack ( stack S )
{
node *p;
while (S) {
p = S; S = S -> next; free(p);
}
return NULL;
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The file queue.c
#include <stdio.h>
#include <stdlib.h>
#include "defs.h"
#include "queue.h"
queue initqueue ( )
{
queue Q;
node *p;
p = (node *)malloc(sizeof(node));
p -> data = 0;
p -> next = NULL;
Q.front = Q.back = p;
return Q;
}
···
queue destroyqueue ( queue Q )
{
node *p;
while (Q.front) {
p = Q.front;
Q.front = (Q.front) -> next;
free(p);
}
Q.front = Q.back = NULL;
return Q;
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The application staquecheck.c
#include <stdio.h>
#include <stdlib.h>
#include "defs.h"
#include "stack.h"
#include "queue.h"
#define ITER_CNT 10
int main ( )
{
stack S;
queue Q;
int i;
S = initstack();
for (i=0; i<ITER_CNT; ++i) { S = push(S, rand() % 100); printstack(S); }
S = destroystack(S);
Q = initqueue();
for (i=0; i<ITER_CNT; ++i) { Q = enqueue(Q, rand() % 100); printqueue(Q); }
Q = destroyqueue(Q);
exit(0);
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Compile in one shot
$ gcc -Wall staquecheck.c stack.c queue.c
$ ls -l
total 48
-rwxr-xr-x 1 abhij abhij 17640 Dec 23 20:40 a.out
-rw-r--r-- 1 abhij abhij 152 Dec 23 19:43 defs.h
-rw-r--r-- 1 abhij abhij 1262 Dec 23 19:45 queue.c
-rw-r--r-- 1 abhij abhij 360 Dec 23 19:43 queue.h
-rw-r--r-- 1 abhij abhij 1098 Dec 23 19:45 stack.c
-rw-r--r-- 1 abhij abhij 315 Dec 23 19:43 stack.h
-rw-r--r-- 1 abhij abhij 983 Dec 23 20:34 staquecheck.c
$ ./a.out
...
$
• Never forget an executable name after –o. Writing the C source file name after –o will
replace the file.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Generating individual object files
• Compile using the -c option.
• Does not require a main function.
• This does not generate an executable file (even if main is there).
$ gcc -Wall -c stack.c
$ gcc -Wall -c queue.c
$ gcc -Wall -o myapp staquecheck.c stack.o queue.o
$ ls -l
-rw-r--r-- 1 abhij abhij 152 Dec 23 19:43 defs.h
-rwxr-xr-x 1 abhij abhij 17640 Dec 23 21:01 myapp
-rw-r--r-- 1 abhij abhij 1262 Dec 23 19:45 queue.c
-rw-r--r-- 1 abhij abhij 360 Dec 23 19:43 queue.h
-rw-r--r-- 1 abhij abhij 3424 Dec 23 21:01 queue.o
-rw-r--r-- 1 abhij abhij 1098 Dec 23 19:45 stack.c
-rw-r--r-- 1 abhij abhij 315 Dec 23 19:43 stack.h
-rw-r--r-- 1 abhij abhij 3248 Dec 23 21:01 stack.o
-rw-r--r-- 1 abhij abhij 983 Dec 23 20:34 staquecheck.c
$ ./myapp
...
$
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Difference between #include <. . .> and #include ". . ."
• These compilations add the current directory to the list of include directories.
• You can now use #include <defs.h>, #include <stack.h>, and
#include <queue.h> in the source codes.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The environment variable C INCLUDE PATH
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Introduction to libraries
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Types of libraries
Static libraries
• Prefix: lib
• Extension: .a
• The static math library has the name libm.a
• Functions from static libraries are inserted in the executable during linking
• We have the files defs.h, stack.h, queue.h, stack.c, and queue.c as before.
• We want to build the static library libstaque.a. This will contain all the stack and
queue functions as listed earlier.
• The library is not meant to contain any main function.
• Application programs like staquecheck.c will contain the main functions as needed.
• Compile individual source files with the –c option to generate the object files.
• Combine the object files into an archive libstaque.a using the command ar.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Generate libstaque.a
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
What is there in libstaque.a
$ nm libstaque.a
queue.o:
stack.o: 0000000000000144 T dequeue
00000000000001c9 T destroystack 0000000000000242 T destroyqueue
0000000000000036 T emptystack 000000000000004a T emptyqueue
U free 00000000000000dd T enqueue
U fwrite U free
U _GLOBAL_OFFSET_TABLE_ 0000000000000076 T front
0000000000000000 T initstack U fwrite
U malloc U _GLOBAL_OFFSET_TABLE_
00000000000000f4 T pop 0000000000000000 T initqueue
U printf U malloc
000000000000016a T printstack U printf
00000000000000a8 T push 00000000000001d6 T printqueue
U putchar U putchar
U stderr U stderr
0000000000000055 T top $
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
How to use the library
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
How to link the library
• Like –lm, you should compile with –lstaque.
$ gcc -Wall staquecheck.c -lstaque
/usr/bin/ld: cannot find -lstaque
collect2: error: ld returned 1 exit status
$
• The linker ld does not look in the current directory for searching libraries.
• The –L option advises the linker to add directories to the library path.
$ gcc -Wall -L. staquecheck.c -lstaque
$ ls -l
-rwxr-xr-x 1 abhij abhij 17536 Dec 24 18:52 a.out
-rw-r--r-- 1 abhij abhij 152 Dec 23 19:43 defs.h
-rw-r--r-- 1 abhij abhij 7046 Dec 24 18:25 libstaque.a
-rw-r--r-- 1 abhij abhij 1262 Dec 23 19:45 queue.c
-rw-r--r-- 1 abhij abhij 360 Dec 23 19:43 queue.h
-rw-r--r-- 1 abhij abhij 3424 Dec 24 18:23 queue.o
-rw-r--r-- 1 abhij abhij 1098 Dec 23 19:45 stack.c
-rw-r--r-- 1 abhij abhij 315 Dec 23 19:43 stack.h
-rw-r--r-- 1 abhij abhij 3248 Dec 24 18:23 stack.o
-rw-r--r-- 1 abhij abhij 473 Dec 24 18:52 staquecheck.c
-rw-r--r-- 1 abhij abhij 144 Dec 23 19:43 staque.h
$
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
How to avoid –L?
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
What about the header files?
• A user with superuser privileges can copy the header files to one of these directories.
• Using subdirectories is a good option.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Installing the libstaque headers
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The keyword extern
• The functions declared in the header files are not implemented by your code.
• These functions are implemented in external library/libraries.
• The key word extern directs the compiler to wait for these implementations.
The header file queue.h
extern queue initqueue ( ) ;
extern int emptyqueue ( queue ) ;
extern int front ( queue ) ;
extern queue enqueue ( queue , int ) ;
extern queue dequeue ( queue ) ;
extern void printqueue ( queue ) ;
extern queue destroyqueue ( queue ) ;
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Building the shared staque library
• We again need only the files defs.h, stack.h, queue.h, stack.c, and queue.c.
• We plan to generate libstaque.so.
• Compile individual source files with the –c option to generate the object files.
• Use the option –fPIC to generate position-independent codes.
• Combine the objects into the shared library using gcc –shared.
$ gcc -Wall -fPIC -c stack.c
$ gcc -Wall -fPIC -c queue.c
$ gcc -shared -o libstaque.so stack.o queue.o
$ ls -l
...
-rwxr-xr-x 1 abhij abhij 16928 Dec 24 20:51 libstaque.so
...
$
• You can nm libstaque.so to find all the defined and undefined symbols.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
How to link libstaque.so?
• The linker is not supposed to link the stack and queue functions to applications.
• These functions will be read from libstaque.so during runtime.
• Again you need the –L option to add the path of the library.
• If you (in the superuser mode) copy libstaque.so to a system directory, then you do
not need –L.
$ sudo cp libstaque.so /usr/local/lib/
$ gcc -Wall staquecheck.c -lstaque
$ ls -l
-rwxr-xr-x 1 abhij abhij 17064 Dec 24 21:05 a.out
...
$
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Libstaque functions are undefined in your a.out
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Set the runtime library path
–W –Wall includes the following (among others). Some of these have many
subcategories.
–Wcomment Warn about nested comments.
–Wformat Warn about type mismatches in scanf and printf.
–Wunused Warn about unused variables.
–Wimplicit Warn about functions used before declaration.
–Wreturn-type Warn about returning void for functions with non-void return
values.
–Wall does not include the following (among otheres).
–Wconversion Warn about implicit type conversions.
–Wshadow Warn about shadowed variables.
–Werror Convert warnings to errors.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Some useful gcc options (contd.)
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The C preprocessor
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Macros used as flags
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Example of macros used as flags
exit(0);
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Redefine MYFLAG from command line
$ gcc -Wall -DMYFLAG macros.c
$ ./a.out
MYFLAG is defined
MYFLAG is undefined here
$
$ cpp -DMYFLAG macros.c
...
int main ()
{
printf("MYFLAG is defined\n");
exit(0);
}
$
#endif
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Use of macros as values for substitution
int main ()
{
if (EXPR1 == EXPR2) printf("EXPR1 is equal to EXPR2\n");
else printf("EXPR1 is not equal to EXPR2\n");
if (EXPR1 == EXPR3) printf("EXPR1 is equal to EXPR3\n");
else printf("EXPR1 is not equal to EXPR3\n");
if (EXPR1 == EXPR4 * EXPR4) printf("EXPR1 is equal to EXPR4 * EXPR4\n");
else printf("EXPR1 is not equal to EXPR4 * EXPR4\n");
exit(0);
}
• This program cannot compile as such, because EXPR3 and EXPR4 are not defined.
• We define these macros by the –D option.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Examples of macros as values for substitution
$ gcc -Wall -DEXPR3="50 + 50" -DEXPR4="5 + 5" macroval.c
$ ./a.out
EXPR1 is equal to EXPR2
EXPR1 is equal to EXPR3
EXPR1 is not equal to EXPR4 * EXPR4
$
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Quoting strings with –D
int main ()
{
printf("Welcome %s\n", MYNAME);
exit(0);
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Appendix
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Talking with the shell
• You run your compiled executable (like a.out) from the shell.
• You may add one or more command-line arguments.
• These arguments should somehow go to your C program.
• When the program finishes execution, it should return something to the shell.
• The return value conventionally indicates successful/unsuccessful termination.
The fully decorated main() function
int main ( int argc, char *argv[] )
{
···
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
The shell talks to your program
• argc is the count of arguments including the program name (like ./a.out).
• argv is a null-terminated array of strings storing the command-line arguments.
• Each argument is a string.
• Use the library functions atoi, atol, atof, . . . (defined in stdlib.h) to convert arguments
to int, long int, double, . . . .
• For example, if you run ./a.out 2022 -name "Sad Tijihba" 6.32, then we have
• argc = 5,
• argv[0] = "./a.out",
• argv[1] = "2022",
• argv[2] = "-name",
• argv[3] = "Sad Tijihba",
• argv[4] = "6.32", and
• argv[5] = NULL.
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
Your program talks to the shell
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta
An example chat
if (argc != 6) {
fprintf(stderr, "*** Incorrect number of arguments\n");
exit(1);
}
printf("The equation of the circle: x^2 + y^2 %c %dx %c %dy %c %d = 0\n", s1, t1, s2, t2, s3, t3);
if ((x - c) * (x - c) + (y - d) * (y - d) <= r * r) printf("(%d,%d) is inside the circle\n", x, y);
else printf("(%d,%d) is outside the circle\n", x, y);
exit(0);
}
Systems Programming Laboratory, Spring 2022 Abhijit Das and Arobinda Gupta