From a8ca407247dac93024c549aac7fab333cb265d72 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Fri, 31 Oct 2025 21:34:09 +0100 Subject: [PATCH] JUSTOCASOU --- minimake/Makefile | 2 +- minimake/src/files/files.c | 99 +++++++++++++++++++++++++++++++++++ minimake/src/files/files.h | 14 +++++ minimake/src/main.c | 38 +++----------- minimake/src/minimake.c | 95 ++++++++++++++++++++++++++++++--- minimake/src/minimake.h | 7 +-- minimake/tests/Makefile.test3 | 1 + minimake/tests/Makefile.test4 | 5 ++ 8 files changed, 220 insertions(+), 41 deletions(-) create mode 100644 minimake/src/files/files.c create mode 100644 minimake/src/files/files.h create mode 100644 minimake/tests/Makefile.test3 create mode 100644 minimake/tests/Makefile.test4 diff --git a/minimake/Makefile b/minimake/Makefile index c12a97e..db29234 100644 --- a/minimake/Makefile +++ b/minimake/Makefile @@ -7,7 +7,7 @@ DBG_LDFLAGS= -fsanitize=address SRC_DIR = src -LIB_SRCS = lines/lines.c hash_maps/hash_maps.c lists/lists.c +LIB_SRCS = lines/lines.c hash_maps/hash_maps.c lists/lists.c files/files.c MAIN_SRCS = main.c minimake.c # SRCS = $(patsubst %,$(SRC_DIR)/%, $(MAIN_SRCS)) diff --git a/minimake/src/files/files.c b/minimake/src/files/files.c new file mode 100644 index 0000000..2d46ecb --- /dev/null +++ b/minimake/src/files/files.c @@ -0,0 +1,99 @@ +#include "files.h" + +#include +#include +#include +#include +#include +#include + +// #include "../lines/lines.h" + +char *get_makefile(struct list *files) +{ + struct list *file = files; + int found = 0; + + // Test file presence + while (file != NULL && !found) + { + FILE *test = fopen(file->data, "r"); + if (test != NULL) + { + fclose(test); + found = 1; + } + else + { + file = file->next; + } + } + + char *res = NULL; + if (found) + res = file->data; + + return res; +} + +ssize_t get_file_lastmodiftime(char *filename) +{ + struct stat stat; + if (lstat(filename, &stat) == -1) + return -1; + return stat.st_mtime; +} + +// Calls a shell that will run the given command +// It will first print the command to run unless the it starts with '@' +// Returns the return code o the command or -1 if a syscall fails +int run_command(char *command) +{ + if (command[0] == '@') + command++; + else + { + puts(command); + } + + // Just in case + fflush(stdout); + fflush(stderr); + + // char *executable; + // size_t args_offset = readword(command, strlen(command), &executable); + + int id = fork(); + if (id < 0) + { + perror("fork"); + return -1; + } + + if (id == 0) + { + int res = 0; + wait(&res); + // printf("Got return code: %d\n", res); + return res; + } + else + { + int res = execl("/bin/sh", "(make)", "-c", command, NULL); + return res; + } +} + +// Returns 1 if file exists (and is readable), 0 otherwise +int file_exists(char *filename) +{ + if (filename == NULL) + return 0; + + FILE *test = fopen(filename, "r"); + if (test == NULL) + return 0; + + fclose(test); + return 1; +} diff --git a/minimake/src/files/files.h b/minimake/src/files/files.h new file mode 100644 index 0000000..da7c555 --- /dev/null +++ b/minimake/src/files/files.h @@ -0,0 +1,14 @@ +#ifndef FILES_H +#define FILES_H + +#define _XOPEN_SOURCE 500 + +#include "../lists/lists.h" +#include + +char* get_makefile(struct list *files); +ssize_t get_file_lastmodiftime(char* filename); +int run_command(char *command); +int file_exists(char *filename); + +#endif // FILES_H diff --git a/minimake/src/main.c b/minimake/src/main.c index 9ab0ada..ec0473f 100644 --- a/minimake/src/main.c +++ b/minimake/src/main.c @@ -5,6 +5,7 @@ #include #include +#include "files/files.h" #include "lists/lists.h" #include "minimake.h" @@ -58,10 +59,12 @@ static int handle_args(int argc, char **argv, struct list **minimake_files, else if (strcmp(argv[i], "-f") == 0) { flags |= FLAGS_CUSTOM_FILE; - if (i + 1 == argc || argv[i + 1][0] == '-') + i++; + + if (i == argc || argv[i][0] == '-') errx(INVALID_ARG, "No file specified after '-f'"); - files = list_prepend(files, argv[i + 1]); + files = list_prepend(files, argv[i]); } // Print else if (strcmp(argv[i], "-p") == 0) @@ -92,33 +95,6 @@ static int handle_args(int argc, char **argv, struct list **minimake_files, return flags; } -char *get_makefile(struct list *files) -{ - struct list *file = files; - int found = 0; - - // Test file presence - while (file != NULL && !found) - { - FILE *test = fopen(file->data, "r"); - if (test != NULL) - { - fclose(test); - found = 1; - } - else - { - file = file->next; - } - } - - char *res = NULL; - if (found) - res = file->data; - - return res; -} - int main(int argc, char **argv) { struct list *files; @@ -129,8 +105,8 @@ int main(int argc, char **argv) if (filename == NULL) errx(GENERIC_ERR, "No Makefile found"); - make(filename, flags, argv[0]); + int res = make(filename, rules, argv[0], flags); list_destroy(files); list_destroy(rules); - return 0; + return res; } diff --git a/minimake/src/minimake.c b/minimake/src/minimake.c index 8bfee8e..675702c 100644 --- a/minimake/src/minimake.c +++ b/minimake/src/minimake.c @@ -10,6 +10,7 @@ #include #include +#include "files/files.h" #include "hash_maps/hash_maps.h" #include "lines/lines.h" #include "lists/lists.h" @@ -459,21 +460,103 @@ void make_parse(char *path) // ==== Runtime ==== -// static void make_run(void) -// {} +// Expands and run a specified rule +static int run_rule(struct rule *rule) +{ + struct list *commands = rule->recipe; + struct list *dependencies = rule->dependencies; + + // Expand dependencies variables + // TODO + + // Build dependencies + while (dependencies != NULL) + { + // Check file existence + if (!file_exists(dependencies->data)) + { + // Check rule existence instead + struct rule *dep_rule = hashmap_get(rules, dependencies->data); + if (dep_rule != NULL) + { + int res = run_rule(dep_rule); + if (res != 0) // Exit on error + return res; + } + else + { + drop(GENERIC_ERR, "No rule to make target '%s'", + dependencies->data); + } + } + } + + while (commands != NULL) + { + // Expand command variables + // TODO + + // Run + int res = run_command(commands->data); + if (res != 0) // Exit on error + return res; + + commands = commands->next; + } + + return 0; +} + +// Run the given rules after parsing +int make_run(struct list *given_rules) +{ + if (given_rules == NULL) + { + // No rule specified => run first rule found in the Makefile + if (rules_list == NULL) + drop(GENERIC_ERR, "No targets"); + + struct rule *full_rule = hashmap_get(rules, rules_list->data); + if (full_rule == NULL) + drop(GENERIC_ERR, + "Internal error: Could not retrieve target '%s' in database", + rules_list->data); + + return run_rule(full_rule); + } + else + { + while (given_rules != NULL) + { + struct rule *full_rule = hashmap_get(rules, given_rules->data); + if (full_rule == NULL) + drop(GENERIC_ERR, "No rule to make target '%s'", + given_rules->data); + + int res = run_rule(full_rule); + if (res != 0) + return res; + + given_rules = given_rules->next; + } + return 0; + } +} // ==== MAKE ==== -void make(char *path, int flags, char *argv0) +int make(char *path, struct list *rules, char *exec_name, int flags) { - program_name = argv0; + program_name = exec_name; make_parse(path); if (flags & FLAGS_PRINT) dump_database(); + int status = make_run(rules); free_all(); + return status; } // Prints an error message before exiting gracefully (by freeing all variables) @@ -482,9 +565,9 @@ void drop(int status, char *format, ...) // Print va_list args; va_start(args, format); - fprintf(stderr, "%s: ", program_name); + fprintf(stderr, "%s: *** ", program_name); vfprintf(stderr, format, args); - fprintf(stderr, "\n"); + fprintf(stderr, ". Stop.\n"); va_end(args); free_all(); diff --git a/minimake/src/minimake.h b/minimake/src/minimake.h index 98f4ccb..f6ed073 100644 --- a/minimake/src/minimake.h +++ b/minimake/src/minimake.h @@ -10,8 +10,8 @@ #define FLAGS_PRINT 2 // Default values -#define DEFAULT_MAKEFILE "Makefile" -#define DEFAULT_MAKEFILE_2 "makefile" +#define DEFAULT_MAKEFILE "makefile" +#define DEFAULT_MAKEFILE_2 "Makefile" #define BUFFER_SIZE 1024 #define HASHMAP_SIZE 32 @@ -38,8 +38,9 @@ struct rule struct list *recipe; }; -void make(char *path, int flags, char* program_name); +int make(char *path, struct list* rules, char *argv0, int flags); void make_parse(char *path); +int make_run(struct list *rules); void drop(int status, char *format, ...); void dump_database(void); size_t expand_variable(struct line *line, size_t index, char **value); diff --git a/minimake/tests/Makefile.test3 b/minimake/tests/Makefile.test3 new file mode 100644 index 0000000..7a42836 --- /dev/null +++ b/minimake/tests/Makefile.test3 @@ -0,0 +1 @@ +VAR = 1 diff --git a/minimake/tests/Makefile.test4 b/minimake/tests/Makefile.test4 new file mode 100644 index 0000000..45ee423 --- /dev/null +++ b/minimake/tests/Makefile.test4 @@ -0,0 +1,5 @@ +rule1: + echo Toto + +rule2: + @echo Toto