├── install ├── makemyfile └── install_makemyfile.sh ├── screenshots └── screen.gif ├── .gitignore ├── src ├── main.c ├── make_my_file.c ├── utils.c ├── check_update.c ├── project_directory_setup │ ├── create_directory_project.c │ └── check_directory.c ├── generate_makefile │ ├── auto_detec_files.c │ ├── configuration.c │ └── write_makefile.c └── print.c ├── LICENSE ├── README.md ├── include ├── make_my_file.h └── write_in_file.h └── Makefile /install/makemyfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathysCogne/Make_My_File-42/HEAD/install/makemyfile -------------------------------------------------------------------------------- /screenshots/screen.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathysCogne/Make_My_File-42/HEAD/screenshots/screen.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | *.a 3 | 4 | obj/ 5 | obj/*.o 6 | *.o 7 | *.d 8 | 9 | .vscode/settings.json 10 | .vscode -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | 12 | int main(void) 13 | { 14 | t_make_config config; 15 | 16 | check_for_updates(); 17 | if (check_directory()) 18 | { 19 | create_directory_project(&config); 20 | return (0); 21 | } 22 | if (make_my_file(&config)) 23 | { 24 | printf(RED"Error.\n"); 25 | return (1); 26 | } 27 | return (0); 28 | } -------------------------------------------------------------------------------- /src/make_my_file.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | 12 | short make_my_file(t_make_config *config) 13 | { 14 | 15 | init_config(config); // GEN CONFIG 16 | auto_detec_sources(config); // DETECTION SOURCES 17 | generate_makefile(config); // GEN MAKEFILE 18 | print_config(config); // END SCREEN 19 | 20 | free_malloc(config); 21 | return (0); 22 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Mathys Cogné-Foucault 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Make My File 2 |   3 | 4 | ### ⚠️ This project is in beta testing. 5 | ### Please report any bugs you find on Discord (@mrmilkshakes) or GitHub! 6 |   7 | 8 | **Make My File** is a fully automated Makefile generator for C projects, optimized for 42 school. 9 | 10 | Run the executable in your project directory and follow the prompts in the console GUI. 11 | 12 |   13 | 14 | ## Features 15 | 16 | - Auto-detect source files, headers and bonus files, including in subdirectories. 17 | - Detect C project structure and Create project structure automatically if not present, including: 18 | - main.c, name_app.c, and name_app.h 19 | - Directories: include/ and src/ 20 | - A corresponding Makefile 21 | - A .gitignore file for c project 22 | 23 | - Link against the `libft` library (42). 24 | - Include and auto-download `MiniLibX` library (42). 25 | - Create object directories and dependency files. 26 | 27 |   28 | 29 | ## Disclaimer 30 | 31 | While **Make My File** automates Makefile generation, knowing how to create one manually is essential, especially during 42 school pool sessions. 32 | 33 | 34 |   35 | 36 | ## Installation 37 | 38 | 1. Run the installer script and follow instructions: (Note: Script work on Linux and macOS.) 39 | ```bash 40 | bash -c "$(curl -L https://github.com/MathysCogne/Make_My_File-42/releases/download/1.2.6/install_makemyfile.sh)" 41 | ``` 42 | 43 |   44 | 45 | 2. To create a Makefile, navigate to the root of your project and run: 46 | ```bash 47 | makemyfile 48 | ``` 49 | 50 | Tip: If you don’t have a project structure yet (meaning there are no .c files in the directory), the app will offer to create one for you. It's a great way to save time if you want to get started quickly! 51 | 52 |   53 | 54 | 3. Follow the on-screen instructions. 55 | 56 | ![Screen](screenshots/screen.gif) 57 | 58 |   59 | 60 | ## Contributing 61 | 62 | Contributions are welcome! Feel free to submit a pull request or open an issue for suggestions. 63 | 64 |   65 | -------------------------------------------------------------------------------- /install/install_makemyfile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REPO_OWNER="MathysCogne" 4 | REPO_NAME="Make_My_File-42" 5 | EXECUTABLE_NAME="makemyfile" 6 | INSTALL_DIR="$HOME/.local/bin" 7 | 8 | BOLD="\033[1m" 9 | ITALIC="\033[3m" 10 | GREEN="\033[32m" 11 | CYAN="\033[36m" 12 | RED="\033[31m" 13 | C_RESET="\033[0m" 14 | 15 | # Check if the installation directory exists 16 | if [ ! -d "$INSTALL_DIR" ]; then 17 | mkdir -p "$INSTALL_DIR" 18 | echo -e "${GREEN}💾 Directory $INSTALL_DIR created for installation.${C_RESET}" 19 | fi 20 | 21 | # Download the latest version from GitHub 22 | LATEST_RELEASE=$(curl -s -H "Accept: application/vnd.github.v3+json" \ 23 | https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/releases/latest | \ 24 | grep -Po '"tag_name": "\K.*?(?=")') 25 | 26 | if [ -z "$LATEST_RELEASE" ]; then 27 | echo -e "${RED}❌ Error: Could not retrieve the latest release version.${C_RESET}" 28 | exit 1 29 | fi 30 | 31 | # Check if the download was successful 32 | echo -e "\n🚀 Downloading the latest version ${BOLD}${CYAN}[$LATEST_RELEASE] of ${BOLD}${CYAN}$EXECUTABLE_NAME${C_RESET}${GREEN}...${C_RESET}\n" 33 | curl -L -o "$EXECUTABLE_NAME" "https://github.com/$REPO_OWNER/$REPO_NAME/releases/download/$LATEST_RELEASE/$EXECUTABLE_NAME" 34 | if [ $? -ne 0 ]; then 35 | echo -e "${RED}❌ Error: Download failed. Please check your network connection.${C_RESET}" 36 | exit 1 37 | fi 38 | 39 | chmod +x "$EXECUTABLE_NAME" 40 | 41 | # Move the executable to the installation directory 42 | echo -e "\nInstalling $EXECUTABLE_NAME to ${ITALIC}$INSTALL_DIR...${C_RESET}" 43 | 44 | mv "$EXECUTABLE_NAME" "$INSTALL_DIR" 45 | 46 | if [ -f "$INSTALL_DIR/$EXECUTABLE_NAME" ]; then 47 | echo -e "${GREEN}✅ $EXECUTABLE_NAME installed successfully!\n${C_RESET}" 48 | echo -e "${GREEN}🔍 To create your Makefile, run the command '${C_RESET}${BOLD}${CYAN}$EXECUTABLE_NAME${C_RESET}${GREEN}${BOLD}' at the root of your project.${C_RESET}" 49 | else 50 | echo -e "${RED}\n\n❌ Installation failed. Please check your permissions.${C_RESET}" 51 | exit 1 52 | fi 53 | 54 | # Add ~/bin to PATH if it is not already there 55 | if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then 56 | echo "export PATH=\$PATH:$INSTALL_DIR" >> "$HOME/.bashrc" 57 | echo -e "${ITALIC}💡 $INSTALL_DIR added to PATH. Please run ${BOLD}${CYAN}'source ~/.bashrc' ${C_RESET}${ITALIC}for changes to take effect.${C_RESET}" 58 | fi 59 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | #include "make_my_file.h" 10 | 11 | char *get_input(const char *prompt) 12 | { 13 | char *input = malloc(256); 14 | if (!input) 15 | return NULL; 16 | 17 | print_clear(); 18 | print_banner(); 19 | printf("%s", prompt); 20 | 21 | if (fgets(input, 256, stdin) != NULL) { 22 | size_t len = strlen(input); 23 | if (len > 0 && input[len - 1] == '\n') 24 | input[len - 1] = '\0'; 25 | } 26 | return (input); 27 | } 28 | 29 | char *get_default_input(const char *prompt, const char *default_value) 30 | { 31 | char *input = get_input(prompt); 32 | if (strlen(input) == 0) { 33 | free(input); 34 | input = strdup(default_value); 35 | } 36 | return (input); 37 | } 38 | 39 | void free_malloc(t_make_config *config) 40 | { 41 | free(config->name); 42 | free(config->src_dir); 43 | free(config->src_files); 44 | free(config->src_file_bonus); 45 | free(config->header_dir); 46 | free(config->header_files); 47 | free(config->obj_dir); 48 | free(config->compiler); 49 | free(config->cflags); 50 | free(config->ldflags); 51 | free(config->libs); 52 | free(config); 53 | } 54 | 55 | void default_config(t_make_config *config) 56 | { 57 | config->src_files = strdup(""); 58 | config->src_file_bonus = strdup(""); 59 | config->header_files = strdup(""); 60 | config->obj_dir = strdup("obj"); 61 | config->compiler = strdup("cc"); 62 | config->cflags = strdup("-Wall -Wextra -Werror"); 63 | config->include_libft = false; 64 | config->include_mlx = false; 65 | config->ldflags = strdup(""); 66 | config->libs = strdup(""); 67 | config->create_obj_dir = true; 68 | config->create_dependencies = true; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/check_update.c: -------------------------------------------------------------------------------- 1 | #include "make_my_file.h" 2 | 3 | #define INSTALL_SCRIPT_PATH "$HOME/.local/bin/install.sh" 4 | 5 | typedef struct 6 | { 7 | char *memory; 8 | size_t size; 9 | } MemoryStruct; 10 | 11 | // Callback function to store the response in a string 12 | size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) 13 | { 14 | size_t total_size = size * nmemb; 15 | MemoryStruct *mem = (MemoryStruct *)userp; 16 | 17 | char *ptr = realloc(mem->memory, mem->size + total_size + 1); 18 | if (ptr == NULL) 19 | return 0; 20 | 21 | mem->memory = ptr; 22 | memcpy(&(mem->memory[mem->size]), contents, total_size); 23 | mem->size += total_size; 24 | mem->memory[mem->size] = 0; 25 | 26 | return total_size; 27 | } 28 | 29 | // Pull the latest version from the GitHub API 30 | char *get_latest_release() 31 | { 32 | CURL *curl; 33 | CURLcode res; 34 | MemoryStruct chunk = { .memory = malloc(1), .size = 0 }; 35 | char *latest_version = malloc(10); 36 | 37 | curl = curl_easy_init(); 38 | if (curl) 39 | { 40 | curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repos/" REPO_OWNER "/" REPO_NAME "/releases/latest"); 41 | curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0"); 42 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); 43 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 44 | 45 | res = curl_easy_perform(curl); 46 | if (res == CURLE_OK) 47 | { 48 | char *tag_start = strstr(chunk.memory, "\"tag_name\":\""); 49 | if (tag_start) 50 | { 51 | tag_start += strlen("\"tag_name\":\""); 52 | char *tag_end = strchr(tag_start, '\"'); 53 | if (tag_end) 54 | { 55 | size_t tag_length = tag_end - tag_start; 56 | strncpy(latest_version, tag_start, tag_length); 57 | latest_version[tag_length] = '\0'; 58 | } 59 | } 60 | else 61 | strcpy(latest_version, CURRENT_VERSION); 62 | } 63 | else 64 | { 65 | fprintf(stderr, "Error: %s\n", curl_easy_strerror(res)); 66 | strcpy(latest_version, CURRENT_VERSION); 67 | } 68 | curl_easy_cleanup(curl); 69 | free(chunk.memory); 70 | } 71 | return latest_version; 72 | } 73 | 74 | void check_for_updates() 75 | { 76 | char *latest_version = get_latest_release(); 77 | 78 | if (strcmp(CURRENT_VERSION, latest_version) != 0) 79 | { 80 | printf("🚀 New version [%s] available! You are currently using version [%s]\n", latest_version, CURRENT_VERSION); 81 | printf("Do you want to update now? (Y/N): "); 82 | 83 | char response; 84 | scanf(" %c", &response); 85 | if (response == 'y' || response == 'Y') 86 | { 87 | // No need for sudo since it's installed in a user directory 88 | system(INSTALL_SCRIPT_PATH); 89 | } 90 | } 91 | free(latest_version); 92 | } -------------------------------------------------------------------------------- /src/project_directory_setup/create_directory_project.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | #include "write_in_file.h" 12 | 13 | static void config_default_project(t_make_config *config) 14 | { 15 | char src_files[52]; 16 | char header_files[52]; 17 | 18 | config->name = get_default_input(BOLD"[1/1]. "C_RESET BOLD CYAN"Enter the name"C_RESET" of the project: \n\n > "ITALIC"No space in name please\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "ProjectName"); 19 | config->create_lib_or_exec = false; 20 | config->src_dir = strdup("src"); 21 | config->header_dir = strdup("include"); 22 | default_config(config); 23 | snprintf(src_files, sizeof(src_files), "main.c %s.c", config->name); 24 | snprintf(header_files, sizeof(header_files), "%s.h", config->name); 25 | config->src_files = strdup(src_files); 26 | config->header_files = strdup(header_files); 27 | } 28 | 29 | void create_directory_project(t_make_config *config) 30 | { 31 | config_default_project(config); 32 | 33 | mkdir(config->src_dir, 0755); 34 | mkdir(config->header_dir, 0755); 35 | 36 | /* MAIN.C */ 37 | FILE *main_c = fopen("src/main.c", "w"); 38 | if (main_c) 39 | { 40 | fprintf(main_c, MAIN_C_CONTENT, config->name, config->name); 41 | fclose(main_c); 42 | } 43 | /* PROJECT.C */ 44 | char *project_c_path; 45 | asprintf(&project_c_path, "%s/%s.c", config->src_dir, config->name); 46 | FILE *project_c = fopen(project_c_path, "w"); 47 | if (project_c) 48 | { 49 | fprintf(project_c, PROJECT_C_CONTENT, config->name, config->name, config->name); 50 | fclose(project_c); 51 | } 52 | /* PROJECT.H */ 53 | char *project_h_path; 54 | asprintf(&project_h_path, "%s/%s.h", config->header_dir, config->name); 55 | FILE *project_h = fopen(project_h_path, "w"); 56 | if (project_h) 57 | { 58 | char *uppercase_name = strdup(config->name); 59 | int i = 0; 60 | while(uppercase_name[i]) 61 | { 62 | uppercase_name[i] = toupper(uppercase_name[i]); 63 | i++; 64 | } 65 | fprintf(project_h, PROJECT_H_CONTENT, uppercase_name, uppercase_name, uppercase_name, config->name); 66 | fclose(project_h); 67 | free(uppercase_name); 68 | } 69 | /* .GITIGNORE */ 70 | FILE *gitignore = fopen(".gitignore", "w"); 71 | if (gitignore) 72 | { 73 | fprintf(gitignore, GITIGNORE_CONTENT); 74 | fprintf(gitignore, "# Customize Executable Makefile\n%s\n", config->name); 75 | fclose(gitignore); 76 | } 77 | free(project_h_path); 78 | free(project_c_path); 79 | 80 | generate_makefile(config); 81 | print_config_setup_project(config); 82 | } -------------------------------------------------------------------------------- /src/project_directory_setup/check_directory.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | 12 | static short is_critical_directory(const char *cwd) 13 | { 14 | const char *home_dir = getenv("HOME"); 15 | return (strcmp(cwd, "/") == 0 || 16 | strcmp(cwd, "/home") == 0 || 17 | strcmp(cwd, "/usr") == 0 || 18 | strcmp(cwd, "/var") == 0 || 19 | strcmp(cwd, "/tmp") == 0 || 20 | strcmp(cwd, "/etc") == 0 || 21 | strcmp(cwd, "/proc") == 0 || 22 | strcmp(cwd, "/sys") == 0 || 23 | strcmp(cwd, "/boot") == 0 || 24 | strcmp(cwd, "/lib") == 0 || 25 | strcmp(cwd, "/lib64") == 0 || 26 | strcmp(cwd, "/opt") == 0 || 27 | strcmp(cwd, "/sbin") == 0 || 28 | strcmp(cwd, "/bin") == 0 || 29 | strcmp(cwd, "/root") == 0 || 30 | strcmp(cwd, "/dev") == 0 || 31 | (home_dir && strcmp(cwd, home_dir) == 0));;; 32 | } 33 | 34 | 35 | short check_directory(void) 36 | { 37 | char message[1400]; 38 | char cwd[MAX_FILES]; 39 | char *c_files; 40 | 41 | if (getcwd(cwd, sizeof(cwd)) == NULL) 42 | exit(EXIT_FAILURE); 43 | 44 | if (is_critical_directory(cwd)) 45 | { 46 | printf(RED BOLD"\n\nWARNING: You are running the program in a critical system directory: %s\n" C_RESET, cwd); 47 | printf(RED BOLD"Please run the program in the root of your project directory.\n\n" C_RESET); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | c_files = auto_detect_files(cwd, ".c"); 52 | print_clear(); 53 | 54 | if (c_files && strlen(c_files) > 0) 55 | { 56 | snprintf(message, sizeof(message), 57 | BOLD YELLOW"WARNING: "C_RESET YELLOW"You must be in the project's root directory to proceed.\n" C_RESET 58 | GREEN BOLD"\n🤖 Auto-Detect - C project detected in current directory: "C_RESET"%s\n\n" 59 | CYAN BOLD"\nPress any key to continue... "C_RESET"For confirm you're in the root directory of your project.\n" C_RESET, cwd); 60 | get_input(message); 61 | free(c_files); 62 | return (0); 63 | } 64 | else 65 | { 66 | snprintf(message, sizeof(message), 67 | BOLD YELLOW"WARNING: "C_RESET YELLOW"You must be in the project's root directory to proceed.\n" C_RESET 68 | YELLOW BOLD"🤖 Auto-Detect - No C project detected in directory: "C_RESET"%s\n" 69 | CYAN BOLD"\nWould you like to generate a basic C project in this directory ? "YorN"\n\n" C_RESET, cwd); 70 | char *input = get_default_input(message, "n"); 71 | if (input[0] == 'y' || input[0] == 'Y') 72 | return (1); 73 | else 74 | { 75 | printf(CYAN BOLD"\nNo project will be generated. Exiting.\n" C_RESET); 76 | printf(BOLD"Goodbye ! 👋\n"); 77 | exit(EXIT_SUCCESS); 78 | } 79 | } 80 | return (0); 81 | } -------------------------------------------------------------------------------- /src/generate_makefile/auto_detec_files.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | 12 | /* Detect files with a specific extension in the given directory */ 13 | static void detect_files(const char *base_dir, const char *current_dir, const char *ext, char **result) 14 | { 15 | DIR *dir; 16 | struct dirent *entry; 17 | 18 | dir = opendir(current_dir); 19 | if (!dir) 20 | { 21 | printf("Error auto-detecting.\nCould not open directory: %s\n", current_dir); 22 | return; 23 | } 24 | 25 | 26 | while ((entry = readdir(dir)) != NULL) 27 | { 28 | if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) 29 | { 30 | char path[MAX_FILES]; 31 | snprintf(path, sizeof(path), "%s/%s", current_dir, entry->d_name); 32 | // Check if a directory 33 | struct stat statbuf; 34 | if (stat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) 35 | detect_files(base_dir, path, ext, result); 36 | else if (strstr(entry->d_name, ext)) // Check the extension 37 | { 38 | // Add the file to the list 39 | char *relative_path = path + strlen(base_dir) + 1; 40 | if (strlen(*result) + strlen(relative_path) + 2 > MAX_FILES) 41 | { 42 | // Realloc if exceeding max files 43 | char *tmp = realloc(*result, strlen(*result) + strlen(relative_path) + 2); 44 | if (!tmp) 45 | { 46 | free(*result); 47 | *result = NULL; 48 | closedir(dir); 49 | return; 50 | } 51 | *result = tmp; 52 | } 53 | strcat(*result, relative_path); 54 | strcat(*result, " "); 55 | printf(C_RESET ITALIC "Detected file: %s" C_RESET "\n", relative_path); 56 | } 57 | } 58 | } 59 | closedir(dir); 60 | } 61 | 62 | char *auto_detect_files(const char *dir_path, const char *ext) 63 | { 64 | char *result = malloc(sizeof(char) * MAX_FILES); 65 | if (!result) 66 | return (NULL); 67 | result[0] = '\0'; 68 | 69 | printf(GREEN BOLD"\n🤖 Auto-detecting files is enabled with extension '%s' in directory: %s\n\n" C_RESET, ext, dir_path); 70 | 71 | detect_files(dir_path, dir_path, ext, &result); 72 | 73 | if (strlen(result) == 0) 74 | printf(RED"\nNo files detected with extension '%s' in directory: %s\n\n" C_RESET, ext, dir_path); 75 | 76 | return (result); 77 | } 78 | 79 | void auto_detec_sources(t_make_config *config) 80 | { 81 | print_clear(); 82 | print_banner(); 83 | 84 | if (!config->src_files || strlen(config->src_files) == 0) 85 | config->src_files = auto_detect_files(config->src_dir, ".c"); 86 | else 87 | printf(RED BOLD"🤖 Auto-detecting for src_files DISABLE\n"); 88 | 89 | if (!config->src_file_bonus || strlen(config->src_file_bonus) == 0) 90 | config->src_file_bonus = auto_detect_files(config->src_dir, "_bonus.c"); 91 | else 92 | printf(RED BOLD"🤖 Auto-detecting for src_files_bonus DISABLE\n"); 93 | 94 | if (!config->header_files || strlen(config->header_files) == 0) 95 | config->header_files = auto_detect_files(config->header_dir, ".h"); 96 | else 97 | printf(RED BOLD"🤖 Auto-detecting for include_files DISABLE\n"); 98 | 99 | print_point_loading(); 100 | } 101 | 102 | -------------------------------------------------------------------------------- /include/make_my_file.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #ifndef MAKE_MY_FILE_H 11 | # define MAKE_MY_FILE_H 12 | 13 | # include 14 | # include 15 | # include 16 | # include 17 | # include 18 | # include 19 | # include 20 | # include 21 | # include 22 | # include 23 | # include 24 | # include 25 | # include 26 | 27 | /***************** UPDATE *******************/ 28 | #define CURRENT_VERSION "1.2.6" 29 | #define REPO_OWNER "MathysCogne" 30 | #define REPO_NAME "Make_My_File-42" 31 | 32 | /***************** MACROS *******************/ 33 | # define MAX_FILES 1024 34 | 35 | # define SOURCE_EXTENSION ".c" 36 | # define HEADER_EXTENSION ".h" 37 | 38 | /***************** COLORS ******************/ 39 | # define RED "\033[31m" 40 | # define GREEN "\033[32m" 41 | # define YELLOW "\033[33m" 42 | # define BLUE "\033[34m" 43 | # define PURPLE "\033[35m" 44 | # define CYAN "\033[36m" 45 | # define BOLD "\033[1m" 46 | # define ITALIC "\033[3m" 47 | # define UDERLINE "\033[4m" 48 | # define C_RESET "\033[0m" 49 | 50 | # define YorN ""C_RESET"["BOLD GREEN"y"C_RESET BOLD"/"BOLD RED"n"C_RESET"]" 51 | 52 | /***************** STRUCT ******************/ 53 | typedef struct s_make_config 54 | { 55 | char *name; /* Executable name */ 56 | char *src_dir; /* Src dir */ 57 | char *src_files; /* Src files */ 58 | char *src_file_bonus; /* Src files bonus */ 59 | char *header_dir; /* Header dir */ 60 | char *header_files; /* Header files */ 61 | char *obj_dir; /* Object dir */ 62 | char *compiler; /* Compiler */ 63 | char *cflags; /* Compilation flags */ 64 | char *ldflags; /* Linker flags */ 65 | char *libs; /* Libraries to link */ 66 | bool create_obj_dir; /* Create object directory */ 67 | bool create_dependencies; /* Generate dependency files*/ 68 | bool include_libft; /* Include libft library */ 69 | bool include_mlx; /* Include MLX library */ 70 | short create_lib_or_exec; /* 0 executable, 1 library */ 71 | /* char *output_dir; Executable directory */ // FEATURE 72 | } t_make_config; 73 | 74 | /************** MAKE MY FILE ***************/ 75 | /* PROJECT DIR SETUP */ 76 | short check_directory(void); 77 | void create_directory_project(t_make_config *config); 78 | 79 | /* GENERATION MAKEFILE */ 80 | short make_my_file(t_make_config *config); 81 | short init_config(t_make_config *config); 82 | void auto_detec_sources(t_make_config *config); 83 | char *auto_detect_files(const char *dir_path, const char *ext); 84 | void generate_makefile(t_make_config *config); 85 | /* AUTO UPDATE */ 86 | void check_for_updates(); 87 | 88 | /****************** UTILS *******************/ 89 | void free_malloc(t_make_config *config); 90 | void default_config(t_make_config *config); 91 | char *get_input(const char *prompt); 92 | char *get_default_input(const char *prompt, const char *default_value); 93 | 94 | /****************** PRINT *******************/ 95 | void print_banner(void); 96 | void print_point_loading(void); 97 | void print_clear(void); 98 | void print_documentation(t_make_config *config); 99 | void print_menu(t_make_config *config); 100 | void print_config(t_make_config *config); 101 | void print_config_setup_project(t_make_config *config); 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile generated by Make My File: https://github.com/MathysCogne/Make_My_File-42 2 | # Date of generation: 29-10-2024 17:22:47 3 | 4 | # 📄 Documentation: 5 | # This Makefile is generated automatically by the Make My File program. 6 | # It facilitates the compilation of C programs. 7 | # For further details on Makefile usage, you can consult the official GNU Make documentation: 8 | # https://www.gnu.org/software/make/manual/make.html 9 | # 10 | # 🔧 Variables: 11 | # - NAME: Name of the executable or library to create. 12 | # - SRCDIR: Directory where the source (.c) files are located. 13 | # - OBJDIR: Directory where object files will be stored. 14 | # - INCDIR: Directory containing header (.h) files for inclusion. 15 | # - SRC: List of source files to compile. 16 | # - OBJ: Object files generated from the source files. 17 | # - CC: The compiler to use. Default is 'cc', but you can modify it if needed. 18 | # - CFLAGS: Compilation flags (default includes warnings and debugging). 19 | # - LDFLAGS: Linker flags (if any). 20 | # - LIBS: Libraries to link against. 21 | # - LIBFT_DIR: Directory where Libft is located. 22 | # - MINILIBX_DIR: Directory where MiniLibX will be cloned automatically. 23 | # 24 | # 🚀 Rules: 25 | # - 'make': Compiles the entire project by generating the executable defined in NAME. 26 | # - 'make clean': Deletes only the compiled object (.o) files, keeping the executable. 27 | # - 'make fclean': Deletes all generated files, including the executable and object files. 28 | # - 'make re': Cleans (fclean) and then rebuilds the project from scratch. 29 | # - 'make bonus': Compiles additional bonus source files if defined in the project. 30 | # - 'make regen': Re-generates the Makefile if Make My File configuration has changed. 31 | # 32 | # 📚 Usage of Libft: 33 | # - Default Directory: 'libft'. 34 | # - If your Libft is located in a different directory, customize the 'LIBFT_DIR' variable in the Makefile accordingly. 35 | # - Include the header in your source files: #include "libft.h" 36 | # - Example usage: int result = ft_strlen("Hello"); 37 | # 38 | # 🖼️ Usage of MiniLibX: 39 | # - MiniLibX will be cloned and included automatically. Choose this option during configuration. 40 | # - Include the header in your source files: #include "mlx.h" 41 | # - Example usage: mlx_init(); 42 | # 43 | # 💡 Tips: 44 | # - Use 'VERBOSE=1' when running make (e.g., 'make VERBOSE=1') to see detailed command outputs. 45 | # 46 | # Please report any bugs or suggestions at: https://github.com/MathysCogne/Make_My_File-42/issues 47 | 48 | NAME = makemyfile 49 | 50 | SRCDIR = src 51 | OBJDIR = obj 52 | INCDIR = include 53 | 54 | # Source Files 55 | SRC = print.c make_my_file.c main.c check_update.c project_directory_setup/create_directory_project.c project_directory_setup/check_directory.c utils.c generate_makefile/configuration.c generate_makefile/auto_detec_files.c generate_makefile/write_makefile.c 56 | OBJ = $(SRC:.c=.o) 57 | SRC := $(addprefix $(SRCDIR)/, $(SRC)) 58 | OBJ := $(patsubst $(SRCDIR)/%, $(OBJDIR)/%, $(OBJ)) 59 | 60 | # Libraries and Linker Flags 61 | LDFLAGS = 62 | LIBS = 63 | 64 | # Archiver 65 | AR = ar 66 | ARFLAGS = rcs 67 | 68 | # Compiler and Flags 69 | CC = cc 70 | CFLAGS = -Wall -Wextra -Werror -I$(INCDIR) -g3 71 | 72 | # Compilation mode (silent by default, set VERBOSE=1 to show commands) 73 | VERBOSE ?= 0 74 | ifeq ($(VERBOSE),1) 75 | V := 76 | else 77 | V := @ 78 | endif 79 | 80 | # Colors 81 | RED := "\033[1;31m" 82 | GREEN := "\033[1;32m" 83 | RESET := "\033[0m" 84 | 85 | 86 | 87 | # Default Rule 88 | all: $(OBJDIR) $(NAME) 89 | 90 | # Object Directory Rule 91 | $(OBJDIR): 92 | $(V)mkdir -p $(OBJDIR) || true 93 | 94 | # Dependency Files 95 | DEP = $(OBJ:.o=.d) 96 | 97 | $(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR) 98 | @mkdir -p $(dir $@) 99 | $(V)$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ 100 | 101 | -include $(DEP) 102 | 103 | # Linking Rule 104 | $(NAME): $(OBJ) 105 | $(V)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(BONUS_OBJ) $(LIBS) $(MLXFLAGS) -o $(NAME) -lcurl 106 | $(V)echo $(GREEN)"[$(NAME)] Executable created ✅"$(RESET) 107 | 108 | # Clean Rules 109 | clean: 110 | $(V)echo $(RED)'[$(NAME)] Cleaning objects'd$(RESET) 111 | $(V)rm -rf $(OBJDIR) 112 | 113 | fclean: clean 114 | $(V)echo $(RED)'[$(NAME)] Cleaning all files'$(RESET) 115 | $(V)rm -f $(NAME) 116 | 117 | re: fclean all 118 | 119 | # Makefile Reconfiguration 120 | regen: 121 | makemyfile 122 | 123 | .PHONY: all clean fclean re bonus regen 124 | .DEFAULT_GOAL := all -------------------------------------------------------------------------------- /include/write_in_file.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #ifndef WRITE_IN_FILE_H 11 | # define WRITE_IN_FILE_H 12 | 13 | /***************** DEFAULT_PROJECT_GEN ******************/ 14 | #define MAIN_C_CONTENT \ 15 | "#include \"%s.h\"\n\n" \ 16 | "int main(int argc, char **argv)\n" \ 17 | "{\n" \ 18 | " (void)argc;\n" \ 19 | " (void)argv;\n" \ 20 | " %s();\n" \ 21 | " return (0);\n" \ 22 | "}\n" 23 | 24 | #define PROJECT_C_CONTENT \ 25 | "#include \"%s.h\"\n\n" \ 26 | "int %s(void)\n" \ 27 | "{\n" \ 28 | " printf(\"This is the main logic of %s!\\n\");\n" \ 29 | " return (0);\n" \ 30 | "}\n" 31 | 32 | #define PROJECT_H_CONTENT \ 33 | "#ifndef %s_H\n" \ 34 | "# define %s_H\n\n" \ 35 | "/* #include \"libft.h\" */\n" \ 36 | "/* #include \"mlx.h\" */\n\n" \ 37 | "#include \n\n" \ 38 | "/************** %s **************/\n" \ 39 | "int %s(void);\n\n" \ 40 | "#endif\n" 41 | 42 | #define GITIGNORE_CONTENT \ 43 | "# Compiled object files\n" \ 44 | "*.o\n" \ 45 | "*.d\n" \ 46 | "obj/\n" \ 47 | "*.obj\n\n" \ 48 | "# Executables\n" \ 49 | "*.exe\n" \ 50 | "*.out\n" \ 51 | "*.app\n\n" \ 52 | "# Libraries\n" \ 53 | "*.a\n" \ 54 | "*.so\n" \ 55 | "# Backup files\n" \ 56 | "*~\n" \ 57 | "*.bak\n\n" \ 58 | "# CMake files\n" \ 59 | "CMakeFiles/\n" \ 60 | "CMakeCache.txt\n" \ 61 | "cmake_install.cmake\n\n" \ 62 | "# IDE specific files\n" \ 63 | ".vscode/\n" \ 64 | ".idea/\n" \ 65 | "*.swp\n\n" \ 66 | "*.log\n\n" 67 | 68 | 69 | /***************** MAKE_GEN ******************/ 70 | 71 | #define MAKEFILE_DOC \ 72 | "# 📄 Documentation:\n" \ 73 | "# This Makefile is generated automatically by the Make My File program.\n" \ 74 | "# It facilitates the compilation of C programs.\n" \ 75 | "# For further details on Makefile usage, you can consult the official GNU Make documentation:\n" \ 76 | "# https://www.gnu.org/software/make/manual/make.html \n" \ 77 | "#\n" \ 78 | "# 🔧 Variables:\n" \ 79 | "# - NAME: Name of the executable or library to create.\n" \ 80 | "# - SRCDIR: Directory where the source (.c) files are located.\n" \ 81 | "# - OBJDIR: Directory where object files will be stored.\n" \ 82 | "# - INCDIR: Directory containing header (.h) files for inclusion.\n" \ 83 | "# - SRC: List of source files to compile.\n" \ 84 | "# - OBJ: Object files generated from the source files.\n" \ 85 | "# - CC: The compiler to use. Default is 'cc', but you can modify it if needed.\n" \ 86 | "# - CFLAGS: Compilation flags (default includes warnings and debugging).\n" \ 87 | "# - LDFLAGS: Linker flags (if any).\n" \ 88 | "# - LIBS: Libraries to link against.\n" \ 89 | "# - LIBFT_DIR: Directory where Libft is located.\n" \ 90 | "# - MINILIBX_DIR: Directory where MiniLibX will be cloned automatically.\n" \ 91 | "#\n" \ 92 | "# 🚀 Rules:\n" \ 93 | "# - 'make': Compiles the entire project by generating the executable defined in NAME.\n" \ 94 | "# - 'make clean': Deletes only the compiled object (.o) files, keeping the executable.\n" \ 95 | "# - 'make fclean': Deletes all generated files, including the executable and object files.\n" \ 96 | "# - 'make re': Cleans (fclean) and then rebuilds the project from scratch.\n" \ 97 | "# - 'make bonus': Compiles additional bonus source files if defined in the project.\n" \ 98 | "# - 'make regen': Re-generates the Makefile if Make My File configuration has changed.\n" \ 99 | "#\n" \ 100 | "# 📚 Usage of Libft:\n" \ 101 | "# - Default Directory: 'libft'.\n" \ 102 | "# - If your Libft is located in a different directory, customize the 'LIBFT_DIR' variable in the Makefile accordingly.\n" \ 103 | "# - Include the header in your source files: #include \"libft.h\"\n" \ 104 | "# - Example usage: int result = ft_strlen(\"Hello\");\n" \ 105 | "#\n" \ 106 | "# 🖼️ Usage of MiniLibX:\n" \ 107 | "# - MiniLibX will be cloned and included automatically. Choose this option during configuration.\n" \ 108 | "# - Include the header in your source files: #include \"mlx.h\"\n" \ 109 | "# - Example usage: mlx_init();\n" \ 110 | "#\n" \ 111 | "# 💡 Tips:\n" \ 112 | "# - Use 'VERBOSE=1' when running make (e.g., 'make VERBOSE=1') to see detailed command outputs.\n" \ 113 | "#\n" \ 114 | "# Please report any bugs or suggestions at: https://github.com/MathysCogne/Make_My_File-42/issues\n\n" 115 | 116 | #endif -------------------------------------------------------------------------------- /src/print.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | #include "write_in_file.h" 12 | 13 | void print_banner(void) 14 | { 15 | printf(C_RESET RED"\n███╗ ███╗ █████╗ ██╗ ██╗███████╗ "C_RESET"███╗ ███╗██╗ ██╗ "YELLOW"███████╗██╗██╗ ███████╗\n"); 16 | printf(RED "████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ "C_RESET"████╗ ████║╚██╗ ██╔╝ "YELLOW"██╔════╝██║██║ ██╔════╝\n"); 17 | printf(RED "██╔████╔██║███████║█████╔╝ █████╗ "C_RESET"██╔████╔██║ ╚████╔╝ "YELLOW"█████╗ ██║██║ █████╗ \n"); 18 | printf(RED "██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ "C_RESET"██║╚██╔╝██║ ╚██╔╝ "YELLOW"██╔══╝ ██║██║ ██╔══╝ \n"); 19 | printf(RED "██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ "C_RESET"██║ ╚═╝ ██║ ██║ "YELLOW"██║ ██║███████╗███████╗\n"); 20 | printf(RED "╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ "C_RESET"╚═╝ ╚═╝ ╚═╝ "YELLOW"╚═╝ ╚═╝╚══════╝╚══════╝\n\n\n" C_RESET); 21 | } 22 | 23 | void print_point_loading(void) 24 | { 25 | int i; 26 | 27 | i = 0; 28 | printf(GREEN BOLD"\n\nLoading"); 29 | while (i < 3) 30 | { 31 | printf("."); 32 | fflush(stdout); 33 | sleep(1); 34 | i++; 35 | } 36 | } 37 | 38 | void print_clear(void) 39 | { 40 | #ifdef _WIN32 41 | system("cls"); 42 | #else 43 | system("clear"); 44 | #endif 45 | } 46 | 47 | void print_config(t_make_config *config) 48 | { 49 | print_clear(); 50 | print_banner(); 51 | 52 | printf(GREEN BOLD "Congratulations ! 🥳🥳🥳 Your Makefile has been generated successfully !\n\n\n" C_RESET); 53 | printf(CYAN BOLD"You are creating a Makefile that generates an "BOLD PURPLE"%s", config->create_lib_or_exec ? "library" : "executable"); 54 | printf(CYAN", named "PURPLE"%s"C_RESET":\n", config->name); 55 | 56 | printf("\n- For compilation, you will be using: " BOLD PURPLE "%s %s %s" C_RESET "\n", config->compiler, config->cflags, config->ldflags); 57 | printf("- Use and create an Object Directory / Dependency Files: " BOLD "%s" C_RESET "\n\n", config->create_obj_dir ? GREEN"Yes" : RED"No"); 58 | 59 | printf("- Source Files: " BOLD PURPLE "%s" C_RESET "\n", config->src_files); 60 | printf("- Header Files: " BOLD PURPLE "%s" C_RESET "\n", config->header_files); 61 | printf("- Bonus Source Files: " BOLD PURPLE "%s" C_RESET "\n\n", 62 | strlen(config->src_file_bonus) > 0 ? config->src_file_bonus : RED"No bonus"); 63 | 64 | printf("- Libraries included: " BOLD PURPLE "%s" C_RESET "\n", 65 | strlen(config->libs) > 0 ? config->libs : "None"C_RESET); 66 | printf("- Libft inclusion: " BOLD "%s" C_RESET "\n", config->include_libft ? GREEN"Yes" : PURPLE"No"); 67 | printf("- MLX inclusion: " BOLD "%s" C_RESET "\n\n\n", config->include_mlx ? GREEN"Yes" : PURPLE"No"); 68 | 69 | printf("Thank you for using Make My File ! Enjoy your project ! 🚀\n\n"); 70 | printf("⭐ If you like this project, please star it on GitHub: "); 71 | printf(BOLD CYAN "https://github.com/MathysCogne/Make_My_File-42" C_RESET "\n"); 72 | printf("🤖 Report any bugs or suggestions at: "); 73 | printf(BOLD CYAN "https://github.com/MathysCogne/Make_My_File-42/issues" C_RESET "\n\n"); 74 | 75 | exit(EXIT_SUCCESS); 76 | } 77 | 78 | void print_config_setup_project(t_make_config *config) 79 | { 80 | print_clear(); 81 | print_banner(); 82 | 83 | printf(GREEN BOLD "Congratulations ! 🥳🥳🥳 Your basic C project has been generated successfully !\n\n" C_RESET); 84 | 85 | printf("\n- For compilation, you will be using: " BOLD PURPLE "%s %s %s" C_RESET "\n", config->compiler, config->cflags, config->ldflags); 86 | printf("- Source Files: " BOLD PURPLE "%s" C_RESET "\n", config->src_files); 87 | printf("- Header Files: " BOLD PURPLE "%s" C_RESET "\n\n", config->header_files); 88 | 89 | printf("Thank you for using Make My File ! Enjoy your project ! 🚀\n\n"); 90 | printf("⭐ If you like this project, please star it on GitHub: "); 91 | printf(BOLD CYAN "https://github.com/MathysCogne/Make_My_File-42" C_RESET "\n"); 92 | printf("🤖 Report any bugs or suggestions at: "); 93 | printf(BOLD CYAN "https://github.com/MathysCogne/Make_My_File-42/issues" C_RESET "\n\n"); 94 | 95 | exit(EXIT_SUCCESS); 96 | } 97 | /* ARCHIVE ****************************************************************************** 98 | *void print_documentation(t_make_config *config) 99 | *{ 100 | * print_clear(); 101 | * print_banner(); 102 | * 103 | * printf(MAKEFILE_DOC); 104 | * 105 | * print_menu(config); 106 | *} 107 | * 108 | *void print_menu(t_make_config *config) 109 | *{ 110 | * int choice; 111 | * 112 | * while (1) 113 | * { 114 | * printf(BOLD CYAN"\n0 ➤"C_RESET" View the documentation\n"); 115 | * printf(BOLD CYAN"1 ➤"C_RESET" Exit\n"); 116 | * printf(BOLD CYAN "\n➜ " C_RESET); 117 | * if (scanf("%d", &choice) != 1) 118 | * { 119 | * printf(RED "Invalid option\n\n" C_RESET); 120 | * while (getchar() != '\n'); 121 | * continue ; 122 | * } 123 | * 124 | * if (choice == 0) 125 | * print_documentation(config); 126 | * if (choice == 1) 127 | * { 128 | * print_clear(); 129 | * print_banner(); 130 | * printf("Thank you for using Make My File ! Enjoy your project ! 🚀\n\n"); 131 | * printf("⭐ If you like this project, please star it on GitHub: "); 132 | * printf(BOLD CYAN "https://github.com/MathysCogne/Make_My_File-42" C_RESET "\n"); 133 | * printf("🤖 Report any bugs or suggestions at: "); 134 | * printf(BOLD CYAN "https://github.com/MathysCogne/Make_My_File-42/issues" C_RESET "\n\n"); 135 | * printf(BOLD"\nGoodbye ! 👋\n\n"); 136 | * exit(0); 137 | * } 138 | * else 139 | * printf(RED "Invalid option.\n\n" C_RESET); 140 | * } 141 | *} 142 | ***********************************************************************************************/ -------------------------------------------------------------------------------- /src/generate_makefile/configuration.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | 12 | short init_config(t_make_config *config) 13 | { 14 | bool fast_mode = false; 15 | char *fast_mode_input = get_default_input(BOLD GREEN"Welcome to the Make My File ! \n\n" C_RESET 16 | "This application will help you create a Makefile.\n\n\n" 17 | BOLD"🚀 "C_RESET"Enable "BOLD CYAN"fast mode "C_RESET""YorN" ?\n\n"C_RESET 18 | "> If you want to use Libft or MiniLibX (minilibx-linux), please choose No. \n" 19 | "> 💡 Tips: Leaving the options blank will always set a default value \n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "src"); 20 | fast_mode = (fast_mode_input[0] == 'y' || fast_mode_input[0] == 'Y'); 21 | free(fast_mode_input); 22 | 23 | /* FAST MODE */ 24 | if (fast_mode) 25 | { 26 | char *create_lib_or_exec = get_input(BOLD"[1/4] "C_RESET"Create "CYAN"library "BOLD"'1'"C_RESET" or "C_RESET CYAN"executable "BOLD"'0'"C_RESET ITALIC" (Default is executable)"C_RESET" ?\n\n"C_RESET BOLD CYAN"➜"C_RESET" "); 27 | config->create_lib_or_exec = (create_lib_or_exec[0] == '1') ? 1 : 0; 28 | free(create_lib_or_exec); 29 | 30 | config->name = get_default_input(BOLD"[2/4] "C_RESET BOLD CYAN"Enter the name"C_RESET" of the executable or library: \n\n > "ITALIC"No space in name please\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "ProjectName"); 31 | config->src_dir = get_default_input(BOLD"[3/4] "C_RESET"Enter the "BOLD CYAN"source directory"C_RESET" or leave blank for "BOLD CYAN"default"C_RESET" "ITALIC"(Default is 'src'): \n\n" 32 | "> If using the current directory, please type '.'\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "src"); 33 | config->header_dir = get_default_input(BOLD"[4/4] "C_RESET"Enter the "BOLD CYAN"includes directory"C_RESET" or leave blank for "BOLD CYAN"default"C_RESET" "ITALIC"(Default is 'include'): \n\n" 34 | "> If using the current directory, please type '.'\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "include"); 35 | default_config(config); // Set other params 36 | return (0); 37 | } 38 | 39 | /* NORMAL MODE */ 40 | char *create_lib_or_exec = get_default_input(BOLD"[1/13] "C_RESET"Create "CYAN"library "BOLD"'1'"C_RESET" or "C_RESET CYAN"executable "BOLD"'0'"C_RESET ITALIC" (Default is executable)"C_RESET" ?\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "0"); 41 | config->create_lib_or_exec = (create_lib_or_exec[0] == '1') ? 1 : 0; 42 | free(create_lib_or_exec); 43 | 44 | config->name = get_default_input(BOLD"[2/13] "C_RESET BOLD CYAN"Enter the name"C_RESET" of the executable or library: \n\n > "ITALIC"No space in name please\n\n" BOLD CYAN"➜"C_RESET" ", "ProjectName"); 45 | config->src_dir = get_default_input(BOLD"[3/13] "C_RESET"Enter the "BOLD CYAN"source directory"C_RESET" or leave blank for "BOLD CYAN"default"C_RESET" "ITALIC"(Default is 'src'): \n\n" 46 | "> If using the current directory, please type '.'\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "src"); 47 | config->header_dir = get_default_input(BOLD"[4/13] "C_RESET"Enter the "BOLD CYAN"includes directory"C_RESET" or leave blank for "BOLD CYAN"default"C_RESET" "ITALIC"(Default is 'include'): \n\n" 48 | "> If using the current directory, please type '.'\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "include"); 49 | config->src_files = get_default_input(BOLD"[5/13] "C_RESET"Enter the "BOLD CYAN"source files"C_RESET" or leave blank for "BOLD CYAN"auto-detection"C_RESET" "ITALIC"(Ex: main.c utils.c ft_putchar.c): \n\n" 50 | C_RESET"🤖"ITALIC" If left blank, source files will be automatically detected in the selected directory\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", ""); 51 | 52 | config->src_file_bonus = get_default_input(BOLD"[6/13] "C_RESET"Enter the "BOLD CYAN"bonus source files"C_RESET" or leave blank for "BOLD CYAN"auto-detection"C_RESET" "ITALIC"(Ex: *_bonus.c): \n\n" 53 | C_RESET"🤖"ITALIC" If left blank, bonus source files will be automatically detected in the selected directory\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", ""); 54 | config->header_files = get_default_input(BOLD"[7/13] "C_RESET"Enter the "BOLD CYAN"header files"C_RESET" or leave blank for "BOLD CYAN"auto-detection"C_RESET" "ITALIC"(Ex: ft.h): \n\n" 55 | C_RESET"🤖"ITALIC" If left blank, header files will be automatically detected in the selected directory\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", ""); 56 | config->obj_dir = strdup("obj"); 57 | 58 | config->compiler = get_default_input(BOLD"[8/13] "C_RESET BOLD CYAN"Enter the compiler"C_RESET" "ITALIC"(Default is 'cc' leave blank): \n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "cc"); 59 | config->cflags = get_default_input(BOLD"[9/13] "C_RESET BOLD CYAN"Enter the compilation flags"C_RESET" "ITALIC"(Default '-Wall -Wextra -Werror' leave blank): \n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "-Wall -Wextra -Werror"); 60 | char *include_libft = get_default_input(BOLD"[10/13] "C_RESET"Include "BOLD CYAN"ft_libft "YorN" "C_RESET"? "C_RESET ITALIC"(Default 'No')\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "n"); 61 | config->include_libft = (include_libft[0] == 'y' || include_libft[0] == 'Y'); 62 | free(include_libft); 63 | 64 | char *include_mlx = get_default_input(BOLD"[11/13] "C_RESET"Include "BOLD CYAN"MLX (minilibx-linux) with auto download script. "YorN" "C_RESET"? "C_RESET ITALIC"(Default 'No')\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "n"); 65 | config->include_mlx = (include_mlx[0] == 'y' || include_mlx[0] == 'Y'); 66 | free(include_mlx); 67 | 68 | config->ldflags = get_default_input(BOLD"[12/13] "C_RESET BOLD CYAN"Enter the linker flags"C_RESET" (LDFLAGS) or leave blank for none: \n\n"C_RESET BOLD CYAN"➜"C_RESET" ", ""); 69 | config->libs = get_default_input(BOLD"[13/13] "C_RESET"Enter "BOLD CYAN"the libraries to link"C_RESET" or leave blank if none: \n\n"C_RESET BOLD CYAN"➜"C_RESET" ", ""); 70 | 71 | // char *create_obj_dir = get_default_input(BOLD"14. "C_RESET"Create and using "BOLD CYAN"object directory with dependency files" "YorN" C_RESET" ? "C_RESET ITALIC "(Default 'Yes')\n\n"C_RESET BOLD CYAN"➜"C_RESET" ", "y"); 72 | // config->create_obj_dir = (create_obj_dir[0] == 'y' || create_obj_dir[0] == 'Y'); 73 | // config->create_dependencies = config->create_obj_dir; 74 | // free(create_obj_dir); 75 | config->create_dependencies = true; 76 | 77 | return (0); 78 | } 79 | -------------------------------------------------------------------------------- /src/generate_makefile/write_makefile.c: -------------------------------------------------------------------------------- 1 | /************************************************************************************************/ 2 | /* ███╗ ███╗ █████╗ ██╗ ██╗███████╗ ███╗ ███╗██╗ ██╗ ███████╗██╗██╗ ███████╗ */ 3 | /* ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝ ████╗ ████║╚██╗ ██╔╝ ██╔════╝██║██║ ██╔════╝ */ 4 | /* ██╔████╔██║███████║█████╔╝ █████╗ ██╔████╔██║ ╚████╔╝ █████╗ ██║██║ █████╗ */ 5 | /* ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██║╚██╔╝██║ ╚██╔╝ ██╔══╝ ██║██║ ██╔══╝ */ 6 | /* ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗ ██║ ╚═╝ ██║ ██║ ██║ ██║███████╗███████╗ */ 7 | /* ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ */ 8 | /************************************************************************************************/ 9 | 10 | #include "make_my_file.h" 11 | #include "write_in_file.h" 12 | 13 | void generate_makefile(t_make_config *config) 14 | { 15 | FILE *file = fopen("Makefile", "w"); 16 | if (!file) 17 | { 18 | printf("Error.\n Could not create Makefile.\n"); 19 | return; 20 | } 21 | 22 | /*** PRINT DOC ***/ 23 | time_t now = time(NULL); 24 | struct tm *local_time = localtime(&now); 25 | fprintf(file, "# Makefile generated by Make My File: https://github.com/MathysCogne/Make_My_File-42\n"); 26 | fprintf(file, "# Date of generation: %02d-%02d-%04d %02d:%02d:%02d\n\n", local_time->tm_mday, local_time->tm_mon + 1, local_time->tm_year + 1900, local_time->tm_hour, local_time->tm_min, local_time->tm_sec); 27 | fprintf(file, MAKEFILE_DOC); 28 | 29 | /*** INCLUDE HEADER DEFINE ***/ 30 | fprintf(file, "NAME = %s\n\n", config->name); 31 | 32 | fprintf(file, "SRCDIR = %s\n", config->src_dir); 33 | fprintf(file, "OBJDIR = %s\n", config->obj_dir); 34 | fprintf(file, "INCDIR = %s\n\n", config->header_dir); 35 | 36 | /*** SRC FILES DEFINE ***/ 37 | fprintf(file, "# Source Files\n"); 38 | fprintf(file, "SRC = %s\n", config->src_files); 39 | fprintf(file, "OBJ = $(SRC:.c=.o)\n"); 40 | 41 | fprintf(file, "SRC := $(addprefix $(SRCDIR)/, $(SRC))\n"); 42 | fprintf(file, "OBJ := $(patsubst $(SRCDIR)/%%, $(OBJDIR)/%%, $(OBJ))\n\n"); 43 | 44 | /*** BONUS FILES DEFINE ***/ 45 | if (config->src_file_bonus && strlen(config->src_file_bonus) > 0) 46 | { 47 | fprintf(file, "# Bonus Files\n"); 48 | fprintf(file, "BONUS_SRC = %s\n", config->src_file_bonus); 49 | fprintf(file, "BONUS_OBJ = $(BONUS_SRC:.c=.o)\n\n"); 50 | 51 | fprintf(file, "BONUS_SRC := $(addprefix $(SRCDIR)/, $(BONUS_SRC))\n"); 52 | fprintf(file, "BONUS_OBJ := $(addprefix $(OBJDIR)/, $(notdir $(BONUS_OBJ)))\n\n"); 53 | } 54 | 55 | /*** LIBFT DEFINE ***/ 56 | if (config->include_libft) 57 | { 58 | fprintf(file, "# Libft - Please configure your own path if different\n"); 59 | fprintf(file, "LIBFT_DIR := libft\n"); 60 | fprintf(file, "LIBFT := $(LIBFT_DIR)/libft.a\n"); 61 | fprintf(file, "LIBFT_INCLUDE := $(LIBFT_DIR)#/include \t\t#Your header file in include dir ?\n"); 62 | } 63 | 64 | /*** MINILIBX DEFINE ***/ 65 | if (config->include_mlx) 66 | { 67 | fprintf(file, "# MiniLibx -> Please include in header file: #include \"mlx.h\"\n"); 68 | fprintf(file, "MINILIBX_DIR := ./minilibx-linux\n"); 69 | fprintf(file, "MLX := $(MINILIBX_DIR)/libmlx.a\n"); 70 | } 71 | 72 | /*** LIBRAIRIES AND LINKER FLAGS DEFINE ***/ 73 | fprintf(file, "# Libraries and Linker Flags\n"); 74 | fprintf(file, "LDFLAGS = %s", 75 | (config->ldflags && strlen(config->ldflags) > 0) ? config->ldflags : ""); 76 | if (config->include_mlx) 77 | fprintf(file, " -L$(MINILIBX_DIR)"); 78 | if (config->include_libft) 79 | fprintf(file, " -L$(LIBFT_DIR)"); 80 | 81 | fprintf(file, "\nLIBS = %s", (config->libs && strlen(config->libs) > 0) ? config->libs : ""); 82 | if (config->include_mlx) 83 | fprintf(file, " $(MLX)"); 84 | if (config->include_libft) 85 | fprintf(file, " $(LIBFT)"); 86 | 87 | fprintf(file, "\n\n# Archiver\n"); 88 | fprintf(file, "AR = ar\n"); 89 | fprintf(file, "ARFLAGS = rcs\n"); 90 | 91 | /*** COMPILER AND FLAGS DEFINE ***/ 92 | fprintf(file, "\n# Compiler and Flags\n"); 93 | fprintf(file, "CC = %s\n", config->compiler); 94 | fprintf(file, "CFLAGS = %s -I$(INCDIR) -g3", config->cflags ? config->cflags : "-Wall -Wextra -Werror"); 95 | if (config->include_mlx) 96 | fprintf(file, " -I$(MINILIBX_DIR) -I/usr/include/X11"); 97 | if (config->include_libft) 98 | fprintf(file, " -I$(LIBFT_INCLUDE)"); 99 | 100 | if (config->include_mlx) 101 | { 102 | fprintf(file, "\n\n# Detect OS for Flags MiniLibx\n"); 103 | fprintf(file, "UNAME_S := $(shell uname -s)\n"); 104 | fprintf(file, "ifeq ($(UNAME_S),Linux)\n"); 105 | fprintf(file, "\tMLXFLAGS += -lmlx -lXext -lX11\n"); 106 | fprintf(file, "else ifeq ($(UNAME_S),Darwin)\n"); 107 | fprintf(file, "\tMLXFLAGS += -L/opt/X11/lib -lX11 -lXext -lXrandr -lXcursor\n"); 108 | fprintf(file, "endif\n"); 109 | } 110 | 111 | /*** SILENCE COMPILATION ***/ 112 | fprintf(file, "\n\n# Compilation mode (silent by default, set VERBOSE=1 to show commands)\n"); 113 | fprintf(file, "VERBOSE ?= 0\n"); 114 | fprintf(file, "ifeq ($(VERBOSE),1)\n"); 115 | fprintf(file, " V := \n"); 116 | fprintf(file, "else\n"); 117 | fprintf(file, " V := @\n"); 118 | fprintf(file, "endif\n\n"); 119 | 120 | /*** COLORS ***/ 121 | fprintf(file, "# Colors\n"); 122 | fprintf(file, "RED := \"\\033[1;31m\"\n"); 123 | fprintf(file, "GREEN := \"\\033[1;32m\"\n"); 124 | fprintf(file, "RESET := \"\\033[0m\"\n\n\n\n"); 125 | 126 | /*** DEFAULT | ALL RULE ***/ 127 | fprintf(file, "# Default Rule\n"); 128 | fprintf(file, "all: $(OBJDIR)"); 129 | if (config->include_mlx) 130 | fprintf(file, " $(MINILIBX_DIR)"); 131 | if (config->include_libft) 132 | fprintf(file, " $(LIBFT)"); 133 | fprintf(file, " $(NAME)"); 134 | 135 | /*** OBJECT DIR RULE ***/ 136 | fprintf(file, "\n\n# Object Directory Rule\n"); 137 | fprintf(file, "$(OBJDIR):\n"); 138 | fprintf(file, "\t$(V)mkdir -p $(OBJDIR) || true\n\n"); 139 | 140 | /*** DEPENDENCIES ***/ 141 | if (config->create_dependencies) 142 | { 143 | fprintf(file, "# Dependency Files\n"); 144 | fprintf(file, "DEP = $(OBJ:.o=.d)\n\n"); 145 | 146 | fprintf(file, "$(OBJDIR)/%%.o: $(SRCDIR)/%%.c | $(OBJDIR)\n"); 147 | fprintf(file, "\t@mkdir -p $(dir $@)\n"); 148 | fprintf(file, "\t$(V)$(CC) $(CFLAGS) -MMD -MP -c $< -o $@\n\n"); 149 | 150 | fprintf(file, "-include $(DEP)\n\n"); 151 | } 152 | 153 | /*** LINKING RULE ***/ 154 | fprintf(file, "# Linking Rule\n"); 155 | fprintf(file, "$(NAME): $(OBJ)"); 156 | if (config->src_file_bonus && strlen(config->src_file_bonus) > 0) 157 | fprintf(file, " $(BONUS_OBJ)"); 158 | if (config->include_libft) 159 | fprintf(file, " $(LIBFT)"); 160 | fprintf(file, "\n"); 161 | /* LIB */ 162 | if (config->create_lib_or_exec == 1) 163 | { 164 | fprintf(file, "\t$(V)$(AR) $(ARFLAGS) $@ $^\n"); 165 | fprintf(file, "\t$(V)echo $(GREEN)\"[$(NAME)] Library created ✅\"$(RESET)\n\n"); 166 | } 167 | /* EXEC */ 168 | else 169 | { 170 | fprintf(file, "\t$(V)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(BONUS_OBJ) $(LIBS) $(MLXFLAGS) -o $(NAME)\n"); 171 | fprintf(file, "\t$(V)echo $(GREEN)\"[$(NAME)] Executable created ✅\"$(RESET)\n\n"); 172 | } 173 | 174 | 175 | 176 | /*** USE Libft ***/ 177 | if (config->include_libft) 178 | { 179 | fprintf(file, "# Libft\n"); 180 | fprintf(file, "$(LIBFT):\n"); 181 | fprintf(file, "\t$(V)$(MAKE) --silent -C $(LIBFT_DIR)\n"); 182 | fprintf(file, "\t$(V)echo '[$(NAME)] Libft build successfully'\n\n"); 183 | } 184 | /*** USE MiniLibX ***/ 185 | if (config->include_mlx) 186 | { 187 | fprintf(file, "# MiniLibX\n"); 188 | fprintf(file, "$(MINILIBX_DIR):\n"); 189 | fprintf(file, "\t$(V)echo '[$(NAME)] Downloading MiniLibX from github.com...'$(RESET)\n"); 190 | fprintf(file, "\t@git clone https://github.com/42Paris/minilibx-linux.git $(MINILIBX_DIR) > /dev/null 2>&1\n"); 191 | fprintf(file, "\t$(V)echo '[$(NAME)] Compiling MiniLibX...'$(RESET)\n"); 192 | fprintf(file, "\t@$(MAKE) -C $(MINILIBX_DIR) > /dev/null 2>&1\n"); 193 | fprintf(file, "\t$(V)echo '[$(NAME)] MiniLibX installed successfully'$(RESET)\n\n"); 194 | } 195 | 196 | /*** BONUS RULE ***/ 197 | if (config->src_file_bonus && strlen(config->src_file_bonus) > 0) 198 | fprintf(file, "bonus: $(OBJDIR) $(BONUS_OBJ) $(NAME)\n"); 199 | 200 | 201 | /*** CLEAN RULES ***/ 202 | fprintf(file, "# Clean Rules\n"); 203 | fprintf(file, "clean:\n"); 204 | fprintf(file, "\t$(V)echo $(RED)'[$(NAME)] Cleaning objects'd$(RESET)\n"); 205 | fprintf(file, "\t$(V)rm -rf $(OBJDIR)\n\n"); 206 | 207 | fprintf(file, "fclean: clean\n"); 208 | fprintf(file, "\t$(V)echo $(RED)'[$(NAME)] Cleaning all files'$(RESET)\n"); 209 | fprintf(file, "\t$(V)rm -f $(NAME)\n"); 210 | if (config->include_libft) 211 | fprintf(file, "\t$(V)$(MAKE) --silent -C $(LIBFT_DIR) fclean\n"); 212 | if (config->include_mlx) 213 | { 214 | fprintf(file, "\t$(V)echo $(RED)'[mlx] Remove directory'$(RESET)\n"); 215 | fprintf(file, "\t@rm -rf $(MINILIBX_DIR)\n"); 216 | } 217 | 218 | fprintf(file, "\nre: fclean all\n\n"); 219 | 220 | 221 | /*** REGEN RULES ***/ 222 | fprintf(file, "# Makefile Reconfiguration \n"); 223 | fprintf(file, "regen:\n"); 224 | fprintf(file, "\tmakemyfile\n\n"); 225 | 226 | /*** PHONY ***/ 227 | fprintf(file, ".PHONY: all clean fclean re bonus regen\n"); 228 | fprintf(file, ".DEFAULT_GOAL := all\n"); 229 | 230 | fclose(file); 231 | } 232 | --------------------------------------------------------------------------------