Ajout de la gestion des variables dans le Bakefile et mise à jour des tests associés
This commit is contained in:
parent
0941b5e09e
commit
c20a508069
bakefile.jar
src/fr/monlouyan/bakefile
tests
bakefile.jar
test-01-depuis-rien
test-01-from-nothing
test-02-already-exist
test-02-existe-deja
test-03-circulaire
test-03-circular
test-04-edited
test-05-variables
test-06-variables-on-cascade
BIN
bakefile.jar
BIN
bakefile.jar
Binary file not shown.
@ -25,10 +25,21 @@ public class BakefileParser {
|
|||||||
*/
|
*/
|
||||||
private static final Pattern COMMAND_PATTERN = Pattern.compile("^\\s+(.+)$");
|
private static final Pattern COMMAND_PATTERN = Pattern.compile("^\\s+(.+)$");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex pour détecter les définitions de variables.
|
||||||
|
* Format : "FLAGS = -ansi -pedantic"
|
||||||
|
*/
|
||||||
|
private static final Pattern VARIABLE_PATTERN = Pattern.compile("^(\\w+)\\s*=\\s*(.*)$");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Première cible trouvée dans le fichier Bakefile.
|
* Première cible trouvée dans le fichier Bakefile.
|
||||||
*/
|
*/
|
||||||
private static String firstTarget;
|
private static String firstTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stocke les variables définies dans le Bakefile.
|
||||||
|
*/
|
||||||
|
private Map<String, String> variables = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public BakefileParser(String filename) {
|
public BakefileParser(String filename) {
|
||||||
@ -39,53 +50,80 @@ public class BakefileParser {
|
|||||||
public List<Rule> parse() {
|
public List<Rule> parse() {
|
||||||
List<Rule> rules = new ArrayList<>();
|
List<Rule> rules = new ArrayList<>();
|
||||||
Set<String> phonyTargets = new HashSet<>();
|
Set<String> phonyTargets = new HashSet<>();
|
||||||
|
|
||||||
if (!Files.exists(Paths.get(filename))) {
|
if (!Files.exists(Paths.get(filename))) {
|
||||||
System.out.println("*** No targets specified and no makefile found. Stop.");
|
System.out.println("*** No targets specified and no makefile found. Stop.");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<String> lines = Files.readAllLines(Paths.get(filename));
|
List<String> lines = Files.readAllLines(Paths.get(filename));
|
||||||
String currentTarget = null;
|
String currentTarget = null;
|
||||||
List<String> dependencies = new ArrayList<>();
|
List<String> dependencies = new ArrayList<>();
|
||||||
List<String> commands = new ArrayList<>();
|
List<String> commands = new ArrayList<>();
|
||||||
|
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
|
Matcher varMatcher = VARIABLE_PATTERN.matcher(line);
|
||||||
Matcher targetMatcher = TARGET_PATTERN.matcher(line);
|
Matcher targetMatcher = TARGET_PATTERN.matcher(line);
|
||||||
Matcher commandMatcher = COMMAND_PATTERN.matcher(line);
|
Matcher commandMatcher = COMMAND_PATTERN.matcher(line);
|
||||||
|
|
||||||
if (targetMatcher.matches()) {
|
if (varMatcher.matches()) {
|
||||||
|
// Stocke la variable
|
||||||
|
variables.put(varMatcher.group(1), varMatcher.group(2));
|
||||||
|
} else if (targetMatcher.matches()) {
|
||||||
if (firstTarget == null) {
|
if (firstTarget == null) {
|
||||||
firstTarget = targetMatcher.group(1);
|
firstTarget = targetMatcher.group(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sauvegarde de la règle précédente si elle existe
|
|
||||||
if (currentTarget != null) {
|
if (currentTarget != null) {
|
||||||
rules.add(new Rule(currentTarget, dependencies, commands, phonyTargets.contains(currentTarget)));
|
rules.add(new Rule(currentTarget, dependencies, replaceVariables(commands), phonyTargets.contains(currentTarget)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nouvelle cible détectée
|
|
||||||
currentTarget = targetMatcher.group(1);
|
currentTarget = targetMatcher.group(1);
|
||||||
dependencies = new ArrayList<>(Arrays.asList(targetMatcher.group(2).trim().split("\\s+")));
|
dependencies = new ArrayList<>(Arrays.asList(targetMatcher.group(2).trim().split("\\s+")));
|
||||||
commands = new ArrayList<>();
|
commands = new ArrayList<>();
|
||||||
} else if (commandMatcher.matches()) {
|
} else if (commandMatcher.matches()) {
|
||||||
// Ligne de commande associée à la dernière cible trouvée
|
|
||||||
commands.add(commandMatcher.group(1));
|
commands.add(commandMatcher.group(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajout de la dernière règle après la boucle
|
|
||||||
if (currentTarget != null) {
|
if (currentTarget != null) {
|
||||||
rules.add(new Rule(currentTarget, dependencies, commands, phonyTargets.contains(currentTarget)));
|
rules.add(new Rule(currentTarget, dependencies, replaceVariables(commands), phonyTargets.contains(currentTarget)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remplace les variables dans une liste de commandes.
|
||||||
|
* Ex : "gcc $(FLAGS) -o main main.c" devient "gcc -ansi -pedantic -o main main.c"
|
||||||
|
* @param commands Liste des commandes à modifier
|
||||||
|
* @return Liste avec les variables remplacées
|
||||||
|
*/
|
||||||
|
private List<String> replaceVariables(List<String> commands) {
|
||||||
|
List<String> resolvedCommands = new ArrayList<>();
|
||||||
|
for (String command : commands) {
|
||||||
|
boolean replaced;
|
||||||
|
do {
|
||||||
|
replaced = false;
|
||||||
|
for (Map.Entry<String, String> entry : variables.entrySet()) {
|
||||||
|
String key = "$(" + entry.getKey() + ")";
|
||||||
|
if (command.contains(key)) {
|
||||||
|
command = command.replace(key, entry.getValue());
|
||||||
|
replaced = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (replaced); // Continue tant qu'on remplace des variables
|
||||||
|
resolvedCommands.add(command);
|
||||||
|
}
|
||||||
|
return resolvedCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer la première cible trouvée dans le fichier Bakefile.
|
* Permet de récupérer la première cible trouvée dans le fichier Bakefile.
|
||||||
* @return La première cible trouvée
|
* @return La première cible trouvée
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,2 +1,4 @@
|
|||||||
|
FLAGS = -ansi -pedabtic
|
||||||
|
|
||||||
main: main.c
|
main: main.c
|
||||||
gcc -o main main.c
|
gcc -o main main.c
|
Binary file not shown.
Binary file not shown.
2
tests/test-04-edited/Bakefile
Normal file
2
tests/test-04-edited/Bakefile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
main: main.c
|
||||||
|
gcc -o main main.c
|
13
tests/test-04-edited/README.md
Normal file
13
tests/test-04-edited/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Test 2 : Compilation où le résultat existe déjà
|
||||||
|
|
||||||
|
## Description
|
||||||
|
Ce test vérifie que si l'exécutable `main` est déjà présent et que `main.c`
|
||||||
|
n'a pas été modifié, alors `Bake` ne tente pas de recompiler.
|
||||||
|
|
||||||
|
## Fichiers utilisés
|
||||||
|
- `main.c` : Fichier source inchangé.
|
||||||
|
- `Bakefile` : Contient les règles de compilation.
|
||||||
|
- `main` : Exécutable déjà généré.
|
||||||
|
|
||||||
|
## Résultat attendu
|
||||||
|
Aucun message indiquant la compilation ne doit apparaître.
|
BIN
tests/test-04-edited/main
Executable file
BIN
tests/test-04-edited/main
Executable file
Binary file not shown.
7
tests/test-04-edited/main.c
Normal file
7
tests/test-04-edited/main.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Ceci est un programme de test du Bakefile !\n");
|
||||||
|
printf("test\n");
|
||||||
|
return 0;
|
||||||
|
}
|
4
tests/test-05-variables/Bakefile
Normal file
4
tests/test-05-variables/Bakefile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
FLAGS = -ansi -pedantic
|
||||||
|
|
||||||
|
main: main.c
|
||||||
|
gcc $(FLAGS) -o main main.c
|
1
tests/test-05-variables/README.md
Normal file
1
tests/test-05-variables/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Test 5 : Utilisation de variables
|
6
tests/test-05-variables/main.c
Normal file
6
tests/test-05-variables/main.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Ceci est un programme de test du Bakefile !\n");
|
||||||
|
return 0;
|
||||||
|
}
|
6
tests/test-06-variables-on-cascade/Bakefile
Normal file
6
tests/test-06-variables-on-cascade/Bakefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FLAGS = -ansi -pedantic
|
||||||
|
FLAGSS = $(FLAGS)
|
||||||
|
FLAGSSS = $(FLAGSS)
|
||||||
|
|
||||||
|
main: main.c
|
||||||
|
gcc $(FLAGSSS) -o main main.c
|
1
tests/test-06-variables-on-cascade/README.md
Normal file
1
tests/test-06-variables-on-cascade/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Test 6 : Gestion des variables en cascade
|
6
tests/test-06-variables-on-cascade/main.c
Normal file
6
tests/test-06-variables-on-cascade/main.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Ceci est un programme de test du Bakefile !\n");
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user