要点:
- make 命令行使用 xxx=abc传递,本质是在makefile中定义了makefile的变量。使用的判断关键字是 ifeq 以及 else ifeq和else
- make 传递给C语言的配置本质是宏定义,使用的判断关键字是 if defined或者 ifdef ,elif definded
核心:
make ifeq 与 else ifeq
c ifdef 与 else ifdef。并且ifdef = if defined
Step1: 命令行定义
make CFG_TEST_VAR=linux
Step2: Makefile中使用
makefile中可以根据配置进行条件判断,条件判断中可以根据条件配置C语言的cflags传递给C文件,但是Makefile的变量不能直接传递
# 如果DEBUG参数被传递,则打印一条消息
ifeq ($(CFG_TEST_VAR),linux)
$(info "Debug mode is enabled.")
DEBUG_FLAG = -g
endif
# 其他规则和目标
mytarget:
gcc myprogram.c -o myprogram $(DEBUG_FLAG)
如果有多个分支:
# 如果DEBUG参数被传递,则打印一条消息
ifeq ($(CFG_TEST_VAR),linux) #linux平台优化1
$(info "Debug mode is enabled.")
DEBUG_FLAG = -O1
else ifeq ($(CFG_TEST_VAR),mac) #其他平台优化2
DEBUG_FLAG = -O2
else
#xxx
endif
# 其他规则和目标
mytarget:
gcc myprogram.c -o myprogram $(DEBUG_FLAG)
Step3: 传递给C语言:
传递给 C 语言本质是 Makefile 根据make变量,定义C语言的宏定义,相当于是通过 m变量 到 c宏 的转换,C语言宏定义使用CFLAGS中 -Dxxx或者-Dxxx=abc来传递
makefile中定义宏
- 定义值模式,这种场景是有多个类似的选择
ifeq ($(CFG_TEST_VAR),linux)
CFLAGS += -DPLATFORM_TYPE=1 # 定义值模式,这种场景是有多个类似的选择
else
CFLAGS += -DPLATFORM_TYPE=2
endif
- 定义判断宏模式
ifeq ($(CFG_TEST_VAR),linux)
#或者直接定义宏
CFLAGS += -DCFG_FEATURE_A # 定义判断宏模式,这种场景通常是某种功能开关,这种一般不常用else组合
endif
注意是-Dxxx
Step4: C语言中使用
判断宏定义的值:
方法1:使用变量值模式
#if defined(PLATFORM_TYPE) && (PLATFORM_TYPE == 1)
printf(xxx);
#else if defined(PLATFORM_TYPE) && (PLATFORM_TYPE == 2)
printk(xxx);
#else
log(xxx);
#endif
方法2:使用值是否定义模式
#if defined(CFG_FEATURE_A)
struct abc def;
def.fature_a_enable = True;
#endif
其他总结
工程实践场景
- 使用在 命令参数,比如 echo 参数,GCC 参数
- 使用在定义条件分支,比如 ifeq linux 或者 mac
- 使用在定义 relase 或者 debug 发布
- 使用在定义 C 语言cflags
- 有某个功能宏定义开关,C语言根据场景判断是否有这种功能代码进行预编译区分(优势是能够节省代码段)
坑:
坑1:在ifeq中使用make命令行传递进来的时候如果是个字符串,不需要额外添加",比如
- 命令行:
make CFG_TEST_VAR=linux
- make中
ifeq ($(CFG_TEST_VAR), linux) #对
ifeq ($(CFG_TEST_VAR), "linux") #错,将不会执行
总结
- 核心:
- make ifeq 与 else ifeq
- c ifdef 与 else ifdef。并且ifdef = if defined
- makefile中是makefile的变量,ifeq和else ifeq是makefile的语法关键字。本质是变量,那么就有变量的判断逻辑。可以通过命令行送变量进来,也可以直接在makefile中定义变量。(命令行送进来的本质是变量)
- C中是C宏定义,#ifdef 和 #if defined这些宏定义的关键字就可以用,#ifdef 的多个条件分支是 #elif defined。
- make和c的这个多层次(4个层次)传递方式,使用变量+宏,串联起了从命令行 经过makefile,再经过gcc的-D传参,送入C语言的宏定义,最后作用在C的变量,从而控制了二进制程序的代码。体现了工程分层以及工程接口和灵活组合的设计关联。很有意思。
引用
姊妹篇:
《C语言如何根据Makefile配置宏定义值进行编译预处理 #if defined(CFG_XXX_TYPE) && (CFG_XXX_TYPE == 1)》 https://blog.csdn.net/essencelite/article/details/135857713