{"id":13460037,"url":"https://github.com/Nuno-Jesus/Make-A-Make","last_synced_at":"2025-03-24T18:32:52.207Z","repository":{"id":176108311,"uuid":"648253885","full_name":"Nuno-Jesus/Make-A-Make","owner":"Nuno-Jesus","description":"Clear the fog around Makefiles with this Makefile tutorial and enhance your knowledge with advanced tips and concepts.","archived":false,"fork":false,"pushed_at":"2023-12-30T16:37:45.000Z","size":509,"stargazers_count":127,"open_issues_count":3,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-29T06:33:19.771Z","etag":null,"topics":["42","42born2code","42cursus","42porto","42projects","42school","c","compilation","makefile","makefile-syntax"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Nuno-Jesus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-01T14:44:23.000Z","updated_at":"2024-10-28T16:02:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"fbc91083-d2b9-4991-9946-414a46c52190","html_url":"https://github.com/Nuno-Jesus/Make-A-Make","commit_stats":null,"previous_names":["nuno-jesus/make-a-make"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nuno-Jesus%2FMake-A-Make","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nuno-Jesus%2FMake-A-Make/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nuno-Jesus%2FMake-A-Make/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nuno-Jesus%2FMake-A-Make/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Nuno-Jesus","download_url":"https://codeload.github.com/Nuno-Jesus/Make-A-Make/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245328462,"owners_count":20597427,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["42","42born2code","42cursus","42porto","42projects","42school","c","compilation","makefile","makefile-syntax"],"created_at":"2024-07-31T10:00:34.424Z","updated_at":"2025-03-24T18:32:51.849Z","avatar_url":"https://github.com/Nuno-Jesus.png","language":"C","funding_links":[],"categories":["WELCOME"],"sub_categories":["**Libft**"],"readme":"# Makefile Tutorial\n\n## Description\nThis README was developed mainly to help 42 students to clear the fog around Makefiles and how they work. But, it will be for sure helpful to anyone out there struggling as well. \n\nIt starts with a beginner's guide, followed up by some medium-advanced concepts.\n\n## \u003ca name=\"index-0\"\u003eIndex\u003c/a\u003e\n\u003cul\u003e\n\t\u003cli\u003e\u003cstrong\u003e\u003ca href=\"#beginners-guide\" style=\"color:white\"\u003eBeginner's Guide\u003c/a\u003e\u003c/strong\u003e\u003c/li\u003e\n\t\u003cul style=\"list-style-type:disc\"\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-1\"\u003e1. What is make?\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-2\"\u003e2. An introduction to Makefiles\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-3\"\u003e3. Rules\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-4\"\u003e4. A simple Makefile\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-4.1\"\u003e4.1 Dependencies and rule processing\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-5\"\u003e5. Variables\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-6\"\u003e6. Automatic Variables\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#index-7\"\u003e7. Towards a more flexible Makefile\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cul style=\"list-style-type:disc\"\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#index-7.1\"\u003e7.1. Removing more redundancy\u003c/a\u003e\u003c/li\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#index-7.2\"\u003e7.2. Implicit Rules\u003c/a\u003e\u003c/li\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#index-7.3\"\u003e7.3. Implicit Variables\u003c/a\u003e\u003c/li\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#index-7.4\"\u003e7.4. Relinking\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\u003c/ul\u003e\n\t\u003cli\u003e\u003cstrong\u003e\u003ca href=\"#advanced-guide\" style=\"color:white\"\u003eAdvanced Topics\u003c/a\u003e\u003c/strong\u003e\u003c/li\u003e\n\t\u003cul style=\"list-style-type:disc\"\u003e\n\t\t\u003cli\u003e\u003ca href=\"#conditionals\"\u003eA1 - Conditional Directives\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#mmd-flag\"\u003eA2 - The MMD flag\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#command-line\"\u003eA3 - Command-line variables\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#functions\"\u003eA4 - Functions\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cul style=\"list-style-type:disc\"\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#functions-1\"\u003eA4.1 - Functions Call Syntax\u003c/a\u003e\u003c/li\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#functions-2\"\u003eA4.2 - Functions for String Manipulation\u003c/a\u003e\u003c/li\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#functions-3\"\u003eA4.3 - Functions for File Names\u003c/a\u003e\u003c/li\u003e\n\t\t\t\u003cli\u003e\u003ca href=\"#functions-4\"\u003eA4.4 - Functions for Generic Purposes\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#vpath\"\u003eA5 - The vpath directive\u003c/a\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\t\u003c!-- \u003cli\u003eTips and tricks\u003c/li\u003e\n\t\u003cul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#organize-project\"\u003eOrganize your project with vpath\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#variable-operators\"\u003eOther variable related operators\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#activate-debug\"\u003eActivate debug commands/flags with conditionals\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#general-tips\"\u003eGeneral tips\u003c/a\u003e\u003c/li\u003e\n\t\u003c/ul\u003e --\u003e\n\t\u003cli\u003e\u003cstrong\u003e\u003ca href=\"#useful-topics\" style=\"color:white\"\u003eUseful Topics\u003c/a\u003e\u003c/strong\u003e\u003c/li\u003e\n\t\u003cul style=\"list-style-type:disc\"\u003e\n\t\t\u003cli\u003e\u003ca href=\"#special-targets\"\u003eSpecial Targets\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#flags\"\u003eMakefile Flags\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#errors\"\u003eGood-to-know Errors\u003c/a\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\u003c/ul\u003e\n\n\n------------------------------------------------------------------\n\n\n# \u003ca name=\"beginners-guide\"\u003eBeginner's Guide\u003c/a\u003e\n\n## \u003ca name=\"index-1\"\u003e1. What is make?\u003c/a\u003e\nThe `make` utility is an automatic tool capable of deciding which commands can / should be executed. The `make` utility is mostly used to automate the compilation process, preventing manual file-by-file compilation. This utility is used through a special file called `Makefile`.\n\nFor this guide, we'll only dispose of a C project.\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"index-2\"\u003e2. An introduction to Makefiles\u003c/a\u003e\nTypically, a Makefile is called to handle the compilation and linking of a project and its files. The Makefile uses the modification times of participating files to assert if re-compilation is needed or not.\n\nFor instance, when compiling a `C` project, the final executable file, would be the zipped version of every `.o` file, which was in turn created from the `.c` files.\n\nLet's create a simple project to work with.\n\n\t├── hello.c \n\t├── main.c\n\t└── Makefile\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"index-3\"\u003e3. Rules\u003c/a\u003e\nRules are the core of a Makefile. Rules define how, when and what files and commands are used to achieve the final executable.\n\nA rule has the following syntax:\n\n```Makefile\ntarget: prerequisite-1 prerequisite-2 prerequisite-3 ...\n\tcommand-1\n\tcommand-2\n\tcommand-3\n\t...\n```\n\n- A `target` is the name of a rule. Usually, also the name of a file, but not always.\n\n- A rule can rely on dependencies that must be fulfilled before execution. These are called `prerequisites`. Details of prerequisite parsing will be detailed in 4.1 section. \n\n- Finally, after the prerequisites are fulfilled, the rule can execute its `recipe`, a collection of `commands`. A rule can also have an empty recipe.\n\nEach command should be indented with a **tab** otherwise, an error like this might show up:\n\n\tMakefile:38: *** missing separator.  Stop.\n\nHere's an example of a rule that attempts to generate a `hello.o` file from a `hello.c` file:\n\n```Makefile\nhello.o: hello.c\n\tclang -c hello.c\n```\n\nAs told before, some rules don't need dependencies.\nThe `clean` rule is used to clean temporary files. Those would be the object files in a C project:\n\n```Makefile\nclean:\n\trm -rf hello.o\n```\n\nYou can also have a similar rule to clean both object files and the executable:\n\n```Makefile\nfclean: clean\n\trm -rf a.out\n```\n\nFinally, if you're lazy like me and need to re-compile everything, you might want to create a rule to clean and re-compile:\n\n```Makefile\nre: fclean\n\t$(MAKE) all\n```\n\n\u003e [!Note]\n\u003e `$(MAKE)` is a variable which expands to `make`. We'll see more about variables up ahead.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"index-4\"\u003e4. A simple Makefile\u003c/a\u003e\nThe Makefile below is capable of compiling our example project. You can find it in the [code/01-start-example](/code/01-start-example/) folder.\n\n```Makefile\nhello.o: hello.c\n\tcc -c hello.c\n\nall: hello.o\n\tcc main.c hello.o\n\nclean:\n\trm -rf hello.o\n\nfclean: clean\n\trm -rf a.out\n\nre: fclean\n\t$(MAKE) all\n```\n\nHere's an image to display the dependencies in a more organized way:\n\u003cdiv align=center\u003e\n\t\u003cimage src=images/graph_1.png\u003e\n\u003c/div\u003e\n\nIn the terminal, run:\n\n\tmake \u003ctarget\u003e\n\n...where `\u003ctarget\u003e` is a list of targets you want to run. In this case, we need both `main.c` and `hello.c` file to be compiled, so you can run:\n\n\tmake all\n\n\u003e [!Warning]\n\u003e If the `\u003ctarget\u003e` field is ommited, the Makefile will execute the first rule. And yes, this example is not doing that, the primary rule should be 'all'.\n\nYou should see something like this on the terminal:\n\n\tcc -c hello.c\n\tcc main.c hello.o\n\nThis is great! The compilation worked out and finally, we can execute our program and use our `hello` function! But what if one wanted to compile `N` more files? Would they need to create `N` more rules?\n\n\n### \u003ca name=\"index-4.1\"\u003e4.1. Dependencies and rules processing\u003c/a\u003e\nConsider a portion of the previous Makefile:\n\n```Makefile\nall: hello.o\n\tcc main.c hello.o\n\nhello.o: hello.c\n\tcc -c hello.c\n```\n\nThe `make` command will read the current Makefile and process the first rule. Before executing `all` it must process `hello.o` since it is a dependency.\n\nThe recompilation of the `hello.o` must be done if either `hello.o` does not exist or `hello.c` was changed since the last `hello.o` file was created. At first, there is no `hello.o` file, so it must be generated.\n\nNow suppose `hello.c` had recent changes. That means `hello.o` would have to be recompiled. Therefore, the `all` target would have to be remade because `hello.o` is newer than the final executable.\n\nHere's a summary:\n\n\tIs hello.o an existent file?\n\t\tYes: Was hello.c modified since the last build?\n\t\t\tYes: Remake hello.o\n\t\t\tNo: Do nothing for hello.o\n\t\tNo: Is there a rule to remake hello.o?\n\t\t\tYes: Remake hello.o\n\t\t\tNo: Error: no rule to make hello.o\n\tExecute cc main.c hello.o\n\n\u003cdiv align=center\u003e\n\t\u003cimage src=images/graph_3.png\u003e\n\u003c/div\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"index-5\"\u003e5. Variables\u003c/a\u003e\nSimilar to programming languages, the Makefile syntax allows you to define variables.\n\nVariables are useful because:\n- allows you to focus your changes on one place;\n- prevents the repetition of values across the Makefile (which are much more error-prone)\n\nVariables can only be strings (a single one or a list of strings). Here are some examples:\n\n```Makefile\nFIRST_NAMES = Nuno Miguel \t\t\t\t\nLAST_NAMES  = Carvalho de Jesus\nFULL_NAME   = $(FIRST_NAMES) $(LAST_NAMES) # Nuno Miguel Carvalho de Jesus\n```\n\n\u003e [!Note]\n\u003e The naming convention for variables is uppercase, to distinguish from Makefile rules.\n\nYou can use variables in rules and other variables as well. To access their values, you must use:\n\n\t$(FIRST_NAME)\n\nor \n\n\t${FIRST_NAME}\n\nLet's add a few files to our project:\n\n\t├── bye.c \n\t├── hello.c \n\t├── highfive.c \n\t├── main.c\n\t└── Makefile\n\nA naive solution would be to create more rules. You can find the code in the [code/02-naive-example](/code/02-naive-example/) folder:\n\n```Makefile\nall: hello.o bye.o highfive.o\n\tcc main.c hello.o bye.o highfive.o\n\nhello.o: hello.c\n\tcc -c hello.c\n\nbye.o: bye.c\n\tcc -c bye.c\n\nhighfive.o: highfive.c\n\tcc -c highfive.c\n```\n\nThis would be the new dependency graph:\n\u003cdiv align=center\u003e\n\t\u003cimage src=images/graph_2.png\u003e\n\u003c/div\u003e\n\nBut this is ugly and unnecessary since the pattern is always the same. Let us use the newly learn variables to clean this up! You can find the code in the [code/03-variables-example](code/03-variables-example/) folder:\n\n```Makefile\nOBJS = hello.o bye.o highfive.o # Dependency list of the 'all' rule\n\nall: $(OBJS)\n\tcc main.c $(OBJS)\n\n%.o: %.c\n\tcc -c $\u003c\n\nclean:\n\trm -rf $(OBJS)\n\n...\n```\n\n\u003e [!Note]\n\u003e Have you have ever run `make -p \u003e logs` ? Neither did I, but it's pretty useful! Detailed explanation on this in an upcoming section.\n\nOk, pause. I know this is a lot to take in. Let's look into the details.When running `make`:\n\n**1.** The `all` rule is chosen by default:\n\n```Makefile\nall: $(OBJS)\n\tcc main.c $(OBJS)\n```\n\n**2.** The `OBJS` variable is expanded its values, creating multiple dependencies:\n\n```Makefile\nall: hello.o bye.o highfive.o\n\tcc main.c $(OBJS)\n```\n\n**3.** In the first compilation, the `hello.o` file doesn't exist. The dependency must then be remade, which forces the Makefile to look for a rule:\n\n```Makefile\n%.o: %.c\n\tcc -c $\u003c\n```\n\nThe `%` can be used in several cases. For this one, it's used to represent a **Regular Expression (REGEX)**. You can read it as \"any dependency that ends on `.o` can be generated here and needs a corresponding `.c` dependency with the same prefix\". For `hello.o` we have:\n\n```Makefile\nhello.o: hello.c\n\tcc -c $\u003c # The $\u003c expands to the first dependency of this rule (hello.c)\n```\n\nThe same goes for other dependencies having a `.o` suffix. The `$\u003c` is an **Automatic Variable**. We'll talk more about Automatic Variables up ahead. Specifically, this one is used to handle strings with variable values, since the value of the dependency is not always the same. Final expansion:\n\n```Makefile\nhello.o: hello.c\n\tcc -c hello.c\n```\n\n**4.** Finally, after all dependencies are generated following the same pattern as before, the `all` rule can execute the recipe. The `OBJS` variable is expanded again to its values:\n\n```Makefile\nall: hello.o bye.o highfive.o\n\tcc main.c hello.o bye.o highfive.o\n```\n\nHere's what we have so far:\n\n```Makefile\nOBJS = hello.o bye.o highfive.o # Dependency list of the 'all' rule\n\nall: $(OBJS)\n\tcc main.c $(OBJS)\n\n%.o: %.c\n\tcc -c $\u003c\n\nclean:\n\trm -rf $(OBJS)\n\nfclean: clean\n\trm -rf a.out\n\nre: fclean\n\t$(MAKE) all\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"index-6\"\u003e6. Automatic variables\u003c/a\u003e\nAutomatic variables are special variables used by the Makefile to dynamically compute values. In other words, you can use those, when a rule does not always have the same dependency or target name, like in the example above.\n\nBelow, is a table of some of the most useful ones:\n\n\u003cdiv\u003e\n\t\u003ctable align=center width=100%\u003e\n\t\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\u003ctd align=center\u003e\u003cstrong\u003eVariables\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\u003ctd align=center\u003e\u003cstrong\u003eDescription\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\u003c/thead\u003e\n\t\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\u003ctd align=center\u003e\u003ccode\u003e$@\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\u003ctd\u003eThe name of a target rule\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\u003ctd align=center\u003e\u003ccode\u003e$\u003c\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\u003ctd\u003eThe name of the first prerequisite\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\u003ctd align=center\u003e\u003ccode\u003e$^\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\u003ctd\u003eThe name of all prerequisites, separated by spaces\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\u003ctd align=center\u003e\u003ccode\u003e$*\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\u003ctd\u003eThe current target name with its suffix deleted\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\u003c/tbody\u003e\n\t\u003c/table\u003e\n\u003c/div\u003e\n\nYou can find the code in the [code/04-automatic-variables-example](/code/04-automatic-variables-example/) folder:\n```Makefile\nall: lib.a this.example\n\nlib.a: hello.o bye.o highfive.o\n\techo $@ # Prints \"lib.a\"\n\techo $\u003c # Prints \"hello.o\"\n\techo $^ # Prints \"hello.o bye.o highfive.o\"\n\t$(AR) lib.a $^\n\n%.example:\n\techo $* # Prints \"this\"\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"index-7\"\u003e7. Towards a more flexible Makefile\u003c/a\u003e\n\nWe are reaching the end of the tutorial! This section is all about polishing what we've developed so far. There will be (much) more content after this section, but it's up to you to go further. \n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n### \u003ca name=\"index-7.1\"\u003e7.1. Removing more redundancy\u003c/a\u003e\nNow that the basics are settled (at least they should be), let's have a look at some details. Noticed how the `rm -rf` and the `cc` commands are repeating? We can place them in variables:\n\n```Makefile\nCC      = cc\nRM      = rm -rf\nOBJS\t= hello.o bye.o highfive.o\n\nall: $(OBJS)\n\t$(CC) main.c $(OBJS)\n\n%.o: %.c\n\t$(CC) -c $\u003c\n\nclean:\n\t$(RM) $(OBJS)\n\nfclean: clean\n\t$(RM) a.out\n\nre: fclean\n\t$(MAKE) all\n```\n\nAfter a few hours, you realized your code is not that clean and you need a more secure compilation (compilation flags). You also want to name your executable `project`. For both situations, we can define variables to avoid unnecessary repetition. You can find the code in the [code/05-redundancy-example](/code/05-redundancy-example/) folder.\nHere are the new changes:\n\n```Makefile\nCC      = cc\nCFLAGS\t= -Wall -Werror -Wextra\nRM      = rm -rf\nNAME\t= project\nOBJS\t= hello.o bye.o highfive.o\n\nall: $(OBJS)\n\t$(CC) $(CFLAGS) main.c $(OBJS) -o $(NAME)\n\n%.o: %.c\n\t$(CC) $(CFLAGS) -c $\u003c\n\n...\n\nfclean: clean\n\t$(RM) $(NAME)\n\n```\n\n\u003e [!Note]\n\u003e The `-o` flag signals the compiler, to specify the name the executable will have.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n### \u003ca name=\"index-7.2\"\u003e7.2. Implicit Rules\u003c/a\u003e\nHave you tried to remove the `%.o: %.c` rule and run `make`? You'll soon find the Makefile is still working. But how? Makefile has its own default rules defined for specific cases, like the ones you'll see below.\nYou can define your own implicit rules by using pattern rules (just like we did before).\n\n**Implicit Rules**, also use **Implicit Variables**, which you can check in the next section. Here are some of the implicit rules:\n\n\u003ctable align=center width=100%\u003e\n\t\u003cthead\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd align=center\u003e\u003cstrong\u003ePurpose\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003ctd align=center\u003e\u003cstrong\u003eRule\u003c/strong\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\u003ctr align=center\u003e\n\t\t\t\u003ctd\u003eCompiling C\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e$(CC) $(CPPFLAGS) $(CFLAGS) -c\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr align=center\u003e\n\t\t\t\u003ctd\u003eCompiling C++\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr align=center\u003e\n\t\t\t\u003ctd\u003eGenerating .a\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e$(AR) $(ARFLAGS) $@ $\u003c\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n### \u003ca name=\"index-7.3\"\u003e7.3. Implicit Variables\u003c/a\u003e\nAs told before, implicit rules rely on variables already known by the Makefile, set with a default value: **Implicit Variables**. You can redefine the value for these variables. Even if you don't use them explicitly, these new values can be used by implicit rules. Here's a table of some of them:\n\n\n\u003ctable align=center width=100%\u003e\n\t\u003cthead\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd align=center\u003e\u003cstrong\u003eName\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003ctd align=center\u003e\u003cstrong\u003eDefault value\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003ctd align=center\u003e\u003cstrong\u003ePurpose\u003c/strong\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eAR\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003ear\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eThe command used to create archives, \u003ccode\u003e.a\u003c/code\u003e files\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eARFLAGS\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e-rv\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eUsed flags when \u003ccode\u003eAR\u003c/code\u003e command is issued\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eCC\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003ecc\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eThe default compiler to use when C compilation is required. The cc is not a compiler, but rather an alias to the default C compiler of your machine (either \u003ccode\u003egcc\u003c/code\u003e or \u003ccode\u003eclang\u003c/code\u003e)\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eCFLAGS\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eUsed flags when \u003ccode\u003eCC\u003c/code\u003e command is issued\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eCXX\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eg++\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eThe default compiler to use when C compilation is required.\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eCXXFLAGS\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eUsed flags when \u003ccode\u003eCC\u003c/code\u003e command is issued\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eCPPFLAGS\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eExtra flags used when \u003ccode\u003eCC or CXX\u003c/code\u003e commands are issued. \u003ccode\u003eCPPFLAGS\u003c/code\u003e and \u003ccode\u003eCFLAGS\u003c/code\u003e might appear the same, but this one was designed to contain include flags to help the compiler to locate missing header files. But you are free to override this as you want.\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eRM\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003erm -f\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eThe command to be used to permanently delete a file\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eMAKE\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003emake\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eUseful when multi-jobs of Makefile come into play. This will be explained later in detail in an upcoming section, but keep in mind this is the best way of calling make targets inside the Makefile\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003eMAKEFLAGS\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003e\u003ccode\u003e\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003ctd\u003eThe flags given to make.\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n### \u003ca name=\"index-7.4\"\u003e7.4. Relinking\u003c/a\u003e\nTo wrap up this simple tutorial, I would like you to run `make` several times. Have you noticed how the `main.c` and `.o` files are getting linked together, even though they haven't changed? This is a phenomenon called **relinking**.\n\nAlthough it might not seem that important, considering a large-scale project, relinking can cause unnecessary and larger compilation times. To avoid it, we can add as a dependency the executable file you are trying to create, like this:\n\n```Makefile\n...\n\nNAME = project\nall: $(NAME)\n\n$(NAME): $(OBJS)\n\t$(CC) $(CFLAGS) main.c $(OBJS) -o $(NAME)\n\n...\n```\nYou can find the code in the [code/06-relinking-example](/code/06-relinking-example/) folder.\nThis version does the same job as before. The main difference lies in the new dependency of `all`. The first compilation will assert the project executable is not a file, so it must be remade through the `$(NAME)` rule. In the second run, however, since the `project` file was created before, the dependency is fulfilled and the Makefile directly attempts to execute the `all` recipe. Since it's empty and no other recipes were run, you'll get this message\n\n\tmake: Nothing to be done for 'all'.\n\nAnd there you have it! I hope this beginner's guide cleared a bit of your doubts. If you're not a beginner (or don't want to be one anymore), I advise you to check the contents up ahead. Many of those might be useful to change and upgrade your Makefiles!\n\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n# \u003ca name=\"advanced-guide\"\u003eAdvanced Topics\u003c/a\u003e\n\n## \u003ca name=\"conditionals\"\u003eA1 - Conditional Directives\u003c/a\u003e\n\nConditionals are directives that `make` should obey or ignore, depending on string values. Conditionals always use strings, either from variables or constant strings.\n\nThis is the general syntax for a conditional:\n\n```Makefile\nconditional-directive-one\n\ttext-if-one-is-true\nelse conditional-directive-two\n\ttext-if-two-is-true\n...\nelse\n\ttext-if-all-above-are-false\nendif\n```\n\nJust like in `C`, conditionals either evaluate to true or false. In the block above, if `conditional-directive-one` is true, `text-if-one-is-true` is \"obeyed\", and the rest is ignored. Otherwise, the second conditional is tested and so on, until reaching the `else` directive (may be present or not). \n\nAlso, conditionals must always end in an `endif` directive.\n\nConsider the following example, saved on [code/11-conditionals-example](code/11-conditionals-example).\n\n```Makefile\nVAR1 = Nuno Jesus#The variable ends here\nVAR2 = Nuno Jesus #The variable ends here\n\nall:\nifeq ($(VAR1), Nuno Jesus)\n\t@echo \"VAR1 contains my name\"\nelse\n\t@echo \"VAR1 does not contain my name\"\nendif\n\nifeq ($(VAR2), Nuno Jesus)\n\t@echo \"VAR2 contains my name\"\nelse\n\t@echo \"VAR2 does not contain my name\"\nendif\n```\n\n\u003e [!Warning]\n\u003e The directives **cannot** be indented inside a recipe, otherwise `make` will consider those as commands and will attempt to execute them.\n\nWe are currently making use of 3 directives:\n\n`ifeq` - after expansion of `VAR1`, compares all the inner strings with the right field. If any string dont't match, the comparison is evaluated to false.\n- `else` - if the `ifeq` directive evaluates to false, the lines below the `else` directive are obeyed.\n- `endif` - marks the end of the conditional.\n\nThis outputs the following:\n```shell\nVAR1 contains my name\nVAR2 does not contain my name\n```\n\nAlthough `VAR1` and `VAR2` are very similar, `VAR2` ends in space! It was more than enough to assert an inequality between the 2 values. On the other hand, the first conditional evaluates to true, because all strings from `VAR1` match the strings on the right side. Note that **leading whitespaces are ignored, but trailing spaces are not**.\n\n\u003e [!Note]\n\u003e You can use the `strip` built-in makefile function to remove extra whitespaces.\n\nConditionals determine which parts of the `Makefile` should be excluded or included before the building process begins.\n\nExpansion of variables occurs as usual. However, **automatic variables cannot be used to test conditionals, since their values are only known in the building process**. \n\nThe animation below demonstrates how conditionals behave.\n\n![Conditionals](https://github.com/Nuno-Jesus/Make-A-Make/assets/93390807/0c23ea0e-d3f3-4cc6-85fb-872fd86126b0)\n\n\u003e [!Note]\n\u003e Quotes are only used to detail the extra space.\n\nThere are 4 different conditional directives. Here's a list:\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eifeq\u003c/h4\u003e\u003c/summary\u003e\n\u003cpre\u003e\nifeq (ARG1, ARG2)\n\t...\nendif\n\u003c/pre\u003e\nBoth \u003ccode\u003eARG1\u003c/code\u003e and \u003ccode\u003eARG2\u003c/code\u003e are expanded. If all strings are identical, the directive evaluates to true - false otherwise.\n\nFor example:\n\n```Makefile\nVAR = 0\n\nall: \nifeq ($(VAR), 0)\n\t@echo VAR=0.\nelse ifeq ($(VAR), 1)\n\t@echo VAR=1.\nelse\n\t@echo This not binary!\nendif\n```\n\nOutput: \n\n\u003cpre\u003e\nVAR=0\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eifneq\u003c/h4\u003e\u003c/summary\u003e\n\u003cpre\u003e\nifneq (ARG1, ARG2)\n\t...\nendif\n\u003c/pre\u003e\nBoth \u003ccode\u003eARG1\u003c/code\u003e and \u003ccode\u003eARG2\u003c/code\u003e are expanded. If any of the strings is different, the directive evaluates to true - false otherwise.\n\nFor example:\n\n```Makefile\nVAR1 = 1 2 3 4 5\nVAR2 = 1 2 3 4 0\n\nall: \nifneq ($(VAR1), $(VAR2))\n\t@echo $(VAR1) != $(VAR2)\nelse\n\t@echo $(VAR1) = $(VAR2)\nendif\n```\n\nOutput:\n\n\u003cpre\u003e\n1 2 3 4 5 != 1 2 3 4 0\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eifdef\u003c/h4\u003e\u003c/summary\u003e\n\u003cpre\u003e\nifdef VARIABLE-NAME\n\t...\nendif\n\u003c/pre\u003e\n\nTakes the name of a variable (not its value), although it can receive a variable that expands to the name of another variable. If `VARIABLE-NAME` isn't an empty string, the conditional evaluates to true - false otherwise. **Undefined variables have an empty value by default.**\n\nFor example:\n\n```Makefile\nVAR = Nuno\n\nall: \nifdef VAR\n\t@echo VAR=$(VAR).\nelse\n\t@echo VAR is not defined.\nendif\n\nifdef WHAT\n\t@echo WHAT=$(WHAT).\nelse\n\t@echo WHAT is not defined.\nendif\n```\n\nOutput:\n\n\u003cpre\u003e\nVAR=Nuno\nWHAT is not defined.\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eifndef\u003c/h4\u003e\u003c/summary\u003e\n\u003cpre\u003e\nifndef VARIABLE-NAME\n\t...\nendif\n\u003c/pre\u003e\n\nTakes the name of a variable (not its value), although it can receive a variable that expands to the name of another variable. If `VARIABLE-NAME` is an empty string, the conditional evaluates to true. **Undefined variables have an empty value by default.**\n\nFor example:\n\n```Makefile\nifndef CFLAGS \n\tCFLAGS = -Wall -Werror -Wextra\nendif\n\nall:\n\t@echo You are using CFLAGS=-Wall -Werror -Wextra\n```\n\nOutput:\n\n\u003cpre\u003e\nYou are using CFLAGS=-Wall -Werror -Wextra\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"mmd-flag\"\u003eA2 - The MMD flag\u003c/a\u003e\n\nMost likely, your Makefile was designed to remake whenever a `.c` file changes. But what if a `.h` changes?\n\nConsider the following files, saved on [code/12-headers-example/](code/12-headers-example/) ...\n\n\t12-headers-example\n\t\t├── header.h \n\t\t├── main.c\n\t\t└── Makefile\n\n\n... where `header.h` and `main.c` are displayed below.\n\n```C\n// header.h\n#ifndef HEADER_H\n# define HEADER_H\n# include \u003cstdio.h\u003e\n\n# define NUMBER 42\n\n#endif\n```\n\n```C\n// main.c\n#include \"header.h\"\n\nint main()\n{\n\tprintf(\"This is the number: %d\\n\", NUMBER);\n\treturn 0;\n}\n```\n\nThe Makefile is initially designed like this:\n\n```Makefile\n###################### Compilation ######################\nCC      \t= cc\nCFLAGS\t\t= -Wall -Werror -Wextra\n\n######################## Commands #######################\nRM = rm -rf\n\n######################### Files #########################\nNAME = a.out\nOBJS = main.o\n\nall: $(NAME)\n\n$(NAME): $(OBJS)\n\t$(CC) $(CFLAGS) $(OBJS) -o $(NAME)\n\nclean:\n\t$(RM) $(OBJS)\n\nfclean: clean\n\t$(RM) $(NAME)\n\nre: fclean\n\t$(MAKE) all\n```\n\nRunning `make` builds `a.out`, which outputs the following when executed:\n\n```sh\nThis is the number: 42\n```\n\nWhat if you were to change the `NUMBER` macro to `24`? Have you tried to `make` and run `a.out` after? To your surprise, the output is exacly the same. Why?\n\nWell, as I explained in section [4.1](#index-4.1), `make` will remake a target if it notices its dependencies have a newer version. So, our Makefile cannot rely on the dependencies it doesn't know about, like `header.h`.\n\nA naive solution would be to add `header.h` as a dependency to `$(NAME)`:\n\n```Makefile\n...\n######################### Files #########################\nNAME \t\t= a.out\nOBJS \t\t= main.o\nHEADERS\t\t= header.h\n\nall: $(NAME)\n\n$(NAME): $(OBJS) $(HEADERS)\n\t$(CC) $(CFLAGS) $(OBJS) -o $(NAME)\n...\n```\n\nIt does fix the issue, but it's only a band-aid. We have yet another issue:\n\nChanging `header.h` only forces the final linking of all object files...\n\n```sh\ncc  -Wall -Werror -Wextra main.o -o a.out\n```\n\n..., but it won't force the recompilation of `.c` files.\n\n\nWe could manually add a rule that specifies what files `main.o` depends on, which also solves the issue, but this is not very scalable.\n\nTo automate this process, we can use the `-MMD` compilation flag which generates a micro-makefile with a `.d` extension for each `.c`.\n\nBy adding `-MMD` and running `make`, ...\n\n```Makefile\n###################### Compilation ######################\nCC      \t= cc\nCFLAGS\t\t= -Wall -Werror -Wextra\nCPPFLAGS\t= -MMD\n\n...\n\nall: $(NAME)\n\n$(NAME): $(OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $(OBJS) -o $(NAME)\n...\n```\n\n...`main.d` is generated, with the following contents:\n\n```Makefile\nmain.o: main.c header.h\n```\n\nGreat! Now, we just need to **include** the `.d` files in our Makefile. You can use the `include` directive:\n\n```Makefile\n...\n\n######################### Files #########################\nNAME \t\t= a.out\nOBJS \t\t= main.o\nDEPS\t\t= $(OBJS:.o=.d)\n\nall: $(NAME)\n\n$(NAME): $(OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $(OBJS) -o $(NAME)\n\n-include $(DEPS)\t\n\n...\n```\n\n\u003e [!Note]\n\u003e The `-` prefix in the `include` directive prevents make from quitting if an included file doesn't exist.\n\nBefore the building process begins, the Makefile will look for the included files and try to append them, just like the animation below demonstrates:\n\n![MMD](https://github.com/Nuno-Jesus/Make-A-Make/assets/93390807/fb790d73-98ee-4617-9343-d17facf33edd)\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"command-line\"\u003eA3 - Command-line variables\u003c/a\u003e\n\nJust like `argv` in C, `make` allows you to declare variables when running the `make` command. Let's assume we want a variable called `DEBUG` to be declared this way. We can write:\n\n```sh\nmake DEBUG=1\n```\n\nGeneral syntax for variable declaration:\n\n```sh\nmake variable-name=variable-value\n```\n\nThe `=` is mandatory, as `make` would consider `DEBUG` as another target to make otherwise. Remember that, if the `variable-value` is empty, the variable is considered undefined. **Assigning a new value to an existent variable overrides its old value.**\n\nHere's an example that prints the value of the `DEBUG` variable. You can find the code in [code/14-command-line-example](code/14-command-line-example):\n\n```Makefile\nDEBUG =\n\nall:\n\t@echo Compiling with DEBUG=$(DEBUG)\n```\n\n```shell\n➜  14-command-line-example git:(advanced-topics) ✗ make DEBUG=-g\nCompiling with DEBUG=-g\n➜  14-command-line-example git:(advanced-topics) ✗ \n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"functions\"\u003eA4 - Functions\u003c/a\u003e\n\nThis starts to look a lot like C right? Now we have functions and they are very similar! Functions take parameters that are processed depending on the behavior of the function. The result of that function is later returned and replaced wherever the function call happened.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n### \u003ca name=\"functions-1\"\u003eA4.1 - Functions Call Syntax\u003c/a\u003e\n\nFunction calls can appear anywhere a variable can. Function calls resemble a variable reference:\n\n```Makefile\n$(function arguments)\n```\n\nor \n\n```Makefile\n${function arguments}\n```\n\nIf the `arguments` field is composed of more than 1 parameter, they are separated using commas:\n\n```Makefile\n$(function arg1, arg2, arg3,...)\n```\n\nWhitespaces and commas are not part of the arguments. Commas and parenthesis are special characters that `make` recognize when it's time to parse a function call. If you need to use these special characters as arguments, you can hide them in variables:\n\n```Makefile\nCOMMA = ,\nEMPTY =\nSPACE = $(EMPTY) $(EMPTY)\nFOO   = a b c\nBAR   = $(subst $(SPACE),$(COMMA),$(FOO))\n\nall:\n\techo FOO=$(FOO)\n\techo BAR=$(BAR)\n\n.SILENT:\n```\n\nOutput\n```shell\nFOO=a b c\nBAR=a,b,c\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n### \u003ca name=\"functions-2\"\u003eA4.2 - Functions for String Manipulation\u003c/a\u003e\n\nUp ahead, we have functions that can be used for generic string manipulation.\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003epatsubst\u003c/h4\u003e - replaces string patterns\u003c/summary\u003e\n\t\n```\n$(patsubst pattern,replacement,text)\n```\n\n**Arguments**\n- `pattern` - A pattern to look for\n- `replacement` - What to replace `pattern` with  \n- `text` - The string(s) to operate on\n\nLooks for whitespace-separated words that match `pattern` in `text` to replace them with `replacement`. The function returns the result after the replacements.\n\nIn `pattern` the `%` symbol may appear, meaning any number of characters that match the pattern. If `%` also appears on `replacement`, the `%` is replaced with the characters matched on `pattern`.\n\nOnly the first `%` in `pattern` and `replacement` are treated this way, while the remaining ones, if any, remain unchanged.\n\nThe following example, saved on [code/16-patsubst-example](code/16-patsubst-example/)...\n\n```Makefile\nFILES = main.c foo.c bar.c\nOBJS = $(patsubst %.c, %.o, $(FILES))\n\nall:\n\techo FILES = $(FILES)\n\techo OBJS = $(OBJS)\n\n.SILENT:\n```\n\n... outputs:\n\n```\nFILES = main.c foo.c bar.c\nOBJS = main.o foo.o bar.o\n```\n\n\u003e [!Note]\n\u003e The notation `$(variable-name:pattern=replacement)` is an equivalent notation. For instance, the assignment of `OBJS` could become `OBJS = $(FILES:.c=.o)`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003estrip\u003c/h4\u003e - strips away whitespaces\u003c/summary\u003e\n\t\n```\n$(strip string)\n```\n\n**Arguments**\n- `string` - The string(s) to work on\n\nRemoves both leading and trailing whitespaces. Multiple whitespaces between strings are condensed into a single space.\n\nHere's an example ([code/17-strip-example](code/17-strip-example)):\n\n```Makefile\nFILES = a           b c         # Ends here\n\nall:\nifeq ($(FILES), a b c)\n\techo \"FILES == a b c\"\nelse\n\techo \"FILES != a b c\"\nendif\n\nifeq ($(strip $(FILES)), a b c)\n\techo \"RESULT == a b c\"\nelse\n\techo \"RESULT != a b c\"\nendif\n\n\n.SILENT:\n```\n\nOutput:\n\n```Makefile\nFILES != a b c\nRESULT == a b c\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003efindstring\u003c/h4\u003e - looks for occurrences of a string\u003c/summary\u003e\n\n```\n$(findstring find,in)\n```\n\n**Arguments**\n- `find` - The string to look for on\n- `in` - The string(s) to search on\n\nIf the text `in` contains a word identical to `find`, the function returns `find`. Otherwise, it returns the empty string.\n\nHere's an example ([code/18-findstring-example](code/18-findstring-example)):\n\n```Makefile\nNAME = Nuno Jesus\n\nall:\n\techo Result=$(findstring Jesus, $(NAME))\n\techo Result=$(findstring Miguel, $(NAME))\n.SILENT:\n```\n\nOutput:\n\n```\nResult=Jesus\nResult=\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003ewords\u003c/h4\u003e - counts the number of words\u003c/summary\u003e\n\n```\n$(words text)\n```\n\n**Arguments**\n- `text` - The string(s) to operate on\n\nCounts the number of words in `text`.\n\nHere's an example ([code/19-words-example](code/19-words-example)):\n\n```Makefile\nVAR = This is a very large string\n\nall:\n\techo VAR has $(words $(VAR)) words\n.SILENT:\n```\n\nOutput:\n\n```\nVAR has 6 words\n```\n\n\u003c/details\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n### \u003ca name=\"functions-3\"\u003eA4.3 - Functions for File Names\u003c/a\u003e\n\nThe following functions were designed to handle file names or paths to files. The transformations take place in the same way for every string.\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003edir\u003c/h4\u003e - extracts the directory part of a file\u003c/summary\u003e\n\n```\n$(dir names…)\n```\n\n**Arguments**\n- `names` - The string(s) to operate on\n\nExtracts the directory part of every file contained in `names`. The directory part is considered to be all the characters until the last `/` is found (including it).\n\nHere's an example ([code/20-dir-example](code/20-dir-example)):\n\n```Makefile\nFILES = source/foo.c source/bar.c baz.c\n\nall:\n\techo These are the directories: $(dir $(FILES))\n.SILENT:\n```\n\nOutput:\n\n```\nThese are the directories: source/ source/ ./\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003enotdir\u003c/h4\u003e - extracts the non-directory part of a file\u003c/summary\u003e\n\n```\n$(notdir names…)\n```\n\n**Arguments**\n- `names` - The string(s) to operate on\n\nExtracts the non-directory part of every file contained in `names`. The non-directory part is considered to be all the characters from the last `/` (not including it) to the end.\n\nHere's an example ([code/21-dir-example](code/21-dir-example)):\n\n```Makefile\nFILES = source/foo.c source/bar.c baz.c\n\nall:\n\techo These are the files: $(notdir $(FILES))\n.SILENT:\n```\n\nOutput:\n\n```\nThese are the files: foo.c bar.c baz.c\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eaddprefix\u003c/h4\u003e - appends a prefix to strings\u003c/summary\u003e\n\n```\n$(addprefix prefix,names…)\n```\n\n**Arguments**\n- `prefix` - The prefix to append\n- `names` - The string(s) to operate on\n\nFor each reference in `names`, it appends `prefix` to it. The final result is the prefix concatenated with each reference, separated by a space between each final reference.\n\nHere's an example ([code/22-addprefix-example](code/22-addprefix-example)):\n\n```Makefile\nFILES = foo.c bar.c baz.c\nSOURCES = sources/\n\nall:\n\techo Final path: $(addprefix $(SOURCES), $(FILES))\n.SILENT:\n```\n\nOutput:\n\n```\nFinal paths: sources/foo.c sources/bar.c sources/baz.c\n```\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eaddsuffix\u003c/h4\u003e - appends a suffix to strings\u003c/summary\u003e\n\n```\n$(addsuffix suffix,names…)\n```\n\n**Arguments**\n- `suffix` - The suffix to append\n- `names` - The string(s) to operate on\n\nFor each reference in `names`, it appends `suffix` to it. The final result is the suffix concatenated with each reference, separated by a space between each final reference.\n\nHere's an example ([code/23-addsuffix-example](code/23-addsuffix-example)):\n\n```Makefile\nFILES = foo bar baz\n\nall:\n\techo Final object files: $(addsuffix .o, $(FILES))\n.SILENT:\n```\n\nOutput:\n\n```\nFinal object files: foo.o bar.o baz.o\n```\n\n\u003c/details\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n### \u003ca name=\"functions-4\"\u003eA4.4 - Functions for Generic Purpose\u003c/a\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eforeach\u003c/h4\u003e - good old loops\u003c/summary\u003e\n\n```\n$(foreach var,list,text)\n```\n\n**Arguments**\n- `var` - The name of a variable that will work as a temporary iterator\n- `list` - The string(s) to operate on\n- `text` - The final transformation for each reference in `list`\n\nFor each word in `list`, `var` takes its value and gets transformed according to whatever is expanded on `text`. Both `var` and `list` are expanded before any transformation is applied.\n\nThe `var` field contains the name of a temporary variable used to reference each word inside `list`. This variable becomes undefined outside the `foreach` call.\n\nThe `text` variable is expanded as many times as there are whitespace-separated words in `list`. The multiple expansions are then concatenated with a single space to produce the final result.\n\nThe following example replicates the `addprefix` example, saved on [code/24-foreach-example](code/24-foreach-example):\n\n```Makefile\nFILES = foo.c bar.c baz.c\nSOURCES = sources\n\nall:\n\techo Final paths: $(foreach file, $(FILES), $(SOURCES)/$(file))\n.SILENT:\n```\n\nOutput:\n\n```\nFinal paths: sources/foo.c sources/bar.c sources/baz.c\n```\n\nVisual representation of the example above:\n\n![foreach](https://github.com/Nuno-Jesus/Make-A-Make/assets/93390807/02d0b529-1fb6-4d45-9591-49275ddf0c8b)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003eshell\u003c/h4\u003e - using shell commands\u003c/summary\u003e\n\n```\n$(shell command)\t\n```\n\n**Arguments**\n- `command` - The string(s) to operate on\n\nThe `shell` function has a particular behavior. It's responsible to communicate with the environment outside `make`, invoke a shell and execute a command, just like what happens in a recipe. The result is then returned and replaced wherever the function was called. Newlines are replaced with a single space.\n\nThe `command` parameter is the command that should be run in the shell, alongside its arguments.\n\nThe following example detects and prints the current kernel ([code/25-shell-example](code/25-shell-example)):\n\n```Makefile\nOS = $(shell uname -s)\n\nall:\n\techo $(OS)\t\n.SILENT:\n```\n\nOutput:\n\n``` shell\nLinux\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ch4\u003ecall\u003c/h4\u003e - call your own defined functions\u003c/summary\u003e\n\n```\n$(call variable,param,param,…)\n```\n\n\n**Arguments**\n- `variable` - the name of the function to call. \n- `param` - strings that will serve as arguments of the function defined in `variable`.\n\nIf you're constantly writing the same complex expressions, you can define a function of your own and assign it the expression. On expansion time, each `param` is assigned to the temporary variables `$(1)`, `$(2)`, etc. As for `$(0)` it receives the value of `variable`.\n\nLet's assume you need to compile a few sub-Makefiles. You also want to keep track of the progress using some custom messages. Something like this:\n\n```Makefile\nall:\n\techo \"Compiling folder-1\"\n\t$(MAKE) -C folder-1\n\n\techo \"Compiling folder-2\"\n\t$(MAKE) -C folder-2\n\n\techo \"Compiling folder-3\"\n\t$(MAKE) -C folder-3\n```\n\nThe example below, saved on [code/26-call-example](code/26-call-example) refactors the Makefile above by defining an expression that holds both the `echo` and the `make` commands:\n\n```Makefile\nSUBFOLDERS = folder-1 folder-2 folder-3\n\ndefine compile\n\t$(info Compiling $(1))\n\t$(MAKE) -C $(1)\nendef\n\nall:\n\t$(foreach folder, $(SUBFOLDERS), $(call compile,$(folder)))\n\n```\n\nAlthough it might be confusing, the example above simply automates the tasks manually written before. It iterates through the list of subfolders where the Makefiles are and calls the commands to both log and compile.\n\n\u003c/details\u003e\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n------------------------------------------------------------------\n\n\n\n## \u003ca name=\"vpath\"\u003eA5 - The vpath directive\u003c/a\u003e\n\nIt's exhausting to manually assemble and write the relative path of files. Assuming you stored some source files in a `nc_utils` folder and your Makefile is right next to that folder...\n\n\t├── ... \n\t├── nc_utils\n\t\t├── nc_clamp.c\n\t\t├── nc_count.c\n\t\t├── nc_free.c\n\t\t├── nc_numlen.c\n\t\t├── main.c\n\t└── Makefile\n\n...you would have to either write those paths down...\n\n```Makefile\nSOURCES = nc_utils/nc_clamp.c \\\n          nc_utils/nc_count.c \\\n          nc_utils/nc_free.c \\\n          nc_utils/nc_numlen.c \\\n          nc_utils/main.c\n```\n\n...or make use of some built-in Makefile function...\n\n```Makefile\nSOURCES = nc_clamp.c nc_count.c nc_free.c nc_numlen.c main.c\nSOURCES := $(addprefix utils/, $(SOURCES))\n```\n\nThe first approach is, obviously, **not scalable**. Despite the second looking more friendly, how much more do you have to add if the source files are placed among multiple folders? (this is the directory tree from [my C library](https://github.com/Nuno-Jesus/42_libnc))\n\n\t├── ...\n\t├── nc_binary_search_tree/\n\t├── nc_conversions/\n\t├── nc_dictionary/\n\t├── nc_is/\n\t├── nc_linked_list/\n\t├── nc_matrix/\n\t├── nc_memory/\n\t├── nc_pair/\n\t├── nc_print/\n\t├── nc_str/\n\t├── nc_utils/\n\t├── nc_vector/\n\t├── Makefile\n\t└── ...\n\nOr even sub-folders? The `addprefix` solution doesn't seem so friendly anymore!\n\nThe `vpath` directive offers a more flexible approach. This directive states what directories `make` should search on. Thus, if any pre-requisite or target is not found on the same directory level as your Makefile, `make` will search on that list of directories for a file with that name.\n\nThe most common syntax for `vpath` is down below:\n\n```Makefile\nvpath pattern directories\n```\n\n- `pattern` - a string containing most often a `%` to match a sequence of characters. If `%` is not present, the `pattern` must match the exact name of a file (quite useless)\n\n- `directories` - a list of directories to search on by files that match `pattern`\n\nUsing `vpath` simplifies the search of source files in `nc_utils`:\n\n```Makefile\nSOURCES = nc_clamp.c nc_count.c nc_free.c nc_numlen.c main.c\n\nvpath %.c nc_utils\n```\n\nAdding more folders into play is a simple matter of adding the source files' names and a new directory to the `vpath` directive. Example with string functions:\n\n```Makefile\nSOURCES =  nc_clamp.c nc_count.c nc_free.c nc_numlen.c\nSOURCES += nc_strlen.c nc_strncmp.c nc_substr.c\nSOURCES += main.c\n\nvpath %.c nc_utils nc_str\n```\n\nYou can find the example above in [code/27-vpath-example](code/27-vpath-example).\n\nThere is also a Makefile implicit `VPATH` variable that serves the same purpose. However, it does not allow you to specify a pattern. One could re-write the `vpath` directive like this:\n\n```Makefile\nVPATH = nc_utils nc_str\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n\n# \u003ca name=\"useful-topics\"\u003eUseful Topics\u003c/a\u003e\n\nI don't think those topics fit either in the beginner's guide or in the advanced topics. However, I think they are useful to know and can be used to improve your Makefiles.\n\n## \u003ca name=\"special-targets\"\u003eSpecial Targets\u003c/a\u003e\nThere are a few special targets that can be used in a Makefile. These targets are not files but, rather commands that can be executed by the Makefile. Please note that these are not all the targets, but rather only the ones I use the most/are more useful.\n\n- `.SILENT` - Disables the default logging of Make actions in the terminal. If used with prerequisites, only those targets are executed silently.\n\n```Makefile\n.SILENT: all\n```\n\nOtherwise, if used without prerequisites, all targets are executed silently.\n\n```Makefile\n.SILENT:\n```\n\n- `.PHONY` - used to tell the Makefile to not confuse the names of the targets with filenames. For instance, if `clean` is considered phony...\n\n```Makefile\n.PHONY: clean\n```\n\n...the Make will always execute the `clean` rule, even if a file named `clean` exists.\n\n- `.DEFAULT_GOAL` - used to define what is the primary target of the Makefile. If not specified, the first target is chosen by default.\n\n```Makefile\n.DEFAULT_GOAL: clean\n```\n\nThe example above would set the clean target to execute by default when running `make`.\n\n- `.NOTPARALLEL` - executes the Makefile in a single thread, even if the -j flag is used. If used with prerequisites, only those targets are executed sequentially.\n\n```Makefile\n.NOTPARALLEL: fclean\n```\n\nOtherwise, if used without prerequisites, all targets are executed sequentially.\n\n```Makefile\n.NOTPARALLEL:\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## \u003ca name=\"flags\"\u003eMakefile Flags\u003c/a\u003e\n\n- `-C \u003cdir\u003e` - used to recursively call another Makefile `\u003cdir\u003e`. The syntax is as follows: `make [target] -C \u003cdir\u003e`. The `target` field can be omitted You can find an example of this in the [code/07-C-flag-example](/code/07-C-flag-example).\n\n```Makefile\nall:\n\t$(MAKE) -C hello/\n\t$(CC) main.c hello/hello.c\n```\n\n```shell\n➜  example-7 git:(master) ✗ make  \nmake -C hello/\nmake[1]: Entering directory '/nfs/homes/ncarvalh/...'\ncc -Wall -Werror -Wextra -c hello.c -o hello.o\nmake[1]: Leaving directory '/nfs/homes/ncarvalh/...'\ncc -Wall -Werror -Wextra main.c hello/hello.c -o project\n➜  example-7 git:(master) ✗\n```\n\nWhen \u003ccode\u003emake -C\u003c/code\u003e is issued, it forces a directory change towards the sub-Make directory. After the sub-Make is done executing, the directory is changed back to the original Make to continue execution.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `-k` - Usually, when an error happens, the Make aborts execution immediately. Using this flag, the Make is forced to attempt executing further targets. If you need an error list, this flag is for you. You can find an example of this in the [code/08-k-flag-example](/code/08-k-flag-example).\n\n```shell\n➜  example-8 git:(master) ✗ make  \ncc -Wall -Werror -Wextra -c hello.c\nmake: *** No rule to make target 'bye.o', needed by 'project'.  Stop.\n➜  example-8 git:(master) ✗  \n```\n```shell\n➜  example-8 git:(master) ✗ make -k  \ncc -Wall -Werror -Wextra -c hello.c\nmake: *** No rule to make target 'bye.o', needed by 'project'.\nmake: *** No rule to make target 'highfive.o', needed by 'project'.\nmake: Target 'all' not remade because of errors.\n➜  example-8 git:(master) ✗\n```\n\nEven though \u003ccode\u003ebye.o\u003c/code\u003e can not be remade, the Makefile attempts to fulfill the next pre-requisite, which also fails, not aborting execution though.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `-p` - Dumps the whole database of known variables and rules (both explicit and implicit). The output is quite extensive, so I'll only display a small portion of it. For demonstration purposes, we're re-using the [code/06-relinking-example](/code/06-relinking-example) folder.\n\n```shell\n➜  example-6 git:(master) ✗ make -p\n...\n# environment\nDBUS_SESSION_BUS_ADDRESS = unix:path=/run/user/101153/bus\n# Makefile (from 'Makefile', line 1)\nCC = cc\n# Makefile (from 'Makefile', line 5)\nOBJS = hello.o bye.o highfive.o\n...\n➜  example-6 git:(master) ✗\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `-s` - Disables the default logging of Make actions in the terminal. Works just like the `.SILENT` special target/ For demonstration purposes, we're re-using the [code/06-relinking-example](/code/06-relinking-example) folder.\n\n```shell\n➜  example-6 git:(master) ✗ make       \ncc -Wall -Werror -Wextra -c hello.c\ncc -Wall -Werror -Wextra -c bye.c\ncc -Wall -Werror -Wextra -c highfive.c\ncc -Wall -Werror -Wextra main.c hello.o bye.o highfive.o -o project\n➜  example-6 git:(master) ✗\n```\n\n```shell\n➜  example-6 git:(master) ✗ make -s\n➜  example-6 git:(master) ✗\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `-r` - Tells the Makefile to ignore any built-in rules. In the example below, we simply omit the rule for compiling C files. You can find an example of this in the [code/09-r-flag-example](/code/09-r-flag-example). \n\n```shell\n➜  example-9 git:(master) ✗ make       \ncc -Wall -Werror -Wextra   -c -o hello.o hello.c\ncc -Wall -Werror -Wextra main.c hello.o -o project\n➜  example-9 git:(master) ✗       \n```\n\n```shell\n➜  example-9 git:(master) ✗ make -r       \nmake: *** No rule to make target 'hello.o', needed by 'project'.  Stop.\n➜  example-9 git:(master) ✗       \n```\n\nBecause we removed the explicit rule for compiling C files, the compilation must be done using an implicit rule. However, using the \u003ccode\u003e-r\u003c/code\u003e, all implicit rules are not considered, so there's no way of generating \u003ccode\u003ehello.o\u003c/code\u003e.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `-j [number of threads]` - Takes advantage of threads to speed up the Makefile execution. The number of threads is optional. You can find an example of this in the [code/10-j-flag-example](/code/10-j-flag-example).\n\nWhen using the `-j` flag, the Makefile will execute the targets in parallel, which doesn't guarantee the order of execution. So a rule designed like this...\n\n```make\nfclean: clean all\n```\n\n... would perform `clean` and `all` at the same time, which can cause weird outputs. You can either re-write it...\n\n```make\nfclean: clean\n\t$(MAKE) all\n```\n\n... or use the `.NOTPARALLEL` special target, which disables parallel execution of targets and their dependencies.\n\n```make\n.NOTPARALLEL: fclean\nfclean: clean all\n```\n\n```shell\n➜  example-10 git:(master) ✗ time make    \ncc -Wall -Werror -Wextra -c hello.c\ncc -Wall -Werror -Wextra -c bye.c\ncc -Wall -Werror -Wextra -c highfive.c\ncc -Wall -Werror -Wextra -c hug.c\ncc -Wall -Werror -Wextra -c kiss.c\ncc -Wall -Werror -Wextra -c handshake.c\ncc -Wall -Werror -Wextra -c wave.c\ncc -Wall -Werror -Wextra main.c hello.o bye.o highfive.o hug.o ...\nmake  0.10s user 0.06s system 84% cpu 0.185 total\n➜  example-10 git:(master) ✗\n```\n\n```shell\n➜  example-10 git:(master) ✗ time make -j  \ncc -Wall -Werror -Wextra -c hello.c\ncc -Wall -Werror -Wextra -c bye.c\ncc -Wall -Werror -Wextra -c highfive.c\ncc -Wall -Werror -Wextra -c hug.c\ncc -Wall -Werror -Wextra -c kiss.c\ncc -Wall -Werror -Wextra -c handshake.c\ncc -Wall -Werror -Wextra -c wave.c\ncc -Wall -Werror -Wextra main.c hello.o bye.o highfive.o hug.o ...\nmake -j  0.12s user 0.06s system 235% cpu 0.076 total\n➜  example-10 git:(master) ✗\n```\n\nThe \u003ccode\u003etime\u003c/code\u003e command is only used to read the CPU load and execution time.\n\n\u003e [!Note]\n\u003e When recursively calling make, the parallel computation is not imposed in sub-Makes unless you use the `$(MAKE)` variable. You also don't need to use the \u003ccode\u003e-j\u003c/code\u003e flag in the sub-Make, since you would launch N more threads, which you don't really need to.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `-n` - Displays the commands the Makefile would run without actually executing it.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `--debug` - Executes and displays how dependencies are resolved. For demonstration purposes, we're re-using the [code/09-r-flag-example](/code/09-r-flag-example) folder.\n\n```shell\n➜  example-9 git:(master) ✗ make\ncc -Wall -Werror -Wextra   -c -o hello.o hello.c\ncc -Wall -Werror -Wextra main.c hello.o -o project\n➜  example-9 git:(master) ✗\n```\n\n```shell\n➜  example-9 git:(master) ✗ make --debug\n...\nReading makefiles...\nUpdating makefiles....\nUpdating goal targets....\n File 'all' does not exist.\n   File 'project' does not exist.\n     File 'hello.o' does not exist.\n    Must remake target 'hello.o'.\ncc -Wall -Werror -Wextra   -c -o hello.o hello.c\n    Successfully remade target file 'hello.o'.\n  Must remake target 'project'.\ncc -Wall -Werror -Wextra main.c hello.o -o project\n  Successfully remade target file 'project'.\nMust remake target 'all'.\nSuccessfully remade target file 'all'.\n➜  example-9 git:(master) ✗\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n- `--no-print-directory` Disables message printing whenever the Makefile enters or exits a directory. For demonstration purposes, we're re-using the [code/07-C-flag-example](/code/07-C-flag-example) folder.\n\n```shell\n➜  example-7 git:(master) ✗ make\nmake -C hello/\nmake[1]: Entering directory '/nfs/homes/ncarvalh/...'\ncc -Wall -Werror -Wextra -c hello.c -o hello.o\nmake[1]: Leaving directory '/nfs/homes/ncarvalh/...'\ncc main.c hello/hello.c\n➜  example-7 git:(master) ✗\n```\n\n```shell\n➜  example-7 git:(master) ✗ make --no-print-directory\nmake -C hello/\ncc -Wall -Werror -Wextra -c hello.c -o hello.o\ncc main.c hello/hello.c\n➜  example-7 git:(master) ✗\n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n- `-I \u003cdir\u003e` - specifies a directory to search for included Makefiles. Useful to prevent building the path to the dependencies. You can find an example of this in the [code/13-I-flag-example](/code/13-I-flag-example).\n\n```shell\n➜  13-I-flag-example git:(advanced-topics) ✗ make          \nMakefile:18: main.d: No such file or directory\nmake: *** No rule to make target 'main.d'.  Stop.\n➜  13-I-flag-example git:(advanced-topics) ✗ make -I teste \ncc -Wall -Werror -Wextra   -c -o main.o main.c\ncc -Wall -Werror -Wextra main.o -o a.out\n➜  13-I-flag-example git:(advanced-topics) ✗ \n```\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n\n------------------------------------------------------------------ \n\n\n## \u003ca name=\"errors\"\u003eGood-to-know Errors\u003c/a\u003e\n\n\tMakefile: *** missing separator.  Stop.\n\n`make` is very strict when it comes to its syntax. Whether it's reading a rule, a variable assignment or a target, `make` looks for separators like `:`, `=` or tabulations. So probably you're missing one of those.\n\n\tMakefile: *** missing separator (did you mean TAB instead of 8 spaces?).  Stop.\n\nThis one is derived from the first. You can get this message if you're attempting to replace tabs with spaces.\n\n\tmake: *** No rule to make target X.  Stop.\n\nThis is probably one of the most common errors. It means `make` was trying to build something called `X`, but couldn't find an explicit or implicit rule to do so. It can be caused due to a typo, wrong pattern matching rules (when using `%`), or missing files.\n\n\tMakefile: *** recipe commences before first target.  Stop.\n\nThis means that when `make` was trying to parse your Makefile, it found something that looks like a recipe but doesn't start with a target. Remember that rules must always have a target.\n\n\twarning: overriding recipe for target 'X'\n\nHappens whenever you define 2 or more recipes for the same target. This will force `make` to override the previous recipes with the last one.\n\n\tCircular X \u003c- Y dependency dropped.\n\nThis means `make` detected a loop when parsing the prerequisites of its rules. Supposing you have something like this...\n\n```Makefile\n\tX: Y ...\n\t\t...\n```\n\n... where `X` depends on `Y`. After tracing `Y` and its prerequisites, the `make` reached a point where it found a target depending on `X`.\n\n\tUnterminated variable reference. Stop.\n\nIf you received this message, you're missing a parenthesis/brace when using a variable. Remember that the correct syntax to use a variable's value is either `$(NAME)` or `${NAME}`.\n\n\tMakefile: *** missing 'endif'.  Stop.\n\nSelf-explanatory, you forgot to add an `endif` directive to your conditional.\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n\n\n------------------------------------------------------------------\n\n\n## 📞 **Contact me**\nFeel free to ask me any questions through Slack (**ncarvalh**).\n\n\u003c!--\n\n## \u003ca name=\"index-4\"\u003eThe vpath directive and project organization\u003c/a\u003e\n\n## \u003ca name=\"index-4\"\u003eQuestions\u003c/a\u003e\n## \u003ca name=\"index-4\"\u003eGeneral tips\u003c/a\u003e\n- Group up common stuff: variables with variables, rules with rules. Mixing it up might turn your Makefile confusing.\n- Comment your Makefile and delimit different sections. If your Makefile is out of this world, you should comment it. Its good for you and the others.\n- Want to silent commands, but not all of them? Write a '@' before each command to silent it.\n- You can append strings to variables by using the '+=' operator\n- As I said before, Makefiles have a wide use case range. You can create rules to avoid writing repeating and large commands, like valgrind.\n- Compiling a Makefile with another Makefile? Don't use make directly. Instead use $(MAKE), which expands to the same value. Might seem pointless, but some flags might depend on in. The $(MAKE) variables tells the Makefile we are calling another Makefile.\n- Using the '\\' operator at the end of the line forces the Makefile to consider the next line as a continuation of the first. Essentially a one line only.\n- Avoid repetition. Use functions when you can\n\n\u003cdiv align=center\u003e\n\t\u003cstrong\u003e\u003ca href=\"#index-0\"\u003e🚀 Go back to top 🚀\u003c/a\u003e\u003c/strong\u003e\n\u003c/div\u003e\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNuno-Jesus%2FMake-A-Make","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNuno-Jesus%2FMake-A-Make","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNuno-Jesus%2FMake-A-Make/lists"}