Understanding and Using Makefile Variables

Table of contents

What are make variables, how to use make variables, recursive and simple assignment, immediate assignment, conditional assignment, shell assignment, variables with spaces, target-specific variables, pattern-specific variables, environment variables, command-line arguments, how to append to a variable, automatic variables, implicit variables.

  • ‣ Makefile Examples
  • ‣ Makefile Flags
  • ‣ Makefile Wildcards
  • ‣ G++ Makefile
  • ‣ Bash Variables Explained

Understanding and Using Makefile Variables

Aniket Bhattacharyea %

In this Series

Table of Contents

The article explains the intricacies of Makefile variables. Earthly improves on Makefile performance by introducing sophisticated caching and concurrent execution. Learn more about Earthly .

Since its appearance in 1976, Make has been helping developers automate complex processes for compiling code, building executables, and generating documentation.

Like other programming languages, Make lets you define and use variables that facilitate reusability of values.

Have you found yourself using the same value in multiple places? This is both repetitive and prone to errors. If you’d like to change this value, you’ll have to change it everywhere. This process is tedious, but it can be solved with variables, and Make offers powerful variable manipulation techniques that can make your life easier.

In this article, you’ll learn all about make variables and how to use them.

A variable is a named construct that can hold a value that can be reused in the program. It is defined by writing a name followed by = , := , or ::= , and then a value. The name of a variable can be any sequence of characters except “:”, “#”, “=”, or white space. In addition, variable names in Make are case sensitive, like many other programming languages.

The following is an example of a variable definition:

Any white space before the variable’s value is stripped away, but white spaces at the end are preserved. Using a $ inside the value of the variable is permitted, but make will assume that a string starting with the $ sign is referring to another variable and will substitute the variable’s value:

As you’ll soon learn, make assumes that $t refers to another variable named t and substitutes it. Since t doesn’t exist, it’s empty, and therefore, foo becomes onewo . If you want to include a $ verbatim, you must escape it with another $ :

Once defined, a variable can be used in any target, prerequisite, or recipe. To substitute a variable’s value, you need to use a dollar sign ( $ ) followed by the variable’s name in parentheses or curly braces. For instance, you can refer to the foo variable using both ${foo} and $(foo) .

Here’s an example of a variable reference in a recipe:

Running make with the earlier makefile will print “Hello, World!”.

Another common example of variable usage is in compiling a C program where you can define an objects variable to hold the list of all object files:

Here, the objects variable has been used in a target, prerequisite, and recipe.

Unlike many other programming languages, using a variable that you have not set explicitly will not result in an error; rather, the variable will have an empty string as its default value. However, some special variables have built-in non-empty values, and several other variables have different default values set for each different rule (more on this later).

How to Set Variables

How to Set Variables

Setting a variable refers to defining a variable with an initial value as well as changing its value later in the program. You can either set a value explicitly in the makefile or pass it as an environment variable or a command-line argument.

Variables in the Makefile

There are four different ways you can define a variable in the Makefile:

  • Recursive assignment
  • Simple assignment
  • Immediate assignment
  • Conditional assignment

As you may remember, you can define a variable with = , := , and ::= . There’s a subtle difference in how variables are expanded based on what operator is used to define them.

  • The variables defined using = are called recursively expanded variables , and
  • Those defined with := and ::= are called simply expanded variables .

When a recursively expanded variable is expanded, its value is substituted verbatim. If the substituted text contains references to other variables, they are also substituted until no further variable reference is encountered. Consider the following example where foo expands to Hello $(bar) :

Since foo is a recursively expanded variable, $(bar) is also expanded, and “Hello World” is printed. This recursive expansion process is performed every time the variable is expanded, using the current values of any referenced variables:

The biggest advantage of recursively expanded variables is that they make it easy to construct new variables piecewise: you can define separate pieces of the variable and string them together. You can define more granular variables and join them together, which gives you finer control over how make is executed.

For example, consider the following snippet that is often used in compiling C programs:

Here, ALL_CFLAGS is a recursively expanded variable that expands to include the contents of CFLAGS along with the -I. option. This lets you override the CFLAGS variable if you wish to pass other options while retaining the mandatory -I. option:

A disadvantage of recursively expanded variables is that it’s not possible to append something to the end of the variable:

To overcome this issue, GNU Make supports another flavor of variable known as simply expanded variables , which are defined with := or ::= . A simply expanded variable, when defined, is scanned for further variable references, and they are substituted once and for all.

Unlike recursively expanded variables, where referenced variables are expanded to their current values, in a simply expanded variable, referenced variables are expanded to their values at the time the variable is defined:

With a simply expanded variable, the following is possible:

GNU Make supports simply and recursively expanded variables. However, other versions of make usually only support recursively expanded variables. The support for simply expanded variables was added to the Portable Operating System Interface (POSIX) standard in 2012 with only the ::= operator.

A variable defined with :::= is called an immediately expanded variable . Like a simply expanded variable, its value is expanded immediately when it’s defined. But like a recursively expanded variable, it will be re-expanded every time it’s used. After the value is immediately expanded, it will automatically be quoted, and all instances of $ in the value after expansion will be converted into $$ .

In the following code, the immediately expanded variable foo behaves similarly to a simply expanded variable:

However, if there are references to other variables, things get interesting:

Here, OUT will have the value one$$two . This is because $(var) is immediately expanded to one$two , which is quoted to get one$$two . But OUT is a recursive variable, so when it’s used, $two will be expanded:

The :::= operator is supported in POSIX Make, but GNU Make includes this operator from version 4.4 onward.

The conditional assignment operator ?= can be used to set a variable only if it hasn’t already been defined:

An equivalent way of defining variables conditionally is to use the origin function :

These four types of assignments can be used in some specific situations:

You may sometimes need to run a shell command and assign its output to a variable. You can do that with the shell function:

A shorthand for this is the shell assignment operator != . With this operator, the right-hand side must be the shell command whose result will be assigned to the left-hand side:

Trailing spaces at the end of a variable definition are preserved in the variable value, but spaces at the beginning are stripped away:

It’s possible to preserve spaces at the beginning by using a second variable to store the space character:

It’s possible to limit the scope of a variable to specific targets only. The syntax for this is as follows:

Here’s an example:

Here, the variable foo will have different values based on which target make is currently evaluating:

Pattern-Specific Variables

Pattern-specific variables make it possible to limit the scope of a variable to targets that match a particular pattern . The syntax is similar to target-specific variables:

For example, the following line sets the variable foo to World for any target that ends in .c :

Pattern-specific variables are commonly used when you want to set the variable for multiple targets that share a common pattern , such as setting the same compiler options for all C files.

The real power of make variables starts to show when you pair them with environment variables . When make is run in a shell, any environment variable present in the shell is transformed into a make variable with the same name and value. This means you don’t have to set them in the makefile explicitly:

When you run the earlier makefile , it should print your username since the USER environment variable is present in the shell.

This feature is most commonly used with flags . For example, if you set the CFLAGS environment variable with your preferred C compiler options, they will be used by most makefiles to compile C code since, conventionally, the CFLAGS variable is only used for this purpose. However, this is only sometimes guaranteed, as you’ll see next.

If there’s an explicit assignment in the makefile to a variable, it overrides any environment variable with the same name:

The earlier makefile will always print Bob since the assignment overrides the $USER environment variable. You can pass the -e flag to make so environment variables override assignments instead, but this is not recommended, as it can lead to unexpected results.

You can pass variable values to the make command as command-line variables. Unlike environment variables, command-line arguments will always override assignments in the makefile unless the override directive is used:

You can simply run make , and the default values will be used:

You can pass a new value for BAR by passing it as a command-line argument:

However, since the override directive is used with FOO , it cannot be changed via command-line arguments:

This feature is handy since it lets you change a variable’s value without editing the makefile . This is most commonly used to pass configuration options that may vary from system to system or used to customize the software. As a practical example, Vim uses command-line arguments to override configuration options , like the runtime directory and location of the default configuration.

How to Append to a Variable

You can use the previous value of a simply expanded variable to add more text to it:

As mentioned before, this syntax will produce an infinite recursion error with a recursively expanded variable. In this case, you can use the += operator, which appends text to a variable, and it can be used for both recursively expanded and simply expanded variables:

However, there’s a subtle difference in the way it works for the two different flavors of variables, which you can read about in the docs .

How To Use Special Variables

In Make, any variable that is not defined is assigned an empty string as the default value. There are, however, a few special variables that are exceptions:

Automatic variables are special variables whose value is set up automatically per rule based on the target and prerequisites of that particular rule. The following are several commonly used automatic variables:

  • $@ is the file name of the target of the rule.
  • $< is the name of the first prerequisite.
  • $? is the name of all the prerequisites that are newer than the target, with spaces between them. If the target does not exist, all prerequisites will be included.
  • $^ is the name of all the prerequisites, with spaces between them.

Here’s an example that shows automatic variables in action:

Running make with the earlier makefile prints the following:

If you run touch one to modify one and run make again, you’ll get a different output:

Since one is newer than the target hello , $? contains only one .

There exist variants of these automatic variables that can extract the directory and file-within-directory name from the matched expression. You can find a list of all automatic variables in the official docs .

Automatic variables are often used where the target and prerequisite names dictate how the recipe executes . A very common practical example is the following rule that compiles a C file of the form x.c into x.o :

Make ships with certain predefined rules for some commonly performed operations. These rules include the following:

  • Compiling x.c to x.o with a rule of the form $(CC) -c $(CPPFLAGS) $(CFLAGS) $^ -o $@
  • Compiling x.cc or x.cpp with a rule of the form $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
  • Linking a static object file x.o to create x with a rule of the form $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
  • And many more

These implicit rules make use of certain predefined variables known as implicit variables. Some of these are as follows:

  • CC is a program for compiling C programs. The default is cc .
  • CXX is a program for compiling C++ programs. The default is g++ .
  • CPP is a program for running the C preprocessor. The default is $(CC) -E .
  • LEX is a program to compile Lex grammars into source code. The default is lex .
  • YACC is a program to compile Yacc grammars into source code. The default is yacc .

You can find the full list of implicit variables in GNU Make’s docs .

Just like standard variables, you can explicitly define an implicit variable:

Or you can define them with command line arguments:

Flags are special variables commonly used to pass options to various command-line tools, like compilers or preprocessors. Compilers and preprocessors are implicitly defined variables for some commonly used tools, including the following:

  • CFLAGS is passed to CC for compiling C.
  • CPPFLAGS is passed to CPP for preprocessing C programs.
  • CXXFLAGS is passed to CXX for compiling C++.

Learn more about Makefile flags .

Make variables are akin to variables in other languages with unique features that make them effective yet somewhat complex. Learning them can be a handy addition to your programming toolkit. If you’ve enjoyed diving into the intricacies of Makefile variables, you might want to explore Earthly for a fresh take on builds!

Bala Priya C %

Bala is a technical writer who enjoys creating long-form content. Her areas of interest include math and programming. She shares her learning with the developer community by authoring tutorials, how-to guides, and more.

makefile variable assignment syntax

12 minute read

Learn how to automate the software building process using `make`, a powerful tool that saves time and resources. This article covers the basics of writing a ...

makefile variable assignment syntax

10 minute read

Learn how to use `make` flags in your `Makefile` to customize the behavior of the compilation tools. Discover the benefits of using flags over hard-coded opt...

makefile variable assignment syntax

8 minute read

Learn how to use wildcards in Makefiles to create flexible and automated build processes. This tutorial provides examples and explanations of common wildcard...

makefile variable assignment syntax

Learn how to compile C++ programs with the g++ compiler provided by GCC and automate the compilation process using Make. This tutorial covers the installatio...

makefile variable assignment syntax

9 minute read

Learn the basics of bash variables and how they work in the UNIX shell. Discover how to define and access local shell variables, work with arrays, handle com...

makefile variable assignment syntax

Learn how to use Makefiles in Visual Studio Code to simplify the build process for your software projects. This tutorial walks you through setting up a C++ p...

makefile variable assignment syntax

7 minute read

Learn how to automate repetitive tasks in Golang development using Makefiles. This tutorial covers creating a Makefile to build, run, clean, test, and manage...

makefile variable assignment syntax

Learn how to use `make` with Python to automate tasks like running tests, installing dependencies, and cleaning builds. Discover the benefits of using `make`...

makefile variable assignment syntax

15 minute read

Learn the key differences between CMake and Make, two popular build automation tools. Discover how CMake's cross-platform capabilities, GUI, and better depen...

makefile variable assignment syntax

Learn all about Terraform variables and how to use them in this comprehensive guide. Discover the different variable types, their usage, and workarounds for ...

makefile variable assignment syntax

Getting Started

Why do makefiles exist, what alternatives are there to make, the versions and types of make, running the examples, makefile syntax, the essence of make, more quick examples, the all target, multiple targets, automatic variables and wildcards, automatic variables, fancy rules, implicit rules, static pattern rules, static pattern rules and filter, pattern rules, double-colon rules, commands and execution, command echoing/silencing, command execution, default shell, double dollar sign.

  • Error handling with -k, -i, and -

Interrupting or killing make

Recursive use of make, export, environments, and recursive make, arguments to make, variables pt. 2, flavors and modification, command line arguments and override, list of commands and define, target-specific variables, pattern-specific variables, conditional part of makefiles, conditional if/else, check if a variable is empty, check if a variable is defined, $(makeflags), first functions, string substitution, the foreach function, the if function, the call function, the shell function, other features, include makefiles, the vpath directive, .delete_on_error, makefile cookbook.

I built this guide because I could never quite wrap my head around Makefiles. They seemed awash with hidden rules and esoteric symbols, and asking simple questions didn’t yield simple answers. To solve this, I sat down for several weekends and read everything I could about Makefiles. I've condensed the most critical knowledge into this guide. Each topic has a brief description and a self contained example that you can run yourself.

If you mostly understand Make, consider checking out the Makefile Cookbook , which has a template for medium sized projects with ample comments about what each part of the Makefile is doing.

Good luck, and I hope you are able to slay the confusing world of Makefiles!

Makefiles are used to help decide which parts of a large program need to be recompiled. In the vast majority of cases, C or C++ files are compiled. Other languages typically have their own tools that serve a similar purpose as Make. Make can also be used beyond compilation too, when you need a series of instructions to run depending on what files have changed. This tutorial will focus on the C/C++ compilation use case.

Here's an example dependency graph that you might build with Make. If any file's dependencies changes, then the file will get recompiled:

makefile variable assignment syntax

Popular C/C++ alternative build systems are SCons , CMake , Bazel , and Ninja . Some code editors like Microsoft Visual Studio have their own built in build tools. For Java, there's Ant , Maven , and Gradle . Other languages like Go, Rust, and TypeScript have their own build tools.

Interpreted languages like Python, Ruby, and raw Javascript don't require an analogue to Makefiles. The goal of Makefiles is to compile whatever files need to be compiled, based on what files have changed. But when files in interpreted languages change, nothing needs to get recompiled. When the program runs, the most recent version of the file is used.

There are a variety of implementations of Make, but most of this guide will work on whatever version you're using. However, it's specifically written for GNU Make, which is the standard implementation on Linux and MacOS. All the examples work for Make versions 3 and 4, which are nearly equivalent other than some esoteric differences.

To run these examples, you'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 . Let's start with the simplest of Makefiles:

Note: Makefiles must be indented using TABs and not spaces or make will fail.

Here is the output of running the above example:

That's it! If you're a bit confused, here's a video that goes through these steps, along with describing the basic structure of Makefiles.

A Makefile consists of a set of rules . A rule generally looks like this:

  • The targets are file names, separated by spaces. Typically, there is only one per rule.
  • The commands are a series of steps typically used to make the target(s). These need to start with a tab character , not spaces.
  • The prerequisites are also file names, separated by spaces. These files need to exist before the commands for the target are run. These are also called dependencies

Let's start with a hello world example:

There's already a lot to take in here. Let's break it down:

  • We have one target called hello
  • This target has two commands
  • This target has no prerequisites

We'll then run make hello . As long as the hello file does not exist, the commands will run. If hello does exist, no commands will run.

It's important to realize that I'm talking about hello as both a target and a file . That's because the two are directly tied together. Typically, when a target is run (aka when the commands of a target are run), the commands will create a file with the same name as the target. In this case, the hello target does not create the hello file .

Let's create a more typical Makefile - one that compiles a single C file. But before we do, make a file called blah.c that has the following contents:

Then create the Makefile (called Makefile , as always):

This time, try simply running make . Since there's no target supplied as an argument to the make command, the first target is run. In this case, there's only one target ( blah ). The first time you run this, blah will be created. The second time, you'll see make: 'blah' is up to date . That's because the blah file already exists. But there's a problem: if we modify blah.c and then run make , nothing gets recompiled.

We solve this by adding a prerequisite:

When we run make again, the following set of steps happens:

  • The first target is selected, because the first target is the default target
  • This has a prerequisite of blah.c
  • Make decides if it should run the blah target. It will only run if blah doesn't exist, or blah.c is newer than blah

This last step is critical, and is the essence of make . What it's attempting to do is decide if the prerequisites of blah have changed since blah was last compiled. That is, if blah.c is modified, running make should recompile the file. And conversely, if blah.c has not changed, then it should not be recompiled.

To make this happen, it uses the filesystem timestamps as a proxy to determine if something has changed. This is a reasonable heuristic, because file timestamps typically will only change if the files are modified. But it's important to realize that this isn't always the case. You could, for example, modify a file, and then change the modified timestamp of that file to something old. If you did, Make would incorrectly guess that the file hadn't changed and thus could be ignored.

Whew, what a mouthful. Make sure that you understand this. It's the crux of Makefiles, and might take you a few minutes to properly understand . Play around with the above examples or watch the video above if things are still confusing.

The following Makefile ultimately runs all three targets. When you run make in the terminal, it will build a program called blah in a series of steps:

  • Make selects the target blah , because the first target is the default target
  • blah requires blah.o , so make searches for the blah.o target
  • blah.o requires blah.c , so make searches for the blah.c target
  • blah.c has no dependencies, so the echo command is run
  • The cc -c command is then run, because all of the blah.o dependencies are finished
  • The top cc command is run, because all the blah dependencies are finished
  • That's it: blah is a compiled c program

If you delete blah.c , all three targets will be rerun. If you edit it (and thus change the timestamp to newer than blah.o ), the first two targets will run. If you run touch blah.o (and thus change the timestamp to newer than blah ), then only the first target will run. If you change nothing, none of the targets will run. Try it out!

This next example doesn't do anything new, but is nontheless a good additional example. It will always run both targets, because some_file depends on other_file , which is never created.

clean is often used as a target that removes the output of other targets, but it is not a special word in Make. You can run make and make clean on this to create and delete some_file .

Note that clean is doing two new things here:

  • It's a target that is not first (the default), and not a prerequisite. That means it'll never run unless you explicitly call make clean
  • It's not intended to be a filename. If you happen to have a file named clean , this target won't run, which is not what we want. See .PHONY later in this tutorial on how to fix this

Variables can only be strings. You'll typically want to use := , but = also works. See Variables Pt 2 .

Here's an example of using variables:

Single or double quotes have no meaning to Make. They are simply characters that are assigned to the variable. Quotes are useful to shell/bash, though, and you need them in commands like printf . In this example, the two commands behave the same:

Reference variables using either ${} or $()

Making multiple targets and you want all of them to run? Make an all target. Since this is the first rule listed, it will run by default if make is called without specifying a target.

When there are multiple targets for a rule, the commands will be run for each target. $@ is an automatic variable that contains the target name.

Both * and % are called wildcards in Make, but they mean entirely different things. * searches your filesystem for matching filenames. I suggest that you always wrap it in the wildcard function, because otherwise you may fall into a common pitfall described below.

* may be used in the target, prerequisites, or in the wildcard function.

Danger: * may not be directly used in a variable definitions

Danger: When * matches no files, it is left as it is (unless run in the wildcard function)

% is really useful, but is somewhat confusing because of the variety of situations it can be used in.

  • When used in "matching" mode, it matches one or more characters in a string. This match is called the stem.
  • When used in "replacing" mode, it takes the stem that was matched and replaces that in a string.
  • % is most often used in rule definitions and in some specific functions.

See these sections on examples of it being used:

There are many automatic variables , but often only a few show up:

Make loves c compilation. And every time it expresses its love, things get confusing. Perhaps the most confusing part of Make is the magic/automatic rules that are made. Make calls these "implicit" rules. I don't personally agree with this design decision, and I don't recommend using them, but they're often used and are thus useful to know. Here's a list of implicit rules:

  • Compiling a C program: n.o is made automatically from n.c with a command of the form $(CC) -c $(CPPFLAGS) $(CFLAGS) $^ -o $@
  • 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) $^ -o $@
  • Linking a single object file: n is made automatically from n.o by running the command $(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@

The important variables used by implicit rules are:

  • CC : Program for compiling C programs; default cc
  • CXX : Program for compiling C++ programs; default g++
  • CFLAGS : Extra flags to give to the C compiler
  • CXXFLAGS : Extra flags to give to the C++ compiler
  • CPPFLAGS : Extra flags to give to the C preprocessor
  • LDFLAGS : Extra flags to give to compilers when they are supposed to invoke the linker

Let's see how we can now build a C program without ever explicitly telling Make how to do the compililation:

Static pattern rules are another way to write less in a Makefile, but I'd say are more useful and a bit less "magic". Here's their syntax:

The essence is that the 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.

A typical use case is to compile .c files into .o files. Here's the manual way :

Here's the more efficient way , using a static pattern rule:

While I introduce functions later on, I'll foreshadow what you can do with them. The filter function can be used in Static pattern rules to match the correct files. In this example, I made up the .raw and .result extensions.

Pattern rules are often used but quite confusing. You can look at them as two ways:

  • A way to define your own implicit rules
  • A simpler form of static pattern rules

Let's start with an example first:

Pattern rules contain a '%' in the target. This '%' matches any nonempty string, and the other characters match themselves. ‘%’ in a prerequisite of a pattern rule stands for the same stem that was matched by the ‘%’ in the target.

Here's another example:

Double-Colon Rules are rarely used, but allow multiple rules to be defined for the same target. If these were single colons, a warning would be printed and only the second set of commands would run.

Add an @ before a command to stop it from being printed You can also run make with -s to add an @ before each line

Each command is run in a new shell (or at least the effect is as such)

The default shell is /bin/sh . You can change this by changing the variable SHELL:

If you want a string to have a dollar sign, you can use $$ . This is how to use a shell variable in bash or sh .

Note the differences between Makefile variables and Shell variables in this next example.

Error handling with -k , -i , and -

Add -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. Add a - before a command to suppress the error Add -i to make to have this happen for every command.

Note only: If you ctrl+c make, it will delete the newer targets it just made.

To recursively call a makefile, use the special $(MAKE) instead of make because it will pass the make flags for you and won't itself be affected by them.

When Make starts, it automatically creates Make variables out of all the environment variables that are set when it's executed.

The export directive takes a variable and sets it the environment for all shell commands in all the recipes:

As such, when you run the make command inside of make, you can use the export directive to make it accessible to sub-make commands. In this example, cooly is exported such that the makefile in subdir can use it.

You need to export variables to have them run in the shell as well.

.EXPORT_ALL_VARIABLES exports all variables for you.

There's a nice list of options that can be run from make. Check out --dry-run , --touch , --old-file .

You can have multiple targets to make, i.e. make clean run test runs the clean goal, then run , and then test .

There are two flavors of variables:

  • recursive (use = ) - only looks for the variables when the command is used , not when it's defined .
  • simply expanded (use := ) - like normal imperative programming -- only those defined so far get expanded

Simply expanded (using := ) allows you to append to a variable. Recursive definitions will give an infinite loop error.

?= only sets variables if they have not yet been set

Spaces at the end of a line are not stripped, but those at the start are. To make a variable with a single space, use $(nullstring)

An undefined variable is actually an empty string!

Use += to append

String Substitution is also a really common and useful way to modify variables. Also check out Text Functions and Filename Functions .

You can override variables that come from the command line by using override . Here we ran make with make option_one=hi

The define directive is not a function, though it may look that way. I've seen it used so infrequently that I won't go into details, but it's mainly used for defining canned recipes and also pairs well with the eval function .

define / endef simply creates a variable that is set to a list of commands. Note here that it's a bit different than having a semi-colon between commands, because each is run in a separate shell, as expected.

Variables can be set for specific targets

You can set variables for specific target patterns

ifdef does not expand variable references; it just sees if something is defined at all

This example shows you how to test make flags with findstring and MAKEFLAGS . Run this example with make -i to see it print out the echo statement.

Functions are mainly just for text processing. Call functions with $(fn, arguments) or ${fn, arguments} . Make has a decent amount of builtin functions .

If you want to replace spaces or commas, use variables

Do NOT include spaces in the arguments after the first. That will be seen as part of the string.

$(patsubst pattern,replacement,text) does the following:

"Finds whitespace-separated words in text that match pattern and replaces them with replacement. Here pattern may contain a ‘%’ which acts as a wildcard, matching any number of any characters within a word. If replacement also contains a ‘%’, the ‘%’ is replaced by the text that matched the ‘%’ in pattern. Only the first ‘%’ in the pattern and replacement is treated this way; any subsequent ‘%’ is unchanged." ( GNU docs )

The substitution reference $(text:pattern=replacement) is a shorthand for this.

There's another shorthand that replaces only suffixes: $(text:suffix=replacement) . No % wildcard is used here.

Note: don't add extra spaces for this shorthand. It will be seen as a search or replacement term.

The foreach function looks like this: $(foreach var,list,text) . It converts one list of words (separated by spaces) to another. var is set to each word in list, and text is expanded for each word. This appends an exclamation after each word:

if checks if the first argument is nonempty. If so, runs the second argument, otherwise runs the third.

Make supports creating basic functions. You "define" the function just by creating a variable, but use the parameters $(0) , $(1) , etc. You then call the function with the special call builtin function. The syntax is $(call variable,param,param) . $(0) is the variable, while $(1) , $(2) , etc. are the params.

shell - This calls the shell, but it replaces newlines with spaces!

The include directive tells make to read one or more other makefiles. It's a line in the makefile that looks like this:

This is particularly useful when you use compiler flags like -M that create Makefiles based on the source. For example, if some c files includes a header, that header will be added to a Makefile that's written by gcc. I talk about this more in the Makefile Cookbook

Use vpath to specify where some set of prerequisites exist. The format is vpath <pattern> <directories, space/colon separated> <pattern> can have a % , which matches any zero or more characters. You can also do this globallyish with the variable VPATH

The backslash ("\") character gives us the ability to use multiple lines when the commands are too long

Adding .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. Technically, I should have used it in every example with all or clean , but I didn't to keep the examples clean. Additionally, "phony" targets typically have names that are rarely file names, and in practice many people skip this.

The make tool will stop running a rule (and will propogate back to prerequisites) if a command returns a nonzero exit status. 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.

Let's go through a really juicy Make example that works well for medium sized projects.

The neat thing about this makefile is it automatically determines dependencies for you. All you have to do is put your C/C++ files in the src/ folder.

Next: Rules , Previous: Introduction , Up: Top   [ Contents ][ Index ]

3 Writing Makefiles

The information that tells make how to recompile a system comes from reading a data base called the makefile .

Next: Makefile Names , Previous: Makefiles , Up: Makefiles   [ Contents ][ Index ]

3.1 What Makefiles Contain

Makefiles contain five kinds of things: explicit rules , implicit rules , variable definitions , directives , and comments . Rules, variables, and directives are described at length in later chapters.

  • An explicit rule says when and how to remake one or more files, called the rule’s targets . It lists the other files that the targets depend on, called the prerequisites of the target, and may also give a recipe to use to create or update the targets. See Writing Rules .
  • An implicit rule says when and how to remake a class of files based on their names. It describes how a target may depend on a file with a name similar to the target and gives a recipe to create or update such a target. See Using Implicit Rules .
  • A variable definition is a line that specifies a text string value for a variable that can be substituted into the text later. The simple makefile example shows a variable definition for objects as a list of all object files (see Variables Make Makefiles Simpler ).
  • Reading another makefile (see Including Other Makefiles ).
  • Deciding (based on the values of variables) whether to use or ignore a part of the makefile (see Conditional Parts of Makefiles ).
  • Defining a variable from a verbatim string containing multiple lines (see Defining Multi-Line Variables ).

You cannot use comments within variable references or function calls: any instance of # will be treated literally (rather than as the start of a comment) inside a variable reference or function call.

Comments within a recipe are passed to the shell, just as with any other recipe text. The shell decides how to interpret it: whether or not this is a comment is up to the shell.

Within a define directive, comments are not ignored during the definition of the variable, but rather kept intact in the value of the variable. When the variable is expanded they will either be treated as make comments or as recipe text, depending on the context in which the variable is evaluated.

Previous: Makefile Contents , Up: Makefile Contents   [ Contents ][ Index ]

3.1.1 Splitting Long Lines

Makefiles use a “line-based” syntax in which the newline character is special and marks the end of a statement. GNU make has no limit on the length of a statement line, up to the amount of memory in your computer.

However, it is difficult to read lines which are too long to display without wrapping or scrolling. So, you can format your makefiles for readability by adding newlines into the middle of a statement: you do this by escaping the internal newlines with a backslash ( \ ) character. Where we need to make a distinction we will refer to “physical lines” as a single line ending with a newline (regardless of whether it is escaped) and a “logical line” being a complete statement including all escaped newlines up to the first non-escaped newline.

The way in which backslash/newline combinations are handled depends on whether the statement is a recipe line or a non-recipe line. Handling of backslash/newline in a recipe line is discussed later (see Splitting Recipe Lines ).

Outside of recipe lines, backslash/newlines are converted into a single space character. Once that is done, all whitespace around the backslash/newline is condensed into a single space: this includes all whitespace preceding the backslash, all whitespace at the beginning of the line after the backslash/newline, and any consecutive backslash/newline combinations.

If the .POSIX special target is defined then backslash/newline handling is modified slightly to conform to POSIX.2: first, whitespace preceding a backslash is not removed and second, consecutive backslash/newlines are not condensed.

Splitting Without Adding Whitespace

If you need to split a line but do not want any whitespace added, you can utilize a subtle trick: replace your backslash/newline pairs with the three characters dollar sign/backslash/newline:

After make removes the backslash/newline and condenses the following line into a single space, this is equivalent to:

Then make will perform variable expansion. The variable reference ‘ $ ’ refers to a variable with the one-character name “ ” (space) which does not exist, and so expands to the empty string, giving a final assignment which is the equivalent of:

Next: Include , Previous: Makefile Contents , Up: Makefiles   [ Contents ][ Index ]

3.2 What Name to Give Your Makefile

By default, when make looks for the makefile, it tries the following names, in order: GNUmakefile , makefile and Makefile .

Normally you should call your makefile either makefile or Makefile . (We recommend Makefile because it appears prominently near the beginning of a directory listing, right near other important files such as README .) The first name checked, GNUmakefile , is not recommended for most makefiles. You should use this name if you have a makefile that is specific to GNU make , and will not be understood by other versions of make . Other make programs look for makefile and Makefile , but not GNUmakefile .

If make finds none of these names, it does not use any makefile. Then you must specify a goal with a command argument, and make will attempt to figure out how to remake it using only its built-in implicit rules. See Using Implicit Rules .

If you want to use a nonstandard name for your makefile, you can specify the makefile name with the ‘ -f ’ or ‘ --file ’ option. The arguments ‘ -f   name ’ or ‘ --file= name ’ tell make to read the file name as the makefile. If you use more than one ‘ -f ’ or ‘ --file ’ option, you can specify several makefiles. All the makefiles are effectively concatenated in the order specified. The default makefile names GNUmakefile , makefile and Makefile are not checked automatically if you specify ‘ -f ’ or ‘ --file ’.

Next: MAKEFILES Variable , Previous: Makefile Names , Up: Makefiles   [ Contents ][ Index ]

3.3 Including Other Makefiles

The include directive tells make to suspend reading the current makefile and read one or more other makefiles before continuing. The directive is a line in the makefile that looks like this:

filenames can contain shell file name patterns. If filenames is empty, nothing is included and no error is printed.

Extra spaces are allowed and ignored at the beginning of the line, but the first character must not be a tab (or the value of .RECIPEPREFIX )—if the line begins with a tab, it will be considered a recipe line. Whitespace is required between include and the file names, and between file names; extra whitespace is ignored there and at the end of the directive. A comment starting with ‘ # ’ is allowed at the end of the line. If the file names contain any variable or function references, they are expanded. See How to Use Variables .

For example, if you have three .mk files, a.mk , b.mk , and c.mk , and $(bar) expands to bish bash , then the following expression

is equivalent to

When make processes an include directive, it suspends reading of the containing makefile and reads from each listed file in turn. When that is finished, make resumes reading the makefile in which the directive appears.

One occasion for using include directives is when several programs, handled by individual makefiles in various directories, need to use a common set of variable definitions (see Setting Variables ) or pattern rules (see Defining and Redefining Pattern Rules ).

Another such occasion is when you want to generate prerequisites from source files automatically; the prerequisites can be put in a file that is included by the main makefile. This practice is generally cleaner than that of somehow appending the prerequisites to the end of the main makefile as has been traditionally done with other versions of make . See Automatic Prerequisites .

If the specified name does not start with a slash, and the file is not found in the current directory, several other directories are searched. First, any directories you have specified with the ‘ -I ’ or ‘ --include-dir ’ option are searched (see Summary of Options ). Then the following directories (if they exist) are searched, in this order: prefix /include (normally /usr/local/include 1 ) /usr/gnu/include , /usr/local/include , /usr/include .

If an included makefile cannot be found in any of these directories, a warning message is generated, but it is not an immediately fatal error; processing of the makefile containing the include continues. Once it has finished reading makefiles, make will try to remake any that are out of date or don’t exist. See How Makefiles Are Remade . Only after it has tried to find a way to remake a makefile and failed, will make diagnose the missing makefile as a fatal error.

If you want make to simply ignore a makefile which does not exist or cannot be remade, with no error message, use the -include directive instead of include , like this:

This acts like include in every way except that there is no error (not even a warning) if any of the filenames (or any prerequisites of any of the filenames ) do not exist or cannot be remade.

For compatibility with some other make implementations, sinclude is another name for -include .

Next: Remaking Makefiles , Previous: Include , Up: Makefiles   [ Contents ][ Index ]

3.4 The Variable MAKEFILES

If the environment variable MAKEFILES is defined, make considers its value as a list of names (separated by whitespace) of additional makefiles to be read before the others. This works much like the include directive: various directories are searched for those files (see Including Other Makefiles ). In addition, the default goal is never taken from one of these makefiles (or any makefile included by them) and it is not an error if the files listed in MAKEFILES are not found.

The main use of MAKEFILES is in communication between recursive invocations of make (see Recursive Use of make ). It usually is not desirable to set the environment variable before a top-level invocation of make , because it is usually better not to mess with a makefile from outside. However, if you are running make without a specific makefile, a makefile in MAKEFILES can do useful things to help the built-in implicit rules work better, such as defining search paths (see Directory Search ).

Some users are tempted to set MAKEFILES in the environment automatically on login, and program makefiles to expect this to be done. This is a very bad idea, because such makefiles will fail to work if run by anyone else. It is much better to write explicit include directives in the makefiles. See Including Other Makefiles .

Next: Overriding Makefiles , Previous: MAKEFILES Variable , Up: Makefiles   [ Contents ][ Index ]

3.5 How Makefiles Are Remade

Sometimes makefiles can be remade from other files, such as RCS or SCCS files. If a makefile can be remade from other files, you probably want make to get an up-to-date version of the makefile to read in.

To this end, after reading in all makefiles make will consider each as a goal target and attempt to update it. If a makefile has a rule which says how to update it (found either in that very makefile or in another one) or if an implicit rule applies to it (see Using Implicit Rules ), it will be updated if necessary. After all makefiles have been checked, if any have actually been changed, make starts with a clean slate and reads all the makefiles over again. (It will also attempt to update each of them over again, but normally this will not change them again, since they are already up to date.) Each restart will cause the special variable MAKE_RESTARTS to be updated (see Special Variables ).

If you know that one or more of your makefiles cannot be remade and you want to keep make from performing an implicit rule search on them, perhaps for efficiency reasons, you can use any normal method of preventing implicit rule look-up to do so. For example, you can write an explicit rule with the makefile as the target, and an empty recipe (see Using Empty Recipes ).

If the makefiles specify a double-colon rule to remake a file with a recipe but no prerequisites, that file will always be remade (see Double-Colon ). In the case of makefiles, a makefile that has a double-colon rule with a recipe but no prerequisites will be remade every time make is run, and then again after make starts over and reads the makefiles in again. This would cause an infinite loop: make would constantly remake the makefile, and never do anything else. So, to avoid this, make will not attempt to remake makefiles which are specified as targets of a double-colon rule with a recipe but no prerequisites.

If you do not specify any makefiles to be read with ‘ -f ’ or ‘ --file ’ options, make will try the default makefile names; see What Name to Give Your Makefile . Unlike makefiles explicitly requested with ‘ -f ’ or ‘ --file ’ options, make is not certain that these makefiles should exist. However, if a default makefile does not exist but can be created by running make rules, you probably want the rules to be run so that the makefile can be used.

Therefore, if none of the default makefiles exists, make will try to make each of them in the same order in which they are searched for (see What Name to Give Your Makefile ) until it succeeds in making one, or it runs out of names to try. Note that it is not an error if make cannot find or make any makefile; a makefile is not always necessary.

When you use the ‘ -t ’ or ‘ --touch ’ option (see Instead of Executing Recipes ), you would not want to use an out-of-date makefile to decide which targets to touch. So the ‘ -t ’ option has no effect on updating makefiles; they are really updated even if ‘ -t ’ is specified. Likewise, ‘ -q ’ (or ‘ --question ’) and ‘ -n ’ (or ‘ --just-print ’) do not prevent updating of makefiles, because an out-of-date makefile would result in the wrong output for other targets. Thus, ‘ make -f mfile -n foo ’ will update mfile , read it in, and then print the recipe to update foo and its prerequisites without running it. The recipe printed for foo will be the one specified in the updated contents of mfile .

However, on occasion you might actually wish to prevent updating of even the makefiles. You can do this by specifying the makefiles as goals in the command line as well as specifying them as makefiles. When the makefile name is specified explicitly as a goal, the options ‘ -t ’ and so on do apply to them.

Thus, ‘ make -f mfile -n mfile foo ’ would read the makefile mfile , print the recipe needed to update it without actually running it, and then print the recipe needed to update foo without running that. The recipe for foo will be the one specified by the existing contents of mfile .

Next: Reading Makefiles , Previous: Remaking Makefiles , Up: Makefiles   [ Contents ][ Index ]

3.6 Overriding Part of Another Makefile

Sometimes it is useful to have a makefile that is mostly just like another makefile. You can often use the ‘ include ’ directive to include one in the other, and add more targets or variable definitions. However, it is invalid for two makefiles to give different recipes for the same target. But there is another way.

In the containing makefile (the one that wants to include the other), you can use a match-anything pattern rule to say that to remake any target that cannot be made from the information in the containing makefile, make should look in another makefile. See Pattern Rules , for more information on pattern rules.

For example, if you have a makefile called Makefile that says how to make the target ‘ foo ’ (and other targets), you can write a makefile called GNUmakefile that contains:

If you say ‘ make foo ’, make will find GNUmakefile , read it, and see that to make foo , it needs to run the recipe ‘ frobnicate > foo ’. If you say ‘ make bar ’, make will find no way to make bar in GNUmakefile , so it will use the recipe from the pattern rule: ‘ make -f Makefile bar ’. If Makefile provides a rule for updating bar , make will apply the rule. And likewise for any other target that GNUmakefile does not say how to make.

The way this works is that the pattern rule has a pattern of just ‘ % ’, so it matches any target whatever. The rule specifies a prerequisite force , to guarantee that the recipe will be run even if the target file already exists. We give the force target an empty recipe to prevent make from searching for an implicit rule to build it—otherwise it would apply the same match-anything rule to force itself and create a prerequisite loop!

Next: Parsing Makefiles , Previous: Overriding Makefiles , Up: Makefiles   [ Contents ][ Index ]

3.7 How make Reads a Makefile

GNU make does its work in two distinct phases. During the first phase it reads all the makefiles, included makefiles, etc. and internalizes all the variables and their values and implicit and explicit rules, and builds a dependency graph of all the targets and their prerequisites. During the second phase, make uses this internalized data to determine which targets need to be updated and run the recipes necessary to update them.

It’s important to understand this two-phase approach because it has a direct impact on how variable and function expansion happens; this is often a source of some confusion when writing makefiles. Below is a summary of the different constructs that can be found in a makefile, and the phase in which expansion happens for each part of the construct.

We say that expansion is immediate if it happens during the first phase: make will expand that part of the construct as the makefile is parsed. We say that expansion is deferred if it is not immediate. Expansion of a deferred construct part is delayed until the expansion is used: either when it is referenced in an immediate context, or when it is needed during the second phase.

You may not be familiar with some of these constructs yet. You can reference this section as you become familiar with them, in later chapters.

Variable Assignment

Variable definitions are parsed as follows:

For the append operator ‘ += ’, the right-hand side is considered immediate if the variable was previously set as a simple variable (‘ := ’ or ‘ ::= ’), and deferred otherwise.

For the shell assignment operator ‘ != ’, the right-hand side is evaluated immediately and handed to the shell. The result is stored in the variable named on the left, and that variable becomes a simple variable (and will thus be re-evaluated on each reference).

Conditional Directives

Conditional directives are parsed immediately. This means, for example, that automatic variables cannot be used in conditional directives, as automatic variables are not set until the recipe for that rule is invoked. If you need to use automatic variables in a conditional directive you must move the condition into the recipe and use shell conditional syntax instead.

Rule Definition

A rule is always expanded the same way, regardless of the form:

That is, the target and prerequisite sections are expanded immediately, and the recipe used to build the target is always deferred. This is true for explicit rules, pattern rules, suffix rules, static pattern rules, and simple prerequisite definitions.

Next: Secondary Expansion , Previous: Reading Makefiles , Up: Makefiles   [ Contents ][ Index ]

3.8 How Makefiles Are Parsed

GNU make parses makefiles line-by-line. Parsing proceeds using the following steps:

  • Read in a full logical line, including backslash-escaped lines (see Splitting Long Lines ).
  • Remove comments (see What Makefiles Contain ).
  • If the line begins with the recipe prefix character and we are in a rule context, add the line to the current recipe and read the next line (see Recipe Syntax ).
  • Expand elements of the line which appear in an immediate expansion context (see How make Reads a Makefile ).
  • Scan the line for a separator character, such as ‘ : ’ or ‘ = ’, to determine whether the line is a macro assignment or a rule (see Recipe Syntax ).
  • Internalize the resulting operation and read the next line.

An important consequence of this is that a macro can expand to an entire rule, if it is one line long . This will work:

However, this will not work because make does not re-split lines after it has expanded them:

The above makefile results in the definition of a target ‘ target ’ with prerequisites ‘ echo ’ and ‘ built ’, as if the makefile contained target: echo built , rather than a rule with a recipe. Newlines still present in a line after expansion is complete are ignored as normal whitespace.

In order to properly expand a multi-line macro you must use the eval function: this causes the make parser to be run on the results of the expanded macro (see Eval Function ).

Previous: Parsing Makefiles , Up: Makefiles   [ Contents ][ Index ]

3.9 Secondary Expansion

Previously we learned that GNU make works in two distinct phases: a read-in phase and a target-update phase (see How make Reads a Makefile ). GNU make also has the ability to enable a second expansion of the prerequisites (only) for some or all targets defined in the makefile. In order for this second expansion to occur, the special target .SECONDEXPANSION must be defined before the first prerequisite list that makes use of this feature.

If that special target is defined then in between the two phases mentioned above, right at the end of the read-in phase, all the prerequisites of the targets defined after the special target are expanded a second time . In most circumstances this secondary expansion will have no effect, since all variable and function references will have been expanded during the initial parsing of the makefiles. In order to take advantage of the secondary expansion phase of the parser, then, it’s necessary to escape the variable or function reference in the makefile. In this case the first expansion merely un-escapes the reference but doesn’t expand it, and expansion is left to the secondary expansion phase. For example, consider this makefile:

After the first expansion phase the prerequisites list of the myfile target will be onefile and $(TWOVAR) ; the first (unescaped) variable reference to ONEVAR is expanded, while the second (escaped) variable reference is simply unescaped, without being recognized as a variable reference. Now during the secondary expansion the first word is expanded again but since it contains no variable or function references it remains the value onefile , while the second word is now a normal reference to the variable TWOVAR , which is expanded to the value twofile . The final result is that there are two prerequisites, onefile and twofile .

Obviously, this is not a very interesting case since the same result could more easily have been achieved simply by having both variables appear, unescaped, in the prerequisites list. One difference becomes apparent if the variables are reset; consider this example:

Here the prerequisite of onefile will be expanded immediately, and resolve to the value top , while the prerequisite of twofile will not be full expanded until the secondary expansion and yield a value of bottom .

This is marginally more exciting, but the true power of this feature only becomes apparent when you discover that secondary expansions always take place within the scope of the automatic variables for that target. This means that you can use variables such as $@ , $* , etc. during the second expansion and they will have their expected values, just as in the recipe. All you have to do is defer the expansion by escaping the $ . Also, secondary expansion occurs for both explicit and implicit (pattern) rules. Knowing this, the possible uses for this feature increase dramatically. For example:

Here, after the initial expansion the prerequisites of both the main and lib targets will be $($@_OBJS) . During the secondary expansion, the $@ variable is set to the name of the target and so the expansion for the main target will yield $(main_OBJS) , or main.o try.o test.o , while the secondary expansion for the lib target will yield $(lib_OBJS) , or lib.o api.o .

You can also mix in functions here, as long as they are properly escaped:

This version allows users to specify source files rather than object files, but gives the same resulting prerequisites list as the previous example.

Evaluation of automatic variables during the secondary expansion phase, especially of the target name variable $$@ , behaves similarly to evaluation within recipes. However, there are some subtle differences and “corner cases” which come into play for the different types of rule definitions that make understands. The subtleties of using the different automatic variables are described below.

Secondary Expansion of Explicit Rules

During the secondary expansion of explicit rules, $$@ and $$% evaluate, respectively, to the file name of the target and, when the target is an archive member, the target member name. The $$< variable evaluates to the first prerequisite in the first rule for this target. $$^ and $$+ evaluate to the list of all prerequisites of rules that have already appeared for the same target ( $$+ with repetitions and $$^ without). The following example will help illustrate these behaviors:

In the first prerequisite list, all three variables ( $$< , $$^ , and $$+ ) expand to the empty string. In the second, they will have values foo.1 , foo.1 bar.1 , and foo.1 bar.1 respectively. In the third they will have values foo.1 , foo.1 bar.1 foo.2 bar.2 , and foo.1 bar.1 foo.2 bar.2 foo.1 foo.1 bar.1 foo.1 bar.1 respectively.

Rules undergo secondary expansion in makefile order, except that the rule with the recipe is always evaluated last.

The variables $$? and $$* are not available and expand to the empty string.

Secondary Expansion of Static Pattern Rules

Rules for secondary expansion of static pattern rules are identical to those for explicit rules, above, with one exception: for static pattern rules the $$* variable is set to the pattern stem. As with explicit rules, $$? is not available and expands to the empty string.

Secondary Expansion of Implicit Rules

As make searches for an implicit rule, it substitutes the stem and then performs secondary expansion for every rule with a matching target pattern. The value of the automatic variables is derived in the same fashion as for static pattern rules. As an example:

When the implicit rule is tried for target foo , $$< expands to bar , $$^ expands to bar boo , $$+ also expands to bar boo , and $$* expands to f .

Note that the directory prefix (D), as described in Implicit Rule Search Algorithm , is appended (after expansion) to all the patterns in the prerequisites list. As an example:

The prerequisite list printed, after the secondary expansion and directory prefix reconstruction, will be /tmp/foo/foo.c /tmp/bar/foo.c foo.h . If you are not interested in this reconstruction, you can use $$* instead of % in the prerequisites list.

GNU Make compiled for MS-DOS and MS-Windows behaves as if prefix has been defined to be the root of the DJGPP tree hierarchy.

Change the hostname of your AL2 instance

When you launch an instance into a private VPC, Amazon EC2 assigns a guest OS hostname. The type of hostname that Amazon EC2 assigns depends on your subnet settings. For more information about EC2 hostnames, see Amazon EC2 instance hostname types in the Amazon EC2 User Guide for Linux Instances .

A typical Amazon EC2 private DNS name for an EC2 instance configured to use IP-based naming with an IPv4 address looks something like this: ip-12-34-56-78.us-west-2.compute.internal , where the name consists of the internal domain, the service (in this case, compute ), the region, and a form of the private IPv4 address. Part of this hostname is displayed at the shell prompt when you log into your instance (for example, ip-12-34-56-78 ). Each time you stop and restart your Amazon EC2 instance (unless you are using an Elastic IP address), the public IPv4 address changes, and so does your public DNS name, system hostname, and shell prompt.

This information applies to Amazon Linux. For information about other distributions, see their specific documentation.

Change the system hostname

If you have a public DNS name registered for the IP address of your instance (such as webserver.mydomain.com ), you can set the system hostname so your instance identifies itself as a part of that domain. This also changes the shell prompt so that it displays the first portion of this name instead of the hostname supplied by AWS (for example, ip-12-34-56-78 ). If you do not have a public DNS name registered, you can still change the hostname, but the process is a little different.

In order for your hostname update to persist, you must verify that the preserve_hostname cloud-init setting is set to true . You can run the following command to edit or add this setting:

If the preserve_hostname setting is not listed, add the following line of text to the end of the file:

To change the system hostname to a public DNS name

Follow this procedure if you already have a public DNS name registered.

For AL2: Use the hostnamectl command to set your hostname to reflect the fully qualified domain name (such as webserver.mydomain.com ).

For Amazon Linux AMI: On your instance, open the /etc/sysconfig/network configuration file in your favorite text editor and change the HOSTNAME entry to reflect the fully qualified domain name (such as webserver.mydomain.com ).

Reboot the instance to pick up the new hostname.

Alternatively, you can reboot using the Amazon EC2 console (on the Instances page, select the instance and choose Instance state , Reboot instance ).

Log into your instance and verify that the hostname has been updated. Your prompt should show the new hostname (up to the first ".") and the hostname command should show the fully-qualified domain name.

To change the system hostname without a public DNS name

For AL2: Use the hostnamectl command to set your hostname to reflect the desired system hostname (such as webserver ).

For Amazon Linux AMI: On your instance, open the /etc/sysconfig/network configuration file in your favorite text editor and change the HOSTNAME entry to reflect the desired system hostname (such as webserver ).

Open the /etc/hosts file in your favorite text editor and change the entry beginning with 127.0.0.1 to match the example below, substituting your own hostname.

You can also implement more programmatic solutions, such as specifying user data to configure your instance. If your instance is part of an Auto Scaling group, you can use lifecycle hooks to define user data. For more information, see Run commands on your Linux instance at launch and Lifecycle hook for instance launch in the AWS CloudFormation User Guide .

Change the shell prompt without affecting the hostname

If you do not want to modify the hostname for your instance, but you would like to have a more useful system name (such as webserver ) displayed than the private name supplied by AWS (for example, ip-12-34-56-78 ), you can edit the shell prompt configuration files to display your system nickname instead of the hostname.

To change the shell prompt to a host nickname

Create a file in /etc/profile.d that sets the environment variable called NICKNAME to the value you want in the shell prompt. For example, to set the system nickname to webserver , run the following command.

Open the /etc/bashrc (Red Hat) or /etc/bash.bashrc (Debian/Ubuntu) file in your favorite text editor (such as vim or nano ). You need to use sudo with the editor command because /etc/bashrc and /etc/bash.bashrc are owned by root .

Edit the file and change the shell prompt variable ( PS1 ) to display your nickname instead of the hostname. Find the following line that sets the shell prompt in /etc/bashrc or /etc/bash.bashrc (several surrounding lines are shown below for context; look for the line that starts with [ "$PS1" ):

Change the \h (the symbol for hostname ) in that line to the value of the NICKNAME variable.

(Optional) To set the title on shell windows to the new nickname, complete the following steps.

Create a file named /etc/sysconfig/bash-prompt-xterm .

Make the file executable using the following command.

Open the /etc/sysconfig/bash-prompt-xterm file in your favorite text editor (such as vim or nano ). You need to use sudo with the editor command because /etc/sysconfig/bash-prompt-xterm is owned by root .

Add the following line to the file.

Log out and then log back in to pick up the new nickname value.

Change the hostname on other Linux distributions

The procedures on this page are intended for use with Amazon Linux only. For more information about other Linux distributions, see their specific documentation and the following articles:

How do I assign a static hostname to a private Amazon EC2 instance running RHEL 7 or Centos 7?

Warning

To use the Amazon Web Services Documentation, Javascript must be enabled. Please refer to your browser's Help pages for instructions.

Thanks for letting us know we're doing a good job!

If you've got a moment, please tell us what we did right so we can do more of it.

Thanks for letting us know this page needs work. We're sorry we let you down.

If you've got a moment, please tell us how we can make the documentation better.

Previous: Immediately Expanded Variable Assignment , Up: The Two Flavors of Variables   [ Contents ][ Index ]

6.2.4 Conditional Variable Assignment

There is another assignment operator for variables, ‘ ?= ’. This is called a conditional variable assignment operator, because it only has an effect if the variable is not yet defined. This statement:

is exactly equivalent to this (see The origin Function ):

Note that a variable set to an empty value is still defined, so ‘ ?= ’ will not set that variable.

IMAGES

  1. Makefiles in Linux: An Overview

    makefile variable assignment syntax

  2. Introduction to Make and Makefile

    makefile variable assignment syntax

  3. How to Write a Makefile with Ease

    makefile variable assignment syntax

  4. C makefile example

    makefile variable assignment syntax

  5. PPT

    makefile variable assignment syntax

  6. Ejemplo simple de makefile

    makefile variable assignment syntax

VIDEO

  1. [Algorithm Session 01]

  2. 6 storing values in variable, assignment statement

  3. 27. Three Address Code for Assignment Statements Using SDT(Syntax Direct Translation)

  4. What are Variables in Python

  5. C++ Linux Tutorial

  6. C++ Variables, Literals, an Assignment Statements [2]

COMMENTS

  1. Using Variables (GNU make)

    A variable is a name defined in a makefile to represent a string of text, called the variable's value. These values are substituted by explicit request into targets, prerequisites, recipes, and other parts of the makefile. (In some other versions of make , variables are called macros .) Variables and functions in all parts of a makefile are ...

  2. What is the difference between the GNU Makefile variable assignments

    The syntax to assign multiline value to a variable is: define VAR_NAME := line line endef or. define VAR_NAME = line line endef Assignment operator can be omitted, then it creates a recursively-expanded variable. define VAR_NAME line line endef The last newline before endef is removed. Bonus: the shell assignment operator '!=' HASH ...

  3. Understanding and Using Makefile Variables

    The following is an example of a variable definition: foo = World. Any white space before the variable's value is stripped away, but white spaces at the end are preserved. ... If there's an explicit assignment in the makefile to a variable, it overrides any environment variable with the same name: USER = Bob all: @ echo ${USER}

  4. Using Variables (GNU make)

    A variable is a name defined in a makefile to represent a string of text, called the variable's value. These values are substituted by explicit request into targets, prerequisites, recipes, and other parts of the makefile. (In some other versions of make , variables are called macros .) Variables and functions in all parts of a makefile are ...

  5. Quick Reference (GNU make)

    See Including Other Makefiles. override variable-assignment. Define a variable, overriding any previous definition, even one from the command line. See The override Directive. export. Tell make to export all variables to child processes by default. See Communicating Variables to a Sub-make. export variable export variable-assignment unexport ...

  6. GNU make

    The simple makefile example shows a variable definition for objects as a list of all object files (see Variables Make Makefiles Simpler). A directive is an instruction for make to do something special while reading the makefile. These include: ... Variable Assignment. Variable definitions are parsed as follows:

  7. GNU make

    GNU make - How to Use Variables. Go to the first, previous, next, last section, table of contents . How to Use Variables. A variable is a name defined in a makefile to represent a string of text, called the variable's value. These values are substituted by explicit request into targets, prerequisites, commands, and other parts of the makefile.

  8. Makefile Tutorial By Example

    Makefile Syntax. A Makefile consists of a set of rules. A rule generally looks like this: targets: prerequisites command command command. The targets are file names, separated by spaces. Typically, there is only one per rule. ... The syntax is $(call variable,param,param). $(0) is the variable, while $(1), $(2), etc. are the params.

  9. Makefiles (GNU make)

    The simple makefile example shows a variable definition for objects as a list of all object files (see Variables Make Makefiles Simpler). A directive is an instruction for make to do something special while reading the makefile. These include: ... Variable Assignment. Variable definitions are parsed as follows:

  10. How to assign the output of a command to a Makefile variable

    With GNU Make, you can use shell and eval to store, run, and assign output from arbitrary command line invocations. The difference between the example below and those which use := is the := assignment happens once (when it is encountered) and for all. Recursively expanded variables set with = are a bit more "lazy"; references to other variables remain until the variable itself is referenced ...

  11. Variables in makefiles

    Variables in makefiles. Variables in a makefile work much the same as variables in a shell script. They are words to which a string of characters can be assigned. Once a string has been assigned to the variable, every reference to the variable in the rest of the makefile is replaced by the string. Variable names are usually chosen to be in all ...

  12. The Conditional Variable Assignment Operator in a Makefile

    Let's define a user variable and initialize it with the output of the whoami command by using the assignment (=) operator: user=$(shell whoami) We should note that we followed a standard naming convention of using lowercase letters in the variable name because the variable's scope is limited to the Makefile.

  13. Makefile Variables Are Complicated

    Earthly https://earthly.dev/youtubeIn this video I'm going to show you how variables work in make files. It might seem like a simple topic, but actually, i...

  14. GNU Make

    You can specify a value in the makefile, either with an assignment (see section Setting Variables) or with a verbatim definition (see section Defining Variables Verbatim). Variables in the environment become make variables. See section Variables from the Environment. Several automatic variables are given new values for each rule. Each of these ...

  15. how to include bash indirect variable assignment in Makefile

    0. Indirect variable setting in bash can be done like so: Trying to run the same as a (GNU) Makefile recipe. foo=bar. ind=foo. echo $$\{!ind\} echo $${!ind} both with and without escaping the {} characters fails with the following message: The problem is probably some missing/wrong escaping of Makefile's special characters.

  16. Change the hostname of your AL2 instance

    Change the system hostname. If you have a public DNS name registered for the IP address of your instance (such as webserver.mydomain.com), you can set the system hostname so your instance identifies itself as a part of that domain.This also changes the shell prompt so that it displays the first portion of this name instead of the hostname supplied by AWS (for example, ip-12-34-56-78).

  17. How to assign value to variable in Makefile?

    In trying to test for the failure of a command in a Makefile (in this case jekyll build relative), the variable $$? should contain the exit code of the last command. In testing, this code is shown to be 127. However, I would like to assign it to the variable LAST_EXIT so that an the next if statement can check whether the executed command succeeded or failed.

  18. Conditional Assignment (GNU make)

    Conditional Assignment (GNU make) Previous: Immediately Expanded Variable Assignment , Up: The Two Flavors of Variables [ Contents ][ Index ] 6.2.4 Conditional Variable Assignment

  19. makefile

    We say that expansion is immediate if it happens during the first phase: in this case make will expand any variables or functions in that section of a construct as the makefile is parsed. immediate := immediate. immediate += deferred or immediate. For the append operator, '+=', the right-hand side is considered immediate if the variable was ...