Project makefile (6): parameter passing, condition judgment, and include

Source: Internet
Author: User
[Copyright statement: reprinted. Please retain the Source: blog.csdn.net/gentleliu. Mail: shallnew at 163 dot com]
When multiple makefiles are nested, we sometimes need to pass some parameters to the next makefile. For example, we define the debug_symbols variable for opening debugging information in the top-level makefile. We want this variable to remain valid when executing the sub-makefile in the subdirectory. This is to pass this variable to the sub-makefile, so how to transfer it? There are two methods:
1. Use the "Export" keyword in the upper makefile to declare the variables to be passed. For example:
DEBUG_SYMBOLS = TRUEexport DEBUG_SYMBOLS
When you do not want to pass a variable to the sub-make, you can use the indicator "unexport" to declare the variable.
An export is usually used to declare a variable while defining it. As follows:
export DEBUG_SYMBOLS = TRUE
2. Specify the variable on the command line. For example:
$(MAKE) -C xxx DEBUG_SYMBOLS = TRUE
This variable is also valid when the subdirectory XXX is used to execute make.
 
Like programming languages, makefile also has its own conditional statements. Conditional statements can control the execution logic of make based on a variable value. Common condition statements are ifeq-else-endif, ifneq-else-endif, and ifdef-else-endif.
The ifeq keyword is used to determine whether the parameters are equal.
For example, it can be used to determine whether to generate debugging information:
ifeq ($(DEBUG_SYMBOLS), TRUE)>---CFLAGS += -g -Wall -Werror -O0else>---CFLAGS += -Wall -Werror -O2endif 
Ifneq is opposite to ifeq. This keyword is used to determine whether the parameters are not equal.
The ifdef keyword is used to determine whether a variable has been defined.
The usage of the last two keywords is similar to that of ifeq.
 
Now we continue to improve the makefile in the previous section. The makefile in the previous section completes the nested call of makefile. Each module has its own makefile. In fact, the makefile of each module is similar. You only need to change it to the final compiled target name or the compilation link option. The rules are similar. Can we consider extracting the rules, each module only needs to modify its own variables. This is feasible. We extract the Rules separately and write a makefile. rule: Put it in the same directory as the top-level makefile. The makefile in other modules only needs to include the makefile. As follows:
include $(SRC_BASE)/Makefile.rule
Include is similar to the header file inclusion in C language. You can understand it as a replacement.
In this way, if the rules are modified, we can directly modify the makefile, so that we do not have to go to every module to modify it, which is also easy to maintain.
In this case, the top-level makefile is slightly modified today:
# Top Makefile for C program                                                                                                                                                             # Copyright (C) 2014 shallnew \at 163 \dot com export DEBUG_SYMBOLS = TRUE DIR = srcMODULES = $(shell ls $(DIR))# MODULES = ipc main tools all : $(MODULES) $(MODULES):>---$(MAKE) -C $(DIR)/[email protected] main:tools ipc clean :>[email protected] subdir in $(MODULES); >---do $(MAKE) -C $(DIR)/$$subdir [email protected]; >---done distclean:>[email protected] subdir in $(MODULES); >---do $(MAKE) -C $(DIR)/$$subdir [email protected]; >---done tags:>---ctags -R help:>[email protected] "===============A common Makefilefor c programs==============">[email protected] "Copyright (C) 2014 liuy0711 \at 163\dot com">[email protected] "The following targets aresupport:">[email protected]>[email protected] " all              - (==make) compile and link">[email protected] " clean            - clean target">[email protected] " distclean        - clean target and otherinformation">[email protected] " tags             - create ctags for vimeditor">[email protected] " help             - print help information">[email protected]>[email protected] "To make a target, do 'make[target]'">[email protected] "========================= Version2.2 =======================" .PHONY : all clean distclean tags help 
Currently, the directory tree in the top-level directory is:
.├── include│   ├── common.h│   ├── ipc│   │   └── ipc.h│   └── tools│       ├── base64.h│       ├── md5.h│       └── tools.h├── libs├── Makefile├── Makefile.rule└── src    ├── ipc    │  ├──inc    │  ├──Makefile    │  └──src    │       └── ipc.c    ├── main    │  ├──inc    │  ├──Makefile    │  └──src    │       ├── main.c    │       └── main.c~    └── tools        ├── inc        ├── Makefile        └── src            ├── base64.c            ├── md5.c            └── tools.c 14 directories, 16 files 
The makefile deletion rules of each sub-module are modified as follows:
 
SRC_BASE = ../.. CFLAGS +=CPPFLAGS += -I. -I./inc -I$(SRC_BASE)/include # SRC_OBJ = $(patsubst %.c, %.o, $(wildcard *.c))SRC_FILES = $(wildcard src/*.c)SRC_OBJ = $(SRC_FILES:.c=.o)SRC_LIB = libtools.a include $(SRC_BASE)/Makefile.rule
Makefile. Rule in the top-level directory specifically processes the rules required for compiling links of each module. The content is as follows:
# Copyright (C) 2014 shallnew \at 163 \dot com                                                                                                                                            ifeq ($(DEBUG_SYMBOLS), TRUE)>---CFLAGS += -g -Wall -Werror -O0else>---CFLAGS += -Wall -Werror -O2endif all : $(SRC_BIN) $(SRC_LIB) ifneq ($(SRC_BIN),)$(SRC_BIN) : $(SRC_OBJ)>---$(CC) -o [email protected] $^ $(LDFLAGS)endif ifneq ($(SRC_LIB),)$(SRC_LIB) : $(SRC_OBJ)>---$(AR) rcs [email protected] $^>---cp [email protected] $(SRC_BASE)/libsendif        # clean targetclean:>---$(RM) $(SRC_OBJ) $(SRC_LIB) $(SRC_BIN)$(SRC_BIN).exe distclean:>---$(RM) $(SRC_OBJ) $(SRC_LIB) $(SRC_BIN)$(SRC_BIN).exe $(SRC_BASE)/libs/* $(SRC_BASE)/tags *~ .PHONY : all clean disclean~
When we put makefile. Rule on the top layer, we may accidentally execute the makefile on the command line, as shown below:
# make -f Makefile.rulemake: Nothing tobe done for `all'.#
Since the variables $ (src_bin) and $ (src_lib) are not defined, the pseudo-target all does not have any dependencies, so compilation fails. Here we should disable the direct execution of this makefile.

In make, there is a variable makelevel, which is used in the make execution process of multi-level calls. Variable represents the call depth. The makelevel value of the variable continuously changes during the execution of make Level 1. Through its value, we can understand the depth of the current make recursive call. The makelevel value on the top layer is "0", "1" for the next level, and "2" for the next level "......., therefore, we hope that the makefile of a sub-directory can be executed only when it is called by the upper-layer make, rather than directly executed. We can determine the makelevel variable to control it. Therefore, the final makefile. Rule in this section is:


# Copyright (C)2014 shallnew \at 163 \dot com ifeq ($(DEBUG_SYMBOLS),TRUE)>---CFLAGS +=-g -Wall -Werror -O0else>---CFLAGS +=-Wall -Werror -O2endif ifeq($(MAKELEVEL), 0)                                                                                                                                                                   all : msgelseall : $(SRC_BIN)$(SRC_LIB)endif ifneq ($(SRC_BIN),)$(SRC_BIN) :$(SRC_OBJ)>---$(CC) -o [email protected]$^ $(LDFLAGS)endif ifneq($(SRC_LIB),)$(SRC_LIB) :$(SRC_OBJ)>---$(AR) [email protected] $^>---cp [email protected]$(SRC_BASE)/libsendif msg:>[email protected]"You cannot directily execute this Makefile! This Makefile should calledby toplevel Makefile." # clean targetclean:>---$(RM)$(SRC_OBJ) $(SRC_LIB) $(SRC_BIN) $(SRC_BIN).exe distclean:>---$(RM)$(SRC_OBJ) $(SRC_LIB) $(SRC_BIN) $(SRC_BIN).exe $(SRC_BASE)/libs/*$(SRC_BASE)/tags *~ .PHONY : all cleandisclean 

Then execute the makefile directly:

# make -f Makefile.ruleYou cannot directily execute this Makefile! This Makefile should called by toplevel Makefile.# 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.