As you already know, a major part of the projects are managed using Make tool. The Make it's a nice tool which controls the generation of executables based on rules. In this post I will share some of things that I found useful when you begin a project using Makefile.
So, let's say that we will create a project that it's called MyProject and in this project we have two folder folder_1 and folder_2.
mkdir MyProject
cd MyProjet
mkdir folder_1 folder_2
Now we will create a Makefile on top of the project (the Mekefile it's a text file so you can use whatever text editor you want to create and edit it). At this stage we have:
bash$ ls
folder_1 folder_2 Makefile
DEBUG Makefile
There is not a special tool that allow to debug a Makefile, as is the case with a GNU Debugger that allow to check your program. But you can use @echo to display useful information when you develop your Makefile. For example let's write this rule, called debug, in the Makefile.
Makefile:
.PHONY: debug
debug:@echo "This is the debug rule"
Bash:
bash$ make debug
This is the debug rule
Note: .PHONY it's a word that it's good to be added in front of rules to avoid conflict with a file of the same name. For example if a file named debug exists, this will not work properly.
TOP DIRECTORY
Sometime it's necessary to know the working directory where the project is located. The Make allow to execute command form shell, we can use pwd(print working directory) to know the working directory or we can use the CURDIR variable.
Makefile:
#WORKDIR := ${shell pwd}
WORKDIR :=$(CURDIR)
.PHONY: debug
debug:@echo "This is the debug rule"
@echo $(WORKDIR)
Bash:
bash$make debug
This is the debug rule
/home/miti/Desktop/MyProject
INCLUDE / -INCLUDE
To organize better the project, Makefile allow to include others makefiles or file, using include directive. If you want to include a file but you don't want to show error, in the case the file don't exists, then use this -include. Let's suppose that in the folder_1 we have the compiler configuration named Toolchain.conf.
Toolchain.conf:
AR = ar
CC = gcc
CPP = g++
NM = nm
OBJCOPY = objcopy
OBJDUMP = objdump
Makefile:
WORKDIR := ${shell pwd}
include $(WORKDIR)/folder_1/Toolchain.conf
.PHONY: debug
debug:@echo "This is the debug rule"
@echo $(WORKDIR)
@echo $(CC)
Bash:
bash$make debug
This is the debug rule
/home/miti/Desktop/MyProject
gcc
WILDCARD
Wildcard it's a very useful command that allow to get all the files found in a folder. This command can be useful when we use recursive Makefile. Let's say that the folder_2 has the following file: file_1.c, file_2.c and file_3.c
Makefile:
WORKDIR := ${shell pwd}
include $(WORKDIR)/folder_1/Toolchain.conf
CC_SRCS ?= $(wildcard folder_2/*.c)
.PHONY: debug
debug:@echo "This is the debug rule"
@echo $(WORKDIR)
@echo $(CC)
@echo $(CC_SRCS)
Bash:
bash$ make debug
This is the debug rule
/home/miti/Desktop/MyProject
gcc
folder_2/file_2.c folder_2/file_3.c folder_2/file_1.c
= := ::= ?=
Often we see in makefile that a variable in set with one of the symbol "=" , ":=" , "::=" or "?=" , but what is the difference between them?
Variable defined with "=" are recursively expanded variables.
Variable defined with ":=" or "::=" are simply expanded variables.
Variable defined with "?=" will be set only if the variable was not already set.
0 Comments