{"id":19929182,"url":"https://github.com/vampy/makefile","last_synced_at":"2026-02-11T11:01:39.938Z","repository":{"id":78387215,"uuid":"313747881","full_name":"vampy/Makefile","owner":"vampy","description":"Makefile Tutorial - learn make by example ","archived":false,"fork":false,"pushed_at":"2021-01-10T12:17:20.000Z","size":14,"stargazers_count":83,"open_issues_count":0,"forks_count":22,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-13T23:34:15.033Z","etag":null,"topics":["gnu","gnu-make","gnu-makefile","gnu-makefiles","make","makefile"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vampy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2020-11-17T21:30:40.000Z","updated_at":"2025-07-18T18:21:36.000Z","dependencies_parsed_at":"2023-03-09T18:00:49.170Z","dependency_job_id":null,"html_url":"https://github.com/vampy/Makefile","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vampy/Makefile","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vampy%2FMakefile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vampy%2FMakefile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vampy%2FMakefile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vampy%2FMakefile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vampy","download_url":"https://codeload.github.com/vampy/Makefile/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vampy%2FMakefile/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29332292,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T06:13:03.264Z","status":"ssl_error","status_checked_at":"2026-02-11T06:12:55.843Z","response_time":97,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["gnu","gnu-make","gnu-makefile","gnu-makefiles","make","makefile"],"created_at":"2024-11-12T22:42:08.772Z","updated_at":"2026-02-11T11:01:39.667Z","avatar_url":"https://github.com/vampy.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"- [Makefile Tutorial](#makefile-tutorial)\n\t- [Makefile Syntax](#makefile-syntax)\n\t- [Make Overview](#make-overview)\n\t- [Running the Examples](#running-the-examples)\n\t- [Simple Examples](#simple-examples)\n\t- [Variables (Section 2.4)](#variables-section-24)\n\t- [Magic Implicit Commands (Section 2.5)](#magic-implicit-commands-section-25)\n\t- [Using Wildcard Characters (Section 4.2)](#using-wildcard-characters-section-42)\n\t- [The Wildcard Function (Section 4.2.3)](#the-wildcard-function-section-423)\n\t- [The vpath Directive (Section 4.3.2)](#the-vpath-directive-section-432)\n\t- [Targets](#targets)\n\t\t- [The all target (Section 4.4)](#the-all-target-section-44)\n\t\t- [Multiple targets `$@` (Section 4.8)](#multiple-targets--section-48)\n\t\t- [Multiple targets via wildcards `%` (Section 4.8)](#multiple-targets-via-wildcards--section-48)\n\t- [Static Patterns](#static-patterns)\n\t\t- [Static Pattern Rules (Section 4.10)](#static-pattern-rules-section-410)\n\t\t- [Static Pattern Rules and Filter (Section 4.10)](#static-pattern-rules-and-filter-section-410)\n\t- [Double-Colon Rules (Section 4.11)](#double-colon-rules-section-411)\n\t- [Command Echoing/Silencing (Section 5.1)](#command-echoingsilencing-section-51)\n\t- [Command Execution (Section 5.2)](#command-execution-section-52)\n\t- [Default Shell (Section 5.2)](#default-shell-section-52)\n\t- [DELETE_ON_ERROR (Section 5.4)](#delete_on_error-section-54)\n\t- [Error handling with `-k`, `-i`, and `i` (Section 5.4)](#error-handling-with--k--i-and-i-section-54)\n\t- [Handling errors with `-` and `-i` (Section 5.4)](#handling-errors-with---and--i-section-54)\n\t- [Interrupting or killing make (Section 5.5)](#interrupting-or-killing-make-section-55)\n\t- [Recursive use of make (Section 5.6)](#recursive-use-of-make-section-56)\n\t- [Use `export` for recursive make (Section 5.6)](#use-export-for-recursive-make-section-56)\n\t- [Another export example (Section 5.6)](#another-export-example-section-56)\n\t- [Variables](#variables)\n\t\t- [`EXPORT_ALL_VARIABLES` (Section 5.6)](#export_all_variables-section-56)\n\t\t- [Variables Reference (Section 6.1)](#variables-reference-section-61)\n\t\t- [Variables Types `=` vs `:=` (Section 6.2)](#variables-types--vs--section-62)\n\t\t- [Variables Expansion (Section 6.2)](#variables-expansion-section-62)\n\t\t- [Variables Conditional set with `?=` (Section 6.2)](#variables-conditional-set-with--section-62)\n\t\t- [Variables: watch out for end-of-line spaces (Section 6.2)](#variables-watch-out-for-end-of-line-spaces-section-62)\n\t\t- [Variables: Text replacement `$(var:a=b)` (Section 6.3)](#variables-text-replacement-varab-section-63)\n\t\t- [Variables: Text replacement % (Section 6.3)](#variables-text-replacement--section-63)\n\t\t- [Undefined Variables (Section 6.5)](#undefined-variables-section-65)\n\t\t- [Variable appending (Section 6.6)](#variable-appending-section-66)\n\t\t- [Target-specific variables (Section 6.10)](#target-specific-variables-section-610)\n\t\t- [Pattern-specific variables (Section 6.11)](#pattern-specific-variables-section-611)\n\t\t- [Check if a variable is empty (Section 7.2)](#check-if-a-variable-is-empty-section-72)\n\t\t- [`ifdef` (Section 7.2)](#ifdef-section-72)\n\t\t- [Conditional if/else (Section 7.1)](#conditional-ifelse-section-71)\n\t\t- [Automatic Variables: `$@`, `$^`, `$?`, etc (Section 10.5)](#automatic-variables----etc-section-105)\n\t- [Command line arguments and `override` (Section 6.7)](#command-line-arguments-and-override-section-67)\n\t- [List of commands and `define` (Section 6.8)](#list-of-commands-and-define-section-68)\n\t- [Testing make flags with `findstring` and `MAKEFLAG`(Section 7.3)](#testing-make-flags-with-findstring-and-makeflagsection-73)\n\t- [Functions](#functions)\n\t\t- [Functions (Section 8.1)](#functions-section-81)\n\t\t- [The foreach function (Section 8.4)](#the-foreach-function-section-84)\n\t\t- [The if function (Section 8.5)](#the-if-function-section-85)\n\t\t- [The call function (Section 8.6)](#the-call-function-section-86)\n\t\t- [The shell function (Section 8.8)](#the-shell-function-section-88)\n\t- [Arguments to make (Section 9)](#arguments-to-make-section-9)\n\t- [Implicit Rules (Section 10)](#implicit-rules-section-10)\n\n# [Makefile Tutorial](https://en.wikipedia.org/wiki/Makefile)\n\nSources:\n- [theicfire/makefiletutorial](https://github.com/theicfire/makefiletutorial) - This tutorial mostly copied from there, but has the advantage to be just a markdown file.\n- [GNU Make Book](https://www.cl.cam.ac.uk/teaching/0910/UnixTools/make.pdf) - This tutorial teaches mainly through examples in order to help quickly explain the concepts in the book.\n- [GNU make manual (HTML)](https://www.gnu.org/software/make/manual/make.html) - Other [Formats Here (PDF, TEXT, etc)](https://www.gnu.org/software/make/manual/)\n- [Adding help to a Makefile](https://www.owenrumney.co.uk/help-in-make-file/)\n\n## Makefile Syntax\nA Makefile consists of a set of *rules*. A rule generally looks like this:\n```\ntargets : prerequisites\n   command\n   command\n   command\n```\n- The **targets** are  usually file names that are generated by a program, separated by spaces. Typically, there is only one per rule. Examples of targets are executable or object files. A target can also be the name of an action to carry out, such as \"clean\".\n- The **prerequisites** (also called **dependencies**) are also file names, separated by spaces, used as input to create the target. A target often depends on several files. However, the rule that specifies a recipe for the target need not have any prerequisites. For example, the rule containing the delete command associated with the target \"clean\" does not have prerequisites.\n- The **commands** are a series of steps typically used to make the target(s). These **need to start with a \\\u003ctab\\\u003e character**, not spaces.\n\n## Make Overview\nThe main use of Make is to list out a set of directions to compile some c or c++ files, although it can solve other similar problems. The user gives Make some *goal*, say \"generate the file hello\".\n\nThe Makefile specifies how to make this file. Here's an example:\n\n```make\n# Since the blah target is first, it is the default target and will be run when we run \"make\"\nblah: blah.o\n\tcc blah.o -o blah\n\nblah.o: blah.c\n\tcc -c blah.c -o blah.o\n\nblah.c:\n\techo \"int main() { return 0; }\" \u003e blah.c\n\nclean:\n\trm -f blah.o blah.c blah\n```\n\n## Running the Examples\nA makefile is executed with the `make` command, e.g. `make [options] [target1 target2 ...]`. By default, when make looks for the makefile, if a makefile name was not included as a parameter, it tries the following names, in order: `makefile` and `Makefile`.\n\nYou'll need a terminal and `make` installed. For each example, put the contents in a file called `Makefile`, and in that directory run the command `make`. Here is the output of running the above example:\n```bash\n$ make\necho \"int main() { return 0; }\" \u003e blah.c\ncc -c blah.c -o blah.o\ncc blah.o -o blah\n```\n\nSome examples, like the above, have a target called \"clean\". Run it via `make clean` to delete the files that `make` generated:\n```bash\n$ make clean\nrm -f blah.o blah.c blah\n```\n\n## Simple Examples\nThis makefile has a single target, called `some_file`. The default target is the first target, so in this case `some_file` will run.\n```make\nsome_file:\n\techo \"This line will always print\"\n```\n\nThis file will make `some_file` the first time, and the second time notice it's already made, resulting in `make: 'some_file' is up to date.`\n```make\nsome_file:\n\techo \"This line will only print once\"\n\ttouch some_file\n```\n\nAlternative syntax: same line\n```\nsome_file: ; touch some_file\n```\n\nThe backslash `\\` character gives us the ability to use multiple lines when the commands are too long\n\n```make\nsome_file:\n\techo This line is too long, so \\\n\t\tit is broken up into multiple lines\n```\n\nHere, the target `some_file` \"depends\" on `other_file`. When we run `make`, the default target (`some_file`, since it's first) will get called. It will first look at its list of *dependencies*, and if any of them are older, it will first run the targets for those dependencies, and then run itself. The second time this is run, neither target will run because both targets exist.\n\n```make\nsome_file: other_file\n\techo \"This will run second, because it depends on other_file\"\n\ttouch some_file\n\nother_file:\n\techo \"This will run first\"\n\ttouch other_file\n```\n\nThis will always make both targets, because `some_file` depends on other_file, which is never created.\n\n```make\nsome_file: other_file\n\ttouch some_file\n\nother_file:\n\techo \"nothing\"\n```\n\n\"clean\" is often used as a target that removes the output of other targets.\n\n```make\nsome_file: clean\n\ttouch some_file\n\nclean:\n\trm -f some_file\n```\n\nAdding `.PHONY` to a target will prevent make from confusing the phony target with a file name. In this example, if the file \"clean\" is created, make clean will still be run. `.PHONY` is great to use, but I'll skip it in the rest of the examples for simplicity.\n\n```make\nsome_file:\n\ttouch some_file\n\ttouch clean\n\n.PHONY: clean\nclean:\n\trm -f some_file\n\trm -f clean\n```\n\n## Variables (Section 2.4)\nVariables can only be strings. Here's an example of using them:\n\n```make\nfiles = file1 file2\nsome_file: $(files)\n\techo \"Look at this variable: \" $(files)\n\ttouch some_file\n\nfile1:\n\ttouch file1\nfile2:\n\ttouch file2\n\nclean:\n\trm -f file1 file2 some_file\n```\n\n## Magic Implicit Commands (Section 2.5)\nProbably one of the most confusing parts about Make is the hidden coupling between Make and GCC. Make was largely made for GCC, and so makes compiling C/C++ programs \"easy\".\n\n```make\n# Implicit command of: \"cc blah.o -o blah\"\n# Note: Do not put a comment inside of the blah.o rule; the implicit rule will not run!\nblah:\n\n# Implicit command of: \"cc -c blah.c -o blah.o\"\nblah.o:\n\nblah.c:\n\techo \"int main() { return 0; }\" \u003e blah.c\n\nclean:\n\trm -f blah.o blah blah.c\n```\n\n## Using Wildcard Characters (Section 4.2)\nWe can use wildcards in the target, prerequisites, or commands.\nValid wildcards are `*, ?, [...]`\n\n```make\nsome_file: *.c\n\t# create the binary\n\n*.c:\n\ttouch f1.c\n\ttouch f2.c\n\nclean:\n\trm -f *.c\n```\n\n## The Wildcard Function (Section 4.2.3)\nWe CANNOT use wildcards in other places, like variable declarations or function arguments\nUse the wildcard function instead.\n\n```make\nwrong = *.o # Wrong\nobjects := $(wildcard *.c) # Right\nsome_binary:\n\ttouch f1.c\n\ttouch f2.c\n\techo $(wrong)\n\techo $(objects)\n\nclean:\n\trm -f *.c\n```\n\n## The vpath Directive (Section 4.3.2)\nUse vpath to specify where some set of prerequisites exist. The format is `vpath \u003cpattern\u003e \u003cdirectories, space/colon seperated\u003e`\n`\u003cpattern\u003e` can have a `%`, which matches any zero or more characters.\nYou can also do this globallyish with the variable VPATH\n\n```make\nvpath %.h ../headers ../other-directory\n\nsome_binary: ../headers blah.h\n\ttouch some_binary\n\n../headers:\n\tmkdir ../headers\n\nblah.h:\n\ttouch ../headers/blah.h\n\nclean:\n\trm -rf ../headers\n\trm -f some_binary\n```\n\n## Targets\n### The all target (Section 4.4)\nMaking multiple targets and you want all of them to run? Make a `all` target and designate it as `.PHONY`\n```make\nall: one two three\n.PHONY: all\n\none:\n\ttouch one\ntwo:\n\ttouch two\nthree:\n\ttouch three\n\nclean:\n\trm -f one two three\n```\n\n### Multiple targets `$@` (Section 4.8)\nWhen there are multiple targets for a rule, the commands will be run for each target\n`$@` is a *automatic variable* that contains the target name.\n\n```make\nall: f1.o f2.o\n\nf1.o f2.o:\n\techo $@\n# Equivalent to:\n# f1.o\n# \techo $@\n# f2.o\n# \techo $@\n```\n\n### Multiple targets via wildcards `%` (Section 4.8)\nWe can use the wildcard `%` in targets, that captures zero or more of any character. Note we do not use `*.o`, because that is just the string `*.o`, which might be useful in the commands,\nbut is only one target and does not expand.\n\u003c!--\nTODO why was this not a problem when I didn't use the % wildcard?\n--\u003e\n```make\n\nall: f1.o f2.o\n.PHONY: all\n\n%.o:\n\techo $@\n```\n\n## Static Patterns\n\n### Static Pattern Rules (Section 4.10)\nMake loves C compilation. And every time it expresses its love, things get confusing. Here's the syntax for a new type of rule called a static pattern:\n```make\ntargets ...: target-pattern: prereq-patterns ...\n   commands\n```\n\nThe essence is that the a given target is matched by the target-pattern (via a `%` wildcard). Whatever was matched is called the *stem*. The stem is then substituted into the prereq-pattern, to generate the target's prereqs.\n\nA typical use case is to compile `.c` files into `.o` files. Here's the *manual way*:\n\n```make\nall: foo.o bar.o\n.PHONY: all\n\n# The automatic variable $@ matches the target, and $\u003c matches the prerequisite\nfoo.o: foo.c\n\techo \"Call gcc to generate $@ from $\u003c\"\n\nbar.o: bar.c\n\techo \"Call gcc to generate bar.o from bar.c\"\n\n# Matches all .c files and creates them if they don't exist\n%.c:\n\ttouch $@\n\nclean:\n\trm -f foo.c bar.c\n```\n\nHere's the more *efficient way*, using a static pattern rule:\n\n```make\n# This Makefile uses less hard coded rules, via static pattern rules\nobjects = foo.o bar.o\nall: $(objects)\n.PHONY: all\n\n# Syntax - targets ...: target-pattern: prereq-patterns ...\n# In the case of the first target, foo.o, the target-pattern matches foo.o and sets the \"stem\" to be \"foo\".\n#   It then replaces that stem with the wilecard pattern in prereq-patterns\n$(objects): %.o: %.c\n\techo \"Call gcc to generate $@ from $\u003c\"\n\n%.c:\n\ttouch $@\n\nclean:\n\trm -f foo.c bar.c\n```\n\n### Static Pattern Rules and Filter (Section 4.10)\n`filter` can be used in Static pattern rules to match the correct files. In this example, I made up the `.raw` and `.result` extensions.\n\n```make\n\nobj_files = foo.result bar.o lose.o\nsrc_files = foo.raw bar.c lose.c\n\nall: $(obj_files)\n.PHONY: all\n\n$(filter %.o,$(obj_files)): %.o: %.c\n\techo \"target: $@ prereq: $\u003c\"\n$(filter %.result,$(obj_files)): %.result: %.raw\n\techo \"target: $@ prereq: $\u003c\"\n\n%.c %.raw:\n\ttouch $@\n\nclean:\n\trm -f $(src_files)\n```\n\n## Double-Colon Rules (Section 4.11)\nDouble-Colon Rules are rarely used, but allow the same target to run commands from multiple targets.\nIf these were single colons, an warning would be printed and only the second set of commands would run.\n```make\nall: blah\n\nblah::\n\techo \"hello\"\n\nblah::\n\techo \"hello again\"\n\nclean:\n\trm -f $(src_files)\n```\n\n\u003c!--\nTODO: This example fails initially because blah.d doesn't exist. I'm not sure how to fix this example, there are probably better ones out there..\n\n# Generating Prerequisites Automatically (Section 4.12)\nExample requires: blah.c\nGenerating prereqs automatically\nThis makes one small makefile per source file\nNotes:\n1) $$ is the current process id in bash. $$$$ is just $$, with escaping. We use it to make a temporary file, that doesn't interfere with others if there is some parallel builds going on.\n2) cc -MM outputs a makefile line. This is the magic that generates prereqs automatically, by looking at the code itself\n3) The purpose of the sed command is to translate (for example):\n    main.o : main.c defs.h\n    into:\n    main.o main.d : main.c defs.h\n4) Running `make clean` will rerun the rm -f ... rule because the include line wants to include an up to date version of the file. There is such a target that updates it, so it runs that rule before including the file.\n```make\n# Run make init first, then run make\n# This outputs\nall: blah.d\n\nclean:\n\trm -f blah.d blah.c blah.h blah.o blah\n\n%.d: %.c\n\trm -f $@; \\\n\t $(CC) -MM $(CPPFLAGS) $\u003c \u003e $@.$$$$; \\\n\t sed 's,\\($*\\)\\.o[ :]*,\\1.o $@ : ,g' \u003c $@.$$$$ \u003e $@; \\\n\t rm -f $@.$$$$\n\ninit:\n\techo \"#include \\\"blah.h\\\"; int main() { return 0; }\" \u003e blah.c\n\ttouch blah.h\n\nsources = blah.c\n\ninclude $(sources:.c=.d)\n```\n--\u003e\n\n## Command Echoing/Silencing (Section 5.1)\nAdd an @ before a command to stop it from being printed\nYou can also run make with -s to add an @ before each line\n\n```make\nall:\n\t@echo \"This make line will not be printed\"\n\techo \"But this will\"\n```\n\n## Command Execution (Section 5.2)\nEach command is run in a new shell (or at least the affect is as such)\n\n```make\nall:\n\tcd ..\n\t# The cd above does not affect this line, because each command is effectively run in a new shell\n\techo `pwd`\n\n\t# This cd command affects the next because they are on the same line\n\tcd ..;echo `pwd`\n\n\t# Same as above\n\tcd ..; \\\n\techo `pwd`\n```\n\n## Default Shell (Section 5.2)\nThe default shell is `/bin/sh`. You can change this by changing the variable `SHELL`:\n\n```make\nSHELL=/bin/bash\n\ncool:\n\techo \"Hello from bash\"\n```\n\n## DELETE_ON_ERROR (Section 5.4)\nThe make tool will stop running a rule (and will propogate back to prerequisites) if a command returns a nonzero exit status.\n`DELETE_ON_ERROR` will delete the target of a rule if the rule fails in this manner. This will happen for all targets, not just the one it is before like PHONY. It's a good idea to always use this, even though make does not for historical reasons.\n\n```make\n.DELETE_ON_ERROR:\nall: one two\n\none:\n\ttouch one\n\tfalse\n\ntwo:\n\ttouch two\n\tfalse\n```\n\n## Error handling with `-k`, `-i`, and `i` (Section 5.4)\nAdd `-k` when running make to continue running even in the face of errors. Helpful if you want to see all the errors of Make at once.\nAdd a \"-\" before a command to suppress the error\nAdd \"-i\" to make to have this happen for every command.\n\n## Handling errors with `-` and `-i` (Section 5.4)\n```make\none:\n\t# This error will be printed but ignored, and make will continue to run\n\t-false\n\ttouch one\n```\n\n## Interrupting or killing make (Section 5.5)\nNote only: If you `ctrl+c` make, it will delete the newer targets it just made.\n\n## Recursive use of make (Section 5.6)\nRecursively call a makefile. Use the special $(MAKE) instead of \"make\"\nbecause it will pass the make flags for you and won't itself be affected by them.\n\n```make\nnew_contents = \"hello:\\n\\ttouch inside_file\"\nall:\n\tmkdir -p subdir\n\techo $(new_contents) | sed -e 's/^ //' \u003e subdir/makefile\n\tcd subdir \u0026\u0026 $(MAKE)\n\nclean:\n\trm -rf subdir\n```\n\n## Use `export` for recursive make (Section 5.6)\nThe export directive takes a variable and makes it accessible to sub-make commands.\nIn this example, \"cooly\" is exported such that the makefile in subdir can use it.\n\nNote: export has the same syntax as sh, but they aren't related (although similar in function)\n\n```make\nnew_contents = \"hello:\\n\\\\techo \\$$(cooly)\"\n\nall:\n\tmkdir -p subdir\n\techo $(new_contents) | sed -e 's/^ //' \u003e subdir/makefile\n\t@echo \"---MAKEFILE CONTENTS---\"\n\t@cd subdir \u0026\u0026 cat makefile\n\t@echo \"---END MAKEFILE CONTENTS---\"\n\tcd subdir \u0026\u0026 $(MAKE)\n\n# Note that variables and exports. They are set/affected globally.\ncooly = \"The subdirectory can see me!\"\nexport cooly\n# This would nullify the line above: unexport cooly\n\nclean:\n\trm -rf subdir\n```\n\n## Another export example (Section 5.6)\nYou need to export variables to have them run in the shell as well.\n\n```make\none=this will only work locally\nexport two=we can run subcommands with this\n\n.PHONY: all\nall:\n\t@echo $(one)\n\t@echo $$one\n\t@echo $(two)\n\t@echo $$two\n```\n\n## Variables\n\n### `EXPORT_ALL_VARIABLES` (Section 5.6)\n`EXPORT_ALL_VARIABLES` does what you might expect\n\n```make\n.EXPORT_ALL_VARIABLES:\nnew_contents = \"hello:\\n\\techo \\$$(cooly)\"\n\ncooly = \"The subdirectory can see me!\"\n# This would nullify the line above: unexport cooly\n\nall:\n\tmkdir -p subdir\n\techo $(new_contents) | sed -e 's/^ //' \u003e subdir/makefile\n\t@echo \"---MAKEFILE CONTENTS---\"\n\t@cd subdir \u0026\u0026 cat makefile\n\t@echo \"---END MAKEFILE CONTENTS---\"\n\tcd subdir \u0026\u0026 $(MAKE)\n\nclean:\n\trm -rf subdir\n```\n\n### Variables Reference (Section 6.1)\nReference variables using `${}` or `$()`\n\n```make\nx = dude\n\n.PHONY: all\nall:\n\techo $(x)\n\techo ${x}\n\n\t# Bad practice, but works\n\techo $x\n```\n\n### Variables Types `=` vs `:=` (Section 6.2)\nTwo flavors of variables:\n- recursive (use `=`) - only looks for the variables when the command is *used*, not when it's *defined*.\n- simply expanded (use `:=`) - like normal imperative programming -- only those defined so far get expanded\n\n```make\n# Recursive variable. This will print \"later\" below\none = one ${later_variable}\n# Simply expanded variable. This will not print \"later\" below\ntwo := two ${later_variable}\n\nlater_variable = later\n\n.PHONY: all\nall:\n\techo $(one)\n\techo $(two)\n```\n\n### Variables Expansion (Section 6.2)\nSimply expanded allows you to append to a variable. Recursive definitions will give an infinite loop error.\n\n```make\none = hello\n# one gets defined as a simply expanded variable (:=) and thus can handle appending\none := ${one} there\n\n.PHONY: all\nall:\n\techo $(one)\n```\n\n### Variables Conditional set with `?=` (Section 6.2)\n?= only sets variables if they have not yet been set\n\n```make\none = hello\none ?= will not be set\ntwo ?= will be set\n\n.PHONY: all\nall:\n\techo $(one)\n\techo $(two)\n```\n\n### Variables: watch out for end-of-line spaces (Section 6.2)\nSpaces at the end of a line are not stripped, ones at the start are\nTo make a variable with a single space, have a variable guard\n\n```make\nwith_spaces = hello   # with_spaces has many spaces after \"hello\"\nafter = $(with_spaces)there\n\nnullstring =\nspace = $(nullstring) # Make a variable with a single space.\n\n.PHONY: all\nall:\n\techo \"$(after)\"\n\techo start\"$(space)\"end\n```\n\n### Variables: Text replacement `$(var:a=b)` (Section 6.3)\nYou can text replace at the end of each space seperated word using `$(var:a=b)`\nNote: don't put spaces in between anything; it will be seen as a search or replacement term\nNote: This is shorthand for using make's `patsubst` expansion function\n\n```make\nfoo := a.o b.o c.o\n# bar becomes a.c b.c c.c\nbar := $(foo:.o=.c)\n\n.PHONY: all\nall:\n\techo $(bar)\n```\n\n### Variables: Text replacement % (Section 6.3)\nYou can use `%` as well to grab some text!\n\n```make\nfoo := a.o b.o c.o\nbar := $(foo:%.o=%)\n\n.PHONY: all\nall:\n\techo $(bar)\n```\n\n### Undefined Variables (Section 6.5)\nAn undefined variable is actually an empty string!\n\n```make\n.PHONY: all\nall:\n\t# Undefined variables are just empty strings!\n\techo $(nowhere)\n```\n\n### Variable appending (Section 6.6)\nUse `+=` to append\n\n```make\nfoo := start\nfoo += more\n\n.PHONY: all\nall:\n\techo $(foo)\n```\n\n### Target-specific variables (Section 6.10)\nVariables can be assigned for specific targets\n\n```make\nall: one = cool\n\n.PHONY: all\nall:\n\techo one is defined: $(one)\n\n.PHONY: other\nother:\n\techo one is nothing: $(one)\n```\n\n### Pattern-specific variables (Section 6.11)\nYou can assign variables for specific target *patterns*\n\n```make\n%.c: one = cool\n\nblah.c:\n\techo one is defined: $(one)\n\n.PHONY: other\nother:\n\techo one is nothing: $(one)\n```\n\n### Check if a variable is empty (Section 7.2)\n```make\nnullstring =\nfoo = $(nullstring) # end of line; there is a space here\n\nall:\nifeq ($(strip $(foo)),)\n\techo \"foo is empty after being stripped\"\nendif\nifeq ($(nullstring),)\n\techo \"nullstring doesn't even have spaces\"\nendif\n```\n\n### `ifdef` (Section 7.2)\nifdef does not expand variable references; it just sees if something is defined at all\n\n```make\nbar =\nfoo = $(bar)\n\nall:\nifdef foo\n\techo \"foo is defined\"\nendif\nifdef bar\n\techo \"but bar is not\"\nendif\n```\n\n### Conditional if/else (Section 7.1)\n```make\nfoo = ok\n\nall:\nifeq ($(foo), ok)\n\techo \"foo equals ok\"\nelse\n\techo \"nope\"\nendif\n```\n\n### Automatic Variables: `$@`, `$^`, `$?`, etc (Section 10.5)\nThere are many [automatic variables](https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html), but often only a few show up:\n\n```make\nhey: one two\n\t# Outputs \"hey\", since this is the first target\n    # $@ - is a macro that refers to the target\n\techo $@\n\n\t# Outputs all prerequisites that are newer than the target, with spaces between them\n\techo $?\n\n\t# Outputs all prerequisites\n    # $^ is a macro that refers to all dependencies\n\techo $^\n\n\ttouch hey\n\none:\n\ttouch one\n\ntwo:\n\ttouch two\n\nclean:\n\trm -f hey one two\n```\n\n## Command line arguments and `override` (Section 6.7)\nYou can override variables that come from the command line by using \"override\".\nHere we ran make with `make some_option=hi`\n\n```make\n# Overrides command line arguments\noverride option_one = did_override\n# Does not override command line arguments\noption_two = not_override\n.PHONY: all\nall:\n\techo $(option_one)\n\techo $(option_two)\n```\n\n## List of commands and `define` (Section 6.8)\n`define` is actually just a list of commands. It has nothing with being a function.\nNote here that it's a bit different than having a semi-colon between commands, because each is run\nin a seperate shell, as expected.\n\n```make\none = export blah=\"I was set!\"; echo $$blah\n\ndefine two\nexport blah=set\necho $$blah\nendef\n\n# One and two are different.\n\n.PHONY: all\nall:\n\t@echo \"This prints 'I was set'\"\n\t@$(one)\n\t@echo \"This does not print 'I was set' because each command runs in a seperate shell\"\n\t@$(two)\n```\n\n## Testing make flags with `findstring` and `MAKEFLAG`(Section 7.3)\nRun this example with `make -i` to see it print out the echo statement.\n\n```make\nbar =\nfoo = $(bar)\n\nall:\n# Search for the \"-i\" flag. MAKEFLAGS is just a list of single characters, one per flag. So look for \"i\" in this case.\nifneq (,$(findstring i, $(MAKEFLAGS)))\n\techo \"i was passed to MAKEFLAGS\"\nendif\n```\n\n## Functions\n\n\n### Functions (Section 8.1)\n*Functions* are mainly just for text processing. Call functions with `$(fn, arguments)` or `${fn, arguments}`. You can make your own using the [call](https://www.gnu.org/software/make/manual/html_node/Call-Function.html#Call-Function) builtin function. Make has a decent amount of [builtin functions](https://www.gnu.org/software/make/manual/html_node/Functions.html).\n\n```make\nbar := ${subst not, totally, \"I am not superman\"}\nall:\n\t@echo $(bar)\n```\n\nIf you want to replace spaces or commas, use variables\n\n```make\ncomma := ,\nempty:=\nspace := $(empty) $(empty)\nfoo := a b c\nbar := $(subst $(space),$(comma),$(foo))\n\nall:\n\t@echo $(bar)\n```\n\nDo **NOT** include spaces in the arguments after the first. That will be seen as part of the string.\n\n```make\ncomma := ,\nempty:=\nspace := $(empty) $(empty)\nfoo := a b c\nbar := $(subst $(space), $(comma) , $(foo))\n\nall:\n\t# Output is \", a , b , c\". Notice the spaces introduced\n\t@echo $(bar)\n```\n\n\u003c!-- # 8.2, 8.3, 8.9 TODO do something about the fns\n# TODO 8.7 origin fn? Better in documentation?\n--\u003e\n\n### The foreach function (Section 8.4)\nThe foreach function looks like this: `$(foreach var,list,text)`.\n\nIt converts one list of words (seperated by speces) to another.\n\n`var` is set to each word in list, and `text` is expanded for each word.\nThis appends an exclamation after each word:\n\n```make\nfoo := who are you\n# For each \"word\" in foo, output that same word with an exclamation after\nbar := $(foreach wrd,$(foo),$(wrd)!)\n\nall:\n\t# Output is \"who! are! you!\"\n\t@echo $(bar)\n```\n\n### The if function (Section 8.5)\n`if` checks if the first argument is nonempty. If so runs the second argument, otherwise runs the third.\n\n```make\nfoo := $(if this-is-not-empty,then!,else!)\nempty :=\nbar := $(if $(empty),then!,else!)\n\nall:\n\t@echo $(foo)\n\t@echo $(bar)\n```\n\n### The call function (Section 8.6)\n`Call`: `$(call variable,param,param)`\n\nSets each of the params as `$(1)`, `$(2)`, etc.\n\n`$(0)` is set as the variable name.\n\n```make\nsweet_new_fn = Variable Name: $(0) First: $(1) Second: $(2) Empty Variable: $(3)\n\nall:\n\t# Outputs \"Variable Name: sweet_new_fn First: go Second: tigers Empty Variable:\"\n\t@echo $(call sweet_new_fn, go, tigers)\n```\n\n### The shell function (Section 8.8)\nshell - This calls the shell, but it replaces newlines with spaces!\n\n```make\nall:\n\t@echo $(shell ls -la) # Very ugly because the newlines are gone!\n```\n\n## Arguments to make (Section 9)\n\nThere's a nice [list of options](http://www.gnu.org/software/make/manual/make.html#Options-Summary) that can be run from make. Check out `--dry-run`, `--touch`, `--old-file`.\n\nYou can have multiple targets to make, i.e. `make clean run test` runs the 'clean' goal, then 'run', and then 'test'.\n\n## Implicit Rules (Section 10)\nPerhaps the most confusing part of make is the magic rules and variables that are made. Here's a list of implicit rules:\n- Compiling a C program: `n.o` is made automatically from `n.c` with a command of the form `$(CC) -c $(CPPFLAGS) $(CFLAGS)`\n- Compiling a C++ program: `n.o` is made automatically from `n.cc` or `n.cpp` with a command of the form `$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)`\n- Linking a single object file: `n` is made automatically from `n.o` by running the command `$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)`\n\nAs such, the important variables used by implicit rules are:\n- `CC`: Program for compiling C programs; default cc\n- `CXX`: Program for compiling C++ programs; default G++\n- `CFLAGS`: Extra flags to give to the C compiler\n- `CXXFLAGS`: Extra flags to give to the C++ compiler\n- `CPPFLAGS`: Extra flags to give to the C preprosessor\n- `LDFLAGS`: Extra flags to give to compilers when they are supposed to invoke the linker\n\n```make\nCC = gcc # Flag for implicit rules\nCFLAGS = -g # Flag for implicit rules. Turn on debug info\n\n# Implicit rule #1: blah is built via the C linker implicit rule\n# Implicit rule #2:  blah.o is built via the C++ compilation implicit rule, because blah.cpp exists\nblah: blah.o\n\nblah.c:\n\techo \"int main() { return 0; }\" \u003e blah.c\n\nclean:\n\trm -f blah*\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvampy%2Fmakefile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvampy%2Fmakefile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvampy%2Fmakefile/lists"}