Difference between revisions of "Make"

From UCT EE Wiki
Jump to navigation Jump to search
(Added entry)
 
(added example)
Line 31: Line 31:
 
To illustrate the process of developing a makefile, let us consider we want to make a program from the following files:
 
To illustrate the process of developing a makefile, let us consider we want to make a program from the following files:
 
<pre>
 
<pre>
   test1.c with H-file test1.h
+
   test1.c  
 +
  test1.h
 
</pre>
 
</pre>
 +
 +
i.e. test.c has H-file interface called test.h
  
 
We want to compile test1.c with gcc and we want to generate a GDB debugger compatible executable, which needs the -g flag to be specified. We want to call the generated executable test1 (an elf file, not needing extension if done on Linux). We could do this easily with just gcc:
 
We want to compile test1.c with gcc and we want to generate a GDB debugger compatible executable, which needs the -g flag to be specified. We want to call the generated executable test1 (an elf file, not needing extension if done on Linux). We could do this easily with just gcc:
Line 39: Line 42:
 
</pre>
 
</pre>
  
But this isn’t scalable. And we haven’t captured information (e.g. to future developers or users) of how to build the program.  
+
But this isn’t scalable. And we haven’t captured the information of dependencies and build process (e.g. so future developers or users will see how to build the program).
 +
 
 +
Let's quickly plan the build method for this. It would be useful to have these two processes available:
 +
 
 +
* clean process : to deletes all intermediary files and the executable.
 +
* build process (the default process) : generate the executable if any of its dependencies (as in the .c or .h files) have changed since the last attempt at building.
 +
 
 +
Here is a super simple start for the makefile, although for the sake of explaining a little more, some special variables, such as $@ and $< have been used (to save some typing) and these are explained after the example. Together with what is being done on each line.
 +
 
 +
<syntaxhighlight lang="make" line='line'>.
 +
CC=gcc
 +
# note the -g below for debugging
 +
# and note that hash symbol used for single line comments
 +
CFLAGS=-I. -g
 +
 
 +
test1.o: test1.c test1.h
 +
        $(CC) -c -o test.o $< $(CFLAGS)
 +
 
 +
test1: test1.o
 +
        $(CC) -o $@ $^ $(CFLAGS)
 +
 
 +
clean:
 +
        rm -f -r test1 test1.o
 +
</syntaxhighlight>
 +
 
  
 
= Recommended Tutorials =
 
= Recommended Tutorials =

Revision as of 08:37, 10 August 2021


Overview

Make is defined as a "build automation tool" which automatically builds executable programs, libraries or other type of target (desired file) from source code. Usually this desired 'target' is an program that you want to run. For full details on make and makefiles see the official GNU Make documentation at https://www.gnu.org/software/make/manual/make.html. Make is a way to capture and automate the build process, to capture the compile process, how the generation of intermediate files depend on other files. If you are not already familiar with the reason for using Makefiles in a project you are recommended to read the Gnu Make Overview.

Makefiles are not limited to just making executables from C / C++ or compiling of code. They can be used for generating other kinds of execution objects which might involve generating some sort of runtime environment in which the exucatable, or executables, run within.

Of course, IDEs often use a makefile or other method of compiling behind the scenes, and you may likely not need to both with needing to edit the makefile itself. The IDE is likely to provide a settings menu where you can specify things like include library paths and compiler options. However, there may still be occasions where you need to manipulate the makefile itself to adjust the method being used to generate you target file(s).

Planning a Makefile

The first thing, before you attempt writing a makefile is to know how the application you want to make is generated. Knowing of whatever compilers, assemblers, linkers and other tools to go from the code to an executable. When talking about C and using GCC, the essential thing you should hopefully know already, before you attempt constructing a makefile, is the basics of the gcc command.

Before making a makefile, you should know what tools that are going to be used in the compile process, and the sequencing of these tools for building your executable.

There may be various other commonly used operations, related to the build process, that might not specifically be part of the build process but needed in starting or setting up the build process, the development environment or the execution environment that you are wanting to utilize. An example of such a process is the ‘clean’ process, which deletes any intermediary files (e.g. object files) and the previously compiled executable. Applying the 'clean' process generally forces the build processes to remake the executable from scratch the next time it is run.

Other common make process are:

  • ‘mark’: which is not really what tutors use for marking your code (it could be!) but rather some companies use it to make a significant state of the project e.g. mark a build in some way, possibly sending it to a repository.
  • ‘backup’: obvious one this. Apply some backup operation, maybe zipping up the project files and uploading it to some file store.
  • ‘test’: either generating testing code (sometimes one generates automated testing code, e.g. a separate project that will test your project) and/or runs tests through your already compile application.

To make this page brief and to give you a quick start to makefiles, a simple example of a makefile for compiling a C program is given below. The subsequent section lists some useful tutorials that you may want to explore further to improve your makefile writing skills.

Simple example makefile

To illustrate the process of developing a makefile, let us consider we want to make a program from the following files:

  test1.c 
  test1.h

i.e. test.c has H-file interface called test.h

We want to compile test1.c with gcc and we want to generate a GDB debugger compatible executable, which needs the -g flag to be specified. We want to call the generated executable test1 (an elf file, not needing extension if done on Linux). We could do this easily with just gcc:

  gcc -g -o test1 test1.c

But this isn’t scalable. And we haven’t captured the information of dependencies and build process (e.g. so future developers or users will see how to build the program).

Let's quickly plan the build method for this. It would be useful to have these two processes available:

  • clean process : to deletes all intermediary files and the executable.
  • build process (the default process) : generate the executable if any of its dependencies (as in the .c or .h files) have changed since the last attempt at building.

Here is a super simple start for the makefile, although for the sake of explaining a little more, some special variables, such as $@ and $< have been used (to save some typing) and these are explained after the example. Together with what is being done on each line.

 1 .
 2 CC=gcc
 3 # note the -g below for debugging
 4 # and note that hash symbol used for single line comments
 5 CFLAGS=-I. -g
 6 
 7 test1.o: test1.c test1.h
 8         $(CC) -c -o test.o $< $(CFLAGS)
 9 
10 test1: test1.o
11         $(CC) -o $@ $^ $(CFLAGS)
12 
13 clean:
14         rm -f -r test1 test1.o


Recommended Tutorials