Linux make command

The Linux make command is used to build and maintain groups of programs and files from the source code. In Linux, it is one of the most frequently used commands by the developers. It assists developers to install and compile many utilities from the terminal. Further, it handles the compilation process of the sizeable projects. It saves the compilation time.

The main motive of the make command is to determine a large program into parts and to check whether it needs to be recompiled or not. Also, it issues the necessary orders to recompile them.

In this section, we will use C++ programs since the C++ programming language is an object-oriented language, but you can use any language installed on your machine. It is not just limited to programs; we can use it to describe other tasks also.

How make command works?

The make command takes targets as arguments. These arguments are specified in 'Makefile.' The makefile contains the targets as well as associated actions related to these targets.

When we execute the make command, it searches for the makefile and scans it to find the target and access its dependencies. If dependencies are not specified, it will search for the dependency and will build it. It will build the main target after the dependencies are built.

For example, if we want to change only one source file and we execute the make command; so, this will compile only the object file that is connected with that source file. It will save a lot of time in the final compilation of the project.

What is Makefile?

The make command invokes the execution of the makefile. It is a special file that contains the shell commands that we create to maintain the project. The makefile contains targets and commands for execution. It is not allowed to create more than one makefile. It is recommended to create a separate directory for it.

It keeps track of recent files, so only update those files which are required. If we have a large program with many source files, we must recompile all the dependent files. So, it may be an extremely time taking process.

The makefile has a list of standards. These standards are helpful for the system to understand what command we want to execute. These standards are in two parts and separated by a new line. The first line is the dependency line, and the subsequent lines are considered as actions or commands. The commands are separated with a tab in the new line.

The dependencies specify the relation of each file with the source files. And the target is an executable file, and it is created after the execution of make command.

Options

The make command facilitates various options to make it more specific. Some important options are as follows:

  • -b, -m: These options are used to ignore the compatibility for the different versions of the make command.
  • -B, --always-make: These options are used to unconditionally make all targets.
  • -C dir, --directory=dir: These options are used to change the directory before executing the makefile.
  • -d: It is used to print the debugging information.
  • --debug[=FLAGS]: It is used to print the debugging information along with normal processing. If we skip the flag, then it will show similar results as the '-d' option.
  • -e, --environment-overrides: It is used to provide the variables taken from the environment precedence to makefile.
  • -f file, --file=file, --makefile=FILE: It is used to use a file as a makefile.
  • -i, --ignore-errors: The '-i' option is used to ignore all errors in commands.
  • -I dir, --include-dir=dir: It is used to specify a directory to search for the specified makefile. If we specify the many '-I' options, it will search in the many directories in the order are specified.
  • -j [jobs], --jobs[=jobs]: It is used to specify the number of jobs to run simultaneously. If we provide many '-j' option, the last one will be considered to execute. If we do not specify the number of jobs, it will not limit the jobs that can run simultaneously.
  • -k, --keep-going: It is used to continue the program as much as possible after getting an error.
  • -l [load], --load-average[=load]: It is used to specify that no new task should be started if other tasks are in the queue and the load average is at its minimum.
  • -n, --just-print, --dry-run, --recon: It is used to display the command that would be run.
  • -o file, --old-file=file, --assume-old=file: It is used to assure that the make will not remake the file even if it is older than its dependencies.
  • -O[type], --output-sync[=type]: It is used to confirm the output of each task is put together rather than an inter-mixed output of other tasks. It is useful for multiple job processing with the '-j' option.
  • -p, --print-data-base: It is used to print the database that produces after reading the makefiles. It is also useful to print the version information when used with the '-v' option. To print the database without trying to remake any files, execute the command as follows:
    make -p -f/dev/null.
  • -q, --question: The '-q' option is used for the Question mode. It will not run any command or print anything. It will only return an exit status is zero if the specified target is already synced; otherwise, it will display a non-zero exit status.
  • -r, --no-builtin-rules: It is used to eliminate the use of the built-in implicit rules.
  • -R, --no-builtin-variables: It is useful if we do not want to define any built-in variable.
  • -s, --silent, --quiet: These options are called Silent operation. It restricts to print the commands as they are executed.
  • -S, --no-keep-going, --stop: It is used to cancel the effect of "-k, --keep-going" operation.
  • -t, --touch: It is used to touch files instead of running their commands.
  • --trace: It is used to trace the disposition of each target.
  • -v, --version: It is used to print the installed version of the make utility. Further, it displays a list of authors, copyright, and some notice regarding the make utility.
  • -w, --print-directory: It is used to track a print message that contains a working directory before and after other processing. It is useful to track down errors from the complicated structure of recursive make command.
  • --no-print-directory: It is used to turn off the '-w' option.
  • -W file, --what-if=file, --new-file=file, --assume-new=file: These options pretend that the target file has just been modified.
  • --warn-undefined-variables: This option is used to warn that an undefined variable is referenced.

Let's understand some examples of the make command. We will see the basic use of makefile, and further, we will create some c++ programs and a makefile. We will perform some operations on them to better understand the make command.

Basic use of make command

Let's understand the very basic use of make command, and it may help you to understand how it works.

Create a directory 'project' and change directory to it. Consider the below commands:

Now create a "Makefile" having the following content for the first program:

From the above file, the say_hello is a target that behaves like a function in any programming language, and echo will be considered as an action. It must be remembered that action should be written by using a TAB. The target and action together create a rule for the makefile. Now, execute the make command as follows:

Consider the below output:

Linux make command

From the above output, we can see the echo operation itself is displaying. If we don't want to display the echo command on the output, execute the echo starting with '@' symbol. To suppress the echo, update the content of makefile as follows:

Consider the below output:

Linux make command

A target might be a binary file that depends on the actions.

Let's add a few more targets, such as generate and list in the makefile. Update the makefile as follows:

If we execute the make command, it only executes the first target because it is the default target of the makefile. Consider the below output:

Linux make command

We can change the default target by including below content to our makefile:

Add it to the first line of the file as follows:

Linux make command

The above makefile will consider 'generate' as the default goal. Execute the make command, and it will give the output as follows:

Linux make command

The DEFAULT GOAL option will execute only one target to specify more than one target to use all options. To specify more than one target, update the first line of the makefile as follows:

It will execute the specified target. Consider the below output:

Linux make command

There is another option that allows us to execute all the targets. If we want to execute all the targets of the makefile, update the file as follows:

The above file will perform all specified targets. Execute the make command, consider the below output:

Linux make command

Advanced use of the make command

Let's create a C++ project having files main.cpp, function1.cpp, function2.cpp and a dependency file function.h.

The code of the files is as following:

main.cpp:

function1.cpp:

function2.cpp:

functions.h:

Now create an executable file of the above project by executing the below command:

The above command will create an executable file 'hello' of the files main.cpp, function1.cpp and function2.cpp.

Consider the below output:

Linux make command

From the above output, if it is successfully executed, it will not give any output.

Let's perform the same task by using the makefile.

Create a file as Makefile and put the below code in it.

The all keyword is used for target and in newline put the same command with a TAB as above to specify the operation. Save the file. Consider the below file:

Linux make command

To operate, execute the command as follows:

The above command will create an executable file 'hello' of the specified files. Consider the below output:

Linux make command

Let's add some more tasks to Makefile. Add a task 'compile' as follows:

To execute the task compile, execute the below command:

The above command will execute the compile task. Consider the below output:

Linux make command

Let's perform some more tasks to our makefile.

update the Makefile as follows:

From the above makefile, we have created three objects as main.o, function1.o, and function2.o. Further, we have provided the dependencies for the targets main.o, function1.o and function2.o as main.cpp, function1.cpp and function2.cpp respectively. All the targets will perform the specified tasks within it. We have also specified a clean target to clean all the dependencies and remove the executable file.

Now execute the make all command to execute our new makefile.

Consider the below output:

Linux make command

From the above output, we can see that the command first executed the main.o, function1.o and function2.o respectively. It will create the executable and objects file of the given files. It will not execute the clean target because we have not specified it in hello. Consider the below files:

Linux make command

The make command has a straight forward working process. It executed the all option and went to hello. After the execution of hello, it read the target in the specified sequence. It searched every target and its dependency and executed them in the sequence.

To remove the objects and executable file, perform the clean task. To perform the clean task, execute the command as follows:

Consider the below output:

Linux make command

The above command will remove all the objects and executable files. See the below snap of the directory:

Linux make command

From the above image, we can see that we have cleaned our directory.

Variables in make command

We can define the variables in our makefile. To define the variables, use the '=" operator. For example, if we want to create a variable A and assign a command gcc to it, assign it as:

Use it as follows in our makefile:

It is passed to the terminal as:

We can use $(A) instead of ${A}, as both are treated the same by the script.

Comments in makefile

To add a comment into the makefile, use the '#' symbol. For example, to add a comment in the compile section, add it as "# This will compile the program." Comments are ignored by the compiler.


Next TopicGCC Linux




Latest Courses