1. Overview
Make is a de-facto tool for building and running software projects. In this article, we’ll learn about the conditional variable assignment operator (?=) using a simple use case.
2. Setup
Let’s start by writing a simple Makefile and adding a target called greet:
greet:
@echo "Hello! I'm make utility. I'll help you run this project."
Now, let’s use the make command to execute the greet target:
$ make greet
Hello! I'm make utility. I'll help you run this project.
We should note that we used the @ prefix before the target definition. That instructs the Make tool to suppress the command definition while showing the output and limiting the output to the result of the executed command.
Great! We’ve got a basic setup ready with us. We’ll extend this Makefile in the next section by using variable definitions.
3. Variables in a Makefile
So far, the greeting shown to the user by our Makefile is a static text, so all users get the same greeting message. To make it dynamic, let’s include the login username in the message so that the greeting is more personalized for each user.
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.
Further, let’s now use this variable in the greet target by referencing this variable using the $() operator:
greet:
@echo "Hello," $(user)"! I'm make utility. I'll help you run this project."
Next, let’s see the revised greeting in action by executing the greet target again:
$ make greet
Hello, tavasthi! I'm make utility. I'll help you run this project.
It looks like we’ve got it right!
4. Using the Conditional Variable Assignment Operator (?=)
Now that we understand the basics of using a variable in a Makefile, we’ll be more comfortable understanding the ?= operator, which is used for conditional variable assignment in a Makefile.
To that end, let’s extend our Makefile by allowing the user to specify the username to be mentioned in the greeting instead of using the login name. However, we want to keep this optional, so if the user doesn’t specify the value, we still resort to the default behavior of using the login name.
As part of the refactoring exercise, we need to use the ?= operator in place of the = operator so that we don’t override the value if the variable already holds a value. Secondly, we’ll now use uppercase letters in the variable name because we’re extending its scope by letting the user define it from the outside:
USER?=$(shell whoami)
greet:
@echo "Hello," $(USER)"! I'm make utility. I'll help you run this project."
Next, let’s see the two scenarios in action:
$ make greet USER="Tapan Avasthi"
Hello, Tapan Avasthi! I'm make utility. I'll help you run this project.
$ make greet
Hello, tavasthi! I'm make utility. I'll help you run this project.
In the first scenario, we must note that we passed the USER variable’s value as an argument to the make command to get a custom username. On the other hand, in the second scenario, we didn’t pass the value of the USER variable, so we got the default login name in the greeting message.
Fairly straightforward, right? That’s all we need to know for using the conditional operator to create an effective Makefile for our projects.
5. Conclusion
In this tutorial, we took a step-by-step approach to learn about the conditional variable assignment in a Makefile. We first understood the basics of using variables in a Makefile, followed by using the ?= operator for a more advanced use case.