{"id":12873,"date":"2019-03-29T00:29:47","date_gmt":"2019-03-29T00:29:47","guid":{"rendered":"http:\/\/www.appservgrid.com\/paw92\/?p=12873"},"modified":"2019-03-29T00:29:47","modified_gmt":"2019-03-29T00:29:47","slug":"a-brief-introduction-to-makefiles-in-open-source-software-development-with-gnu-make","status":"publish","type":"post","link":"https:\/\/www.appservgrid.com\/paw92\/index.php\/2019\/03\/29\/a-brief-introduction-to-makefiles-in-open-source-software-development-with-gnu-make\/","title":{"rendered":"A Brief Introduction to \u2018Makefiles\u2019 in Open Source Software Development with GNU Make"},"content":{"rendered":"<p><strong>GNU Make<\/strong>\u00a0is a development utility which determines the parts of a particular code base that are to be recompiled and can issue commands to perform those operations on the code base. This particular\u00a0<em><strong>make<\/strong><\/em>\u00a0utility can be used with any programming language provided that their compilation can be done from the shell by issuing commands.<\/p>\n<div id=\"attachment_5841\" class=\"wp-caption aligncenter\">\n<p><a href=\"https:\/\/www.tecmint.com\/wp-content\/uploads\/2014\/03\/Makefiles-in-Linux.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-5841\" src=\"https:\/\/www.tecmint.com\/wp-content\/uploads\/2014\/03\/Makefiles-in-Linux.png\" alt=\"Makefiles in Linux\" width=\"442\" height=\"317\" aria-describedby=\"caption-attachment-5841\" data-lazy-loaded=\"true\" \/><\/a><\/p>\n<p id=\"caption-attachment-5841\" class=\"wp-caption-text\">Makefiles in Linux<\/p>\n<\/div>\n<p>In order to use\u00a0<strong>GNU Make<\/strong>, we need to have some set of rules which defines the relationship among different files in our program and commands for updating each file. These are written onto a special file called \u2018<em><strong>makefile<\/strong><\/em>\u2018. The \u2018<em><strong>make<\/strong><\/em>\u2018 command uses the \u2018<em><strong>makefile<\/strong><\/em>\u2018 data base and the last modification times of the files to decide which all files are to recompiled again.<\/p>\n<h3>Contents of a Makefile<\/h3>\n<p>Generally \u2018<em><strong>makefiles<\/strong><\/em>\u2018 contain 5 kinds of things namely:\u00a0<strong>implicit rules<\/strong>,\u00a0<strong>explicit rules<\/strong>,\u00a0<strong>variable definitions<\/strong>,\u00a0<strong>directives<\/strong>, and\u00a0<strong>comments<\/strong>.<\/p>\n<ol>\n<li>An\u00a0<em><strong>explicit rule<\/strong><\/em>\u00a0specifies how to make\/remake one or more files (called targets, will be explained later) and when to do the same.<\/li>\n<li>An\u00a0<em><strong>implicit rule<\/strong><\/em>\u00a0specifies how to make\/remake one or more files based on their names. It describes how a target file name is related to one file with a name similar to the target.<\/li>\n<li>A\u00a0<em><strong>variable definition<\/strong><\/em>\u00a0is a line that specifies a string value for a variable to be substituted later.<\/li>\n<li>A\u00a0<em><strong>directive<\/strong><\/em>\u00a0is an instruction for make to do something special while reading the makefile.<\/li>\n<li>A \u2018<strong>#<\/strong>\u2019 symbol is used represent the start of a\u00a0<em><strong>comment<\/strong><\/em>\u00a0inside\u00a0<em><strong>makefiles<\/strong><\/em>. A line starting with \u2018<strong>#<\/strong>\u2019 is simply ignored.<\/li>\n<\/ol>\n<h4>Structure of Makefiles<\/h4>\n<p>The information that tells\u00a0<em><strong>make<\/strong><\/em>\u00a0how to recompile a system comes from reading a data base called the\u00a0<em><strong>makefile<\/strong><\/em>. A simple\u00a0<em><strong>makefile<\/strong><\/em>\u00a0will consists of rules of the following syntax:<\/p>\n<pre>target ... : prerequisites ... \r\n\trecipe \r\n... \r\n...<\/pre>\n<p>A\u00a0<em><strong>target<\/strong><\/em>\u00a0is defined to be the output file generated by the program. It can be also\u00a0<em><strong>phony targets<\/strong><\/em>, which will be explained below. Examples of target files include\u00a0<strong>executables<\/strong>,\u00a0<strong>object files<\/strong>\u00a0or\u00a0<strong>phony targets<\/strong>\u00a0like\u00a0<em><strong>clean<\/strong><\/em>,\u00a0<em><strong>install<\/strong><\/em>,\u00a0<em><strong>uninstall<\/strong><\/em>\u00a0etc.<\/p>\n<p>A\u00a0<em><strong>prerequisite<\/strong><\/em>\u00a0is a file that is used as an input to create the target files.<\/p>\n<p>A\u00a0<em><strong>recipe<\/strong><\/em>\u00a0is the action that\u00a0<em><strong>make<\/strong><\/em>\u00a0performs for creating the target file based on the prerequisites. It is necessary to put tab character before each recipe inside the\u00a0<em><strong>makefiles<\/strong><\/em>\u00a0unless we specify the \u2018<strong>.RECIPEPREFIX<\/strong>\u2018 variable to define some other character as prefix to recipe.<\/p>\n<h4>A sample Makefile<\/h4>\n<pre>final: main.o end.o inter.o start.o\r\n\tgcc -o final main.o end.o inter.o start.o\r\nmain.o: main.c global.h\r\n\tgcc -c main.c\r\nend.o: end.c local.h global.h\r\n\tgcc -c end.c\r\ninter.o: inter.c global.h\r\n\tgcc -c inter.c\r\nstart.o: start.c global.h\r\n\tgcc -c start.c\r\nclean:\r\n\trm -f main.o end.o inter.o start.o<\/pre>\n<p>In the above example we used\u00a0<strong>4 C<\/strong>\u00a0source files and two header files for creating the executable\u00a0<em><strong>final<\/strong><\/em>. Here each \u2018<strong>.o<\/strong>\u2019 file is both a target and a prerequisite inside the\u00a0<em><strong>makefile<\/strong><\/em>. Now take a look at the last target name\u00a0<em><strong>clean<\/strong><\/em>. It is just a action rather than a target file.<\/p>\n<p>Since we normally don\u2019t need this during compilation, it is not written as a prerequisite in any other rules. Targets that do not refer to files but are just actions are called\u00a0<strong>phony targets<\/strong>. They will not have any prerequisites as other target files.<\/p>\n<h4>How GNU Make process a Makefile<\/h4>\n<p>By default\u00a0<em><strong>make<\/strong><\/em>\u00a0starts off with the first target in the \u2018<em><strong>makefile<\/strong><\/em>\u2018 and is called as \u2018<em><strong>default goal<\/strong><\/em>\u2019. Considering our example, we have\u00a0<em><strong>final<\/strong><\/em>\u00a0as our first target. Since its prerequisites include other object files those are to be updated before creating\u00a0<em><strong>final<\/strong><\/em>. Each of these prerequisites are processed according to their own rules.<\/p>\n<p>Recompilation occurs if there are modifications made to\u00a0<strong>source files<\/strong>\u00a0or\u00a0<strong>header files<\/strong>\u00a0or if the<strong>\u00a0object file<\/strong>\u00a0does not exists at all. After recompiling the necessary object files,\u00a0<em><strong>make<\/strong><\/em>\u00a0decides whether to relink\u00a0<em><strong>final<\/strong>\u00a0<\/em>or not. This must be done if the file\u00a0<em><strong>final<\/strong><\/em>\u00a0does not exist, or if any of the object files are newer than it.<\/p>\n<p>Thus if we change the file\u00a0<em><strong>inter.c<\/strong><\/em>, then on running\u00a0<em><strong>make<\/strong><\/em>\u00a0it will recompile the source file to update the object file\u00a0<em><strong>inter.o<\/strong><\/em>\u00a0and then link\u00a0<em><strong>final<\/strong><\/em>.<\/p>\n<h4>Using variables inside Makefiles<\/h4>\n<p>In our example, we had to list all the\u00a0<strong>object files<\/strong>\u00a0twice in the rule for\u00a0<em><strong>final<\/strong><\/em>\u00a0as shown below.<\/p>\n<pre>final: main.o end.o inter.o start.o\r\n\tgcc -o final main.o end.o inter.o start.o<\/pre>\n<p>In order to avoid such duplications, we can introduce variables to store the list of object files that are being used inside the\u00a0<em><strong>makefile<\/strong><\/em>. By using the variable\u00a0<strong>OBJ<\/strong>\u00a0we can rewrite the sample\u00a0<em><strong>makefile<\/strong><\/em>\u00a0to a similar one shown below.<\/p>\n<pre>OBJ = main.o end.o inter.o start.o\r\nfinal: $(OBJ)\r\n\tgcc -o final $(OBJ)\r\nmain.o: main.c global.h\r\n\tgcc -c main.c\r\nend.o: end.c local.h global.h\r\n\tgcc -c end.c\r\ninter.o: inter.c global.h\r\n\tgcc -c inter.c\r\nstart.o: start.c global.h\r\n\tgcc -c start.c\r\nclean:\r\n\trm -f $(OBJ)<\/pre>\n<h4>Rules for cleaning the source directory<\/h4>\n<p>As we saw in the example\u00a0<em><strong>makefile<\/strong><\/em>, we can define rules to<strong>\u00a0clean up<\/strong>\u00a0the source directory by removing the unwanted object files after the compilation. Suppose we happen to have a target file called\u00a0<em><strong>clean<\/strong><\/em>. How can\u00a0<em><strong>make<\/strong><\/em>\u00a0differentiate the above two situations? Here comes the concept of\u00a0<strong>phony targets<\/strong>.<\/p>\n<p>A\u00a0<strong>phony target<\/strong>\u00a0is one that is not really the name of a file, rather it is just a name for a recipe to be executed whenever an explicit request is made from the\u00a0<em><strong>makefile<\/strong><\/em>. One main reason to use<strong>\u00a0phony target<\/strong>\u00a0is to avoid a conflict with a file of the same name. Other reason is to improve performance.<\/p>\n<p>To explain this thing, I will reveal one unexpected twist. The recipe for\u00a0<em><strong>clean<\/strong><\/em>\u00a0will not be executed by default on running\u00a0<em><strong>make<\/strong><\/em>. Instead it is necessary to invoke the same by issuing the command\u00a0<em><strong>make clean<\/strong><\/em>.<\/p>\n<pre>.PHONY: clean\r\nclean:\r\n\trm -f $(OBJ)<\/pre>\n<p>Now try to create\u00a0<em><strong>makefiles<\/strong><\/em>\u00a0for your own code base. Feel free to comment here with your doubts.<\/p>\n<p><a href=\"https:\/\/www.tecmint.com\/a-brief-introduction-to-makefiles-in-open-source-software-development-with-gnu-make\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>GNU Make\u00a0is a development utility which determines the parts of a particular code base that are to be recompiled and can issue commands to perform those operations on the code base. This particular\u00a0make\u00a0utility can be used with any programming language provided that their compilation can be done from the shell by issuing commands. Makefiles in &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.appservgrid.com\/paw92\/index.php\/2019\/03\/29\/a-brief-introduction-to-makefiles-in-open-source-software-development-with-gnu-make\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;A Brief Introduction to \u2018Makefiles\u2019 in Open Source Software Development with GNU Make&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-12873","post","type-post","status-publish","format-standard","hentry","category-linux"],"_links":{"self":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/12873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/comments?post=12873"}],"version-history":[{"count":1,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/12873\/revisions"}],"predecessor-version":[{"id":12874,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/12873\/revisions\/12874"}],"wp:attachment":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/media?parent=12873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/categories?post=12873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/tags?post=12873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}