Skip to content
Snippets Groups Projects
Verified Commit fb623736 authored by orestis.malaspin's avatar orestis.malaspin
Browse files

ajout makefile + compilation separée

parent 3ca29947
No related branches found
No related tags found
No related merge requests found
---
title: "Compilation séparée et Makefile"
date: "2021-11-02"
patat:
wrap: true
margins:
left: 10
right: 10
---
# Prototypes de fonctions (1/3)
```C
// Prototype, pas d'implémentation, juste la doc
int sum(int size, int tab[size]);
```
## Principes généraux de programmation
- Beaucoup de fonctionnalités dans un code $\Rightarrow$ Modularisation.
- Modularisation du code $\Rightarrow$ écriture de fonctions.
- Beaucoup de fonctions $\Rightarrow$ regrouper les fonctions dans des fichiers séparés.
## Mais pourquoi?
- Lisibilité.
- Raisonnement sur le code.
- Débogage.
## Exemple
- Libraire `stdio.h`: `printf()`{.C}, `scanf()`{.C}, ...
# Prototypes de fonctions (2/3)
- Prototypes de fonctions nécessaires quand:
1. Utilisation de fonctions dans des fichiers séparés.
2. Utilisation de librairies.
- Un prototype indique au compilateur la signature d'une fonction.
- On met les prototypes des fonctions **publiques** dans des fichiers *headers*, extension `.h`.
- Les *implémentations* des fonctions vont dans des fichier `.c`.
# Prototypes de fonctions (3/3)
## Fichier header
- Porte l'extension `.h`
- Contient:
- définitions des types
- prototypes de fonctions
- macros
- directives préprocesseur (cf. plus loin)
- Utilisé pour décrire **l'interface** d'une librairie ou d'un module.
- Un fichier `C` (extension `.c`) utilise un header en *l'important* avec la directive `#include`{.C}:
```C
#include <stdio.h> // libraire dans LD_LIBRARY_PATH
#include "chemin/du/prototypes.h" // chemin explicite
```
# Génération d'un exécutable (1/5)
## Un seul fichier source
![Étapes de génération.](figs/compilation.svg){width=100%}
# Génération d'un exécutable (2/5)
```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/5)
## Plusieurs fichiers sources
![Étapes de génération, plusieurs fichiers.](figs/compilation_plusieurs.svg){width=100%}
# Génération d'un exécutable (4/5)
\footnotesize
::: Main
## `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;
}
```
:::
:::::::::::::: {.columns}
::: {.column width="45%"}
## `sum.h`
```C
#ifndef _SUM_H_
#define _SUM_H_
int sum(int tab[], int n);
#endif
```
:::
::: {.column width="55%"}
## `sum.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;
}
```
:::
::::::::::::::
# Génération d'un exécutable (5/5)
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`
```bash
$ gcc -Wall -Wextra -std=c11 -c main.c
$ gcc -Wall -Wextra -std=c11 -c sum.c
```
- Édition des liens
```bash
$ gcc main.o sum.o -o prog
```
# Préprocesseur (1/2)
## 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/2)
## 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
```
- Inclusions multiples peuvent poser problème: définitions multiples. Les headers commencent par:
```C
#ifndef _VAR_
#define _VAR_
/* commentaires */
#endif
```
# Introduction à `make`
## A quoi ça sert?
- Automatiser le processus de conversion d'un type de fichier à un autre, en *gérant les dépendances*.
- Effectue la conversion des fichiers qui ont changé uniquement.
- Utilisé pour la compilation:
- Création du code objet à partir des sources.
- Création de l'exécutable à partir du code objet.
- Tout "gros" projet utilise `make` (pas uniquement en `C`).
# Utilisation de `make`
Le programme `make` exécutera la série d'instruction se trouvant dans un `Makefile` (ou `makefile` ou `GNUmakefile`).
## Le `Makefile`
- Contient une liste de *règles* et *dépendances*.
- Règles et dépendances construisent des *cibles*.
- Ici utilisé pour compiler une série de fichiers sources
```
$ gcc -c example.c # + plein d'options..
$ gcc -o example exemple.o # + plein d'options
```
:::::::::::::: {.columns}
::: {.column width="55%"}
## `Makefile`
```bash
example: example.o
gcc -o example example.o
exmaple.o: exmaple.c example.h
gcc -c example.c
```
:::
::: {.column width="45%"}
## Terminal
```bash
$ make
gcc -c example.c
gcc -o example example.o
```
:::
::::::::::::::
# Syntaxe d'un `Makefile` (1/4)
![Un exemple simple de `Makefile`.](figs/ex_makefile.svg){width=100%}
# Syntaxe d'un `Makefile` (2/4)
![La cible.](figs/ex_makefile_cible.svg){width=100%}
# Syntaxe d'un `Makefile` (3/4)
![Les dépendances.](figs/ex_makefile_dep.svg){width=100%}
# Syntaxe d'un `Makefile` (4/4)
![La règle.](figs/ex_makefile_regle.svg){width=100%}
# Principe de fonctionnement
1. `make` cherche le fichier `Makefile`, `makefile` ou `GNUmakefile` dans le répertoire courant.
2. Par défaut exécute la première cible, ou celle donnée en argument.
3. Décide si une cible doit être régénérée en comparant la date de modification (on recompile que ce qui a été modifié).
4. Regarde si les dépendances doivent être régénérées:
- Oui: prend la première dépendance comme cible et recommence à 3.
- Non: exécute la règle.
`make` a un comportement **récursif**.
# Exemple avancé
:::::::::::::: {.columns}
::: {.column width="55%"}
## `Makefile`
```bash
hello: hello.o main.o
gcc hello.o main.o -o hello
hello.o: hello.c hello.h
gcc -Wall -Wextra -c hello.c
main.o: main.c
gcc -Wall -Wextra -c main.c
clean:
rm -f *.o hello
rebuild: clean hello
```
:::
::: {.column width="45%"}
## Un graph complexe
![`Makefile` complexe.](figs/complex_makefile.svg){width=100%}
:::
::::::::::::::
# Factorisation
:::::::::::::: {.columns}
::: {.column width="55%"}
## Ancien `Makefile`
```bash
hello: hello.o main.o
gcc hello.o main.o -o hello
hello.o: hello.c hello.h
gcc -Wall -Wextra -c hello.c
main.o: main.c
gcc -Wall -Wextra -c main.c
clean:
rm -f *.o hello
rebuild: clean hello
```
:::
::: {.column width="45%"}
## Nouveau `Makefile`
```bash
CC=gcc -Wall -Wextra
hello: hello.o main.o
$(CC) $^ -o $@
hello.o: hello.c hello.h
$(CC) -c $<
main.o: main.c
$(CC) -c $<
clean:
rm -f *.o hello
rebuild: clean hello
```
:::
::::::::::::::
# Variables
## Variables utilisateur
- Déclaration
```bash
id = valeur
id = valeur1 valeur2 valeur3
```
- Utilisation
```bash
$(id)
```
- Déclaration à la ligne de commande
```bash
make CFLAGS="-O3 -Wall"
```
## Variables internes
- `$@` : la cible
- `$^` : la liste des dépendances
- `$<` : la première dépendance
- `$*` : le nom de la cible sans extension
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment