{#fig:compilation width=100%}
# Factorisation
# Génération d'un exécutable (2/N)
:::::::::::::: {.columns}
## Un seul fichier source
::: {.column width="55%"}
## Ancien `Makefile`
```bash
gcc proc.c -o prog
```
1.**Précompilation: **`gcc` appelle `cpp`, le préprocesseur qui effectue de la substitution de texte (`#define`, `#include`, macros, ...) et génère le code `C` à compiler, portant l'extension `.i` (`prog.i`).
2.**Compilation assembleur: **`gcc` compile le code C en code assembleur, portant l'extension `.s` (`prog.s`).
3.**Compilation code objet: **`gcc` appelle `as`, l'assembleur, qui compile le code assembleur en code machine (code objet) portant l'extension `.o` (`prog.o`).
4.**Édition des liens: **`gcc` appelle `ld`, l'éditeur de liens, qui lie le code objet avec les librairies et d'autres codes objet pour produire l'exécutable final (`prog`).
Les différents codes intermédiaires sont effacés.
# Génération d'un exécutable (3/N)
## Plusieurs fichiers sources
hello: hello.o main.o
gcc hello.o main.o -o hello
{#fig:compilation_plusieurs width=100%}
hello.o: hello.c hello.h
gcc -Wall-Wextra-c hello.c
# Génération d'un exécutable (4/N)
main.o: main.c
gcc -Wall-Wextra-c main.c
::: Main
clean:
rm-f*.o hello
## `main.c`
```C
#include <stdio.h>
#include "sum.h"
int main() {
int tab[] = {1, 2, 3, 4};
printf("sum: %d\n", sum(tab, 4));
return 0;
}
rebuild: clean hello
```
:::
:::::::::::::: {.columns}
::: {.column width="45%"}
## `sum.h`
## Nouveau `Makefile`
```C
#ifndef _SUM_H_
#define _SUM_H_
```bash
CC=gcc -Wall-Wextra
int sum(int tab[], int n);
hello: hello.o main.o
$(CC)$^-o$@
#endif
```
:::
::: {.column width="55%"}
hello.o: hello.c hello.h
$(CC)-c$<
## `sum.c`
main.o: main.c
$(CC)-c$<
```C
#include "sum.h"
int sum(int tab[], int n) {
int s = 0;
for (int i = 0; i < n; i++) {
s += tab[i];
}
return s;
}
clean:
rm-f*.o hello
rebuild: clean hello
```
:::
:::
::::::::::::::
# Variables
# Génération d'un exécutable (4/N)
La compilation séparée se fait en plusieurs étapes.
## Compilation séparée
1. Générer séparément les fichiers `.o` avec l'option `-c`.
2. Éditer les liens avec l'option `-o` pour générer l'exécutable.
## Exemple
- Création des fichiers objets, `main.o` et `sum.o`
## Variables utilisateur
- Déclaration
```bash
$ gcc -Wall -Wextra -std=c11 -c main.c
$ gcc -Wall -Wextra -std=c11 -c sum.c
id= valeur
id= valeur1 valeur2 valeur3
```
-Édition des liens
-Utilisation
```bash
$ gcc main.o sum.o -o prog
```
# Préprocesseur (1/N)
## Généralités
- Première étape de la chaîne de compilation.
- Géré automatiquement par `gcc` ou `clang`.
- Lit et interprète certaines directives:
1. Les commentaires (`//`{.C} et `/* ... */`{.C}).
2. Les commandes commençant par `#`{.C}.
- Le préprocesseur ne compile rien, mais subtitue uniquement du texte.
## La directive `define`{.C}
- Permet de définir un symbole:
```C
#define PI 3.14159
#define _SUM_H_
```
- Permet de définir une macro.
```C
#define NOM_MACRO(arg1, arg2, ...) [code]
```
# Préprocesseur (2/N)
## La directive `include`{.C}
- Permet d'inclure un fichier.
- Le contenu du fichier est ajouté à l'endroit du `#include`{.C}.
- Inclusion de fichiers "globaux" ou "locaux"
```C
#include <file.h> // LD_LIBRARY_PATH
#include "other_file.h" // local path
$(id)
```
-Les inclusions multiples peuvent poser problème: définitions multiples. Les headers commencent par: