脚本系列 —— 从Makefile中学习“ifneq, ifeq, filter, strip”(持续更新)

本文详细解读了Makefile中的ifneq条件判断和filter函数使用实例,展示了如何通过这两个功能判断变量是否包含特定模式,并根据结果设置变量值。理解这些技巧有助于编写高效和灵活的Makefile脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘取一些Makefile文件里的片段,进行语法讲解

例1

ifneq "" "$(filter eng.%,$(BUILD_NUMBER))"
  # BUILD_NUMBER has a timestamp in it, which means that
  # it will change every time.  Pick a stable value.
  FILE_NAME_TAG := eng.$(USER)
else
  FILE_NAME_TAG := $(BUILD_NUMBER)
endif

上面这段语句分别用到了"ifneq",“filter”,“%”,下面详细解释一下
ifneq
条件判断语句,和ifeq相反;若后边两个对象不相等,则条件成立;
这里的两个判断对象分别是“”(空值)“$(filter eng.%,$(BUILD_NUMBER))”

filter
“$(filter eng.%,$(BUILD_NUMBER))”,这段语句的意思是从变量$(BUILD_NUMBER)中筛选出包含eng.%的部分,这其中的%是Makefile的通配符;

例如:
  $(filter eng.%,“eng.123”)的结果就是"eng.123"
  $(filter eng.,“eng.123”)的结果就是"eng."

综上分析,此例所做处理就是判断变量BUILD_NUMBER是否包含eng.,如果包含则FILE_NAME_TAG被赋值为eng.$(USER),否则被赋值为$(BUILD_NUMBER)


例2

ifneq ($(strip $(TARGET_NO_KERNEL)),true)
  INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
else
  INSTALLED_KERNEL_TARGET :=
endif

strip
这个关键字的作用是去掉对象中开头结尾的空字符,包括空格,Tab缩进等不可见字符;

例如:
  $(strip " a bc “)的结果为"a bc”


<think>好的,我现在需要解决用户的问题:在Makefile中,如何用ifneq实现多个条件的“或”逻辑,并且要提供一个示例。首先,我需要回忆一下Makefile的条件判断语法。 我记得Makefile中的条件判断主要有ifeqifneq等,用于比较两个值是否相等或不相等。但用户的问题是多个条件的“或”操作,也就是说,只要其中一个条件满足,就执行某个命令。这时候,直接使用ifneq可能不太容易,因为ifneq本身不支持多个条件的逻辑组合,比如&&或||这样的操作符。 首先,我需要确认Makefile的语法是否支持在ifneq中直接使用多个条件。查阅文档发现,Makefile的条件语句并不像编程语言那样支持逻辑运算符,每个条件判断只能比较两个值。所以,如果用户想实现多个条件的“或”逻辑,可能需要通过嵌套多个ifneq或者使用其他方法。 接下来,考虑如何通过多个条件判断的组合来实现“或”的效果。例如,用户可能想检查变量VAR是否不等于A或B。在逻辑上,这等同于“如果VAR不等于A 并且 VAR不等于B”,那么... 但是用户需要的是“或”的情况,即如果VAR不等于A 或者 不等于B,但实际上这可能不符合逻辑,因为如果VAR是C,那么它既不是A也不是B,这时候可能需要用两个条件来判断。但可能用户实际的需求是,当VAR不等于A或者不等于B时执行某些操作,这可能需要重新考虑逻辑结构。 或者,用户可能想表达的是,如果变量不等于多个值中的任何一个,就执行某个操作。这时候可能需要结合多个条件判断,或者使用函数来辅助。 再仔细想一下,ifneq的语法是ifneq (arg1, arg2),所以如果需要多个条件,可能需要用多个ifneq嵌套,或者使用逻辑表达式。但Makefile的条件判断不支持直接在同一个ifneq中写多个条件,所以可能需要使用多个条件判断的组合,或者使用其他方法,比如使用filter函数。 例如,使用filter函数来检查变量是否在某个列表中。例如,如果变量VAR的值不是A或B,可以写成ifneq ($(filter $(VAR),A B),)。这样,如果VAR是A或B,filter会返回非空,取反后条件成立。但用户想要的是“或”的关系,可能需要调整。 但用户的问题是关于ifneq的多个条件或,可能需要将多个条件分开处理。例如,如果用户想要判断变量是否不等于条件1 或者 不等于条件2,这时候可能需要分开两个ifneq,然后用逻辑或的方式组合,但Makefile中如何组合多个条件呢? 实际上,在Makefile中,不能直接使用逻辑或运算符,但可以通过嵌套条件语句来实现。例如: ifneq (条件1) # 执行操作 else ifneq (条件2) # 执行同样的操作 endif 但这样会导致重复代码。或者,可以使用变量来保存条件的结果,再进行逻辑判断。例如: COND1 := $(if $(条件1),true,false) COND2 := $(if $(条件2),true,false) ifneq ($(COND1)|$(COND2),false|false) # 执行操作 endif 但这种方法可能比较复杂,需要用户理解变量赋值和条件函数的使用。 另外,用户可能需要的是类似“如果变量不等于A或者不等于B”,但实际上这样的条件总是成立,除非变量同时等于A和B,这显然不可能。所以可能用户的实际需求是“如果变量既不是A也不是B”,这时候应该用逻辑与,也就是多个条件同时满足的情况。 例如,如果VAR不是A,并且VAR不是B,那么执行某些操作。这时候可以使用两个ifneq的嵌套: ifneq ($(VAR),A) ifneq ($(VAR),B) # 执行操作 endif endif 或者,使用逻辑与的方式,结合filter函数: ifneq ($(filter $(VAR),A B),) # 如果VAR在A或B中,则条件不成立 else # 执行操作 endif 或者更准确地说,如果VAR不在A或B中: ifeq ($(filter $(VAR),A B),) # 执行操作 endif 这可能更简洁,因为filter函数会返回VAR是否在列表中。如果用户想要当VAR不等于A或者不等于B时执行操作,这可能需要重新审视逻辑,因为这样的条件在大多数情况下都为真,除非VAR同时等于A和B,这不可能。 所以,可能用户的真实意图是当变量不等于多个值中的任何一个时,执行某些操作,即“或”的组合条件。这时候,正确的方法应该是使用filter函数来判断变量是否不在指定的列表中。 例如,用户想要在VAR不等于A或者不等于B的情况下执行命令,这可能需要更仔细的逻辑分析。但通常,正确的逻辑应该是当VAR不是A且不是B时才执行,这时候用逻辑与。或者,用户可能想当VAR是A或者B时不执行,否则执行,这也是逻辑与的情况。 现在回到用户的问题,他们希望用ifneq实现多个条件的“或”。假设用户想判断变量是否不等于A或者不等于B,那么这实际上是一个总是为真的条件,除非A和B是相同的值。例如,如果VAR是A,那么它不等于B,所以条件成立。如果VAR是B,它不等于A,条件也成立。只有当VAR同时等于A和B时,条件不成立,但这种情况不可能。因此,用户可能在这里存在逻辑上的误解。 可能用户实际上想要的是当变量既不等于A也不等于B时才执行,即逻辑与的情况。这时候应该使用两个ifneq嵌套,或者使用filter函数。 例如: ifneq ($(VAR),A) ifneq ($(VAR),B) # 执行操作 endif endif 或者使用filterifeq ($(filter $(VAR),A B),) # 执行操作 endif 这里,filter会返回VAR是否在列表A B中,如果不在,则条件成立。 但用户的问题明确提到要使用ifneq,并且是多个条件的“或”,所以可能需要另一种方法。 另一种思路是使用逻辑表达式组合,例如: ifneq ($(VAR),A) # 条件1成立 else ifneq ($(VAR),B) # 条件2成立 else # 都不成立 endif 但这样每个条件会单独处理,可能无法直接合并。 或者,可以使用变量组合的方式,例如,判断变量是否等于A或B,如果不等,则执行: ifneq ($(filter $(VAR),A B),) # 如果VAR是A或B,这里不执行 else # 执行操作 endif 但这里使用的是ifeqfilter的组合,而不是ifneq。 可能用户需要的是一个示例,展示如何用ifneq处理多个条件,例如,当变量不等于A或者变量不等于B时执行某些操作。但如前所述,这样的条件几乎总是成立,除非VAR同时等于A和B,所以这可能不是用户的实际需求。因此,用户可能实际上需要的是当变量不等于多个值中的任何一个时执行操作,即逻辑与的情况。 假设用户的需求是:如果变量VAR不等于A,或者VAR不等于B,则执行操作。这实际上等同于VAR不同时等于A和B的情况。例如,如果用户希望当VAR不是A或者不是B的时候执行,那么当VAR是C时满足,当VAR是A但不等于B时也满足,但实际上VAR不可能同时等于A和B,所以这种情况可能不太合理。 可能用户的问题存在表述上的误差,正确的需求应该是当变量不等于A且不等于B时才执行,这时使用两个ifneq的嵌套,或者使用filter函数。 但根据用户的问题,他们明确想要的是ifneq的多个条件或,因此可能需要用变量组合的方式。 例如,可以这样写: ifneq ($(VAR),A) # 条件1成立 DO_SOMETHING = yes endif ifneq ($(VAR),B) # 条件2成立 DO_SOMETHING = yes endif ifdef DO_SOMETHING # 执行操作 endif 但这样可能比较繁琐,不过能实现当VAR不等于A或者不等于B时执行操作。 或者,可以使用逻辑或的表达式,通过Make的函数来计算。例如: 如果VAR不等于A 或者 VAR不等于B,可以用: ifneq ($(VAR),A)$(VAR),B) # 这可能不是正确的语法 endif 但Makefile不支持这种写法,正确的做法可能需要更复杂的处理。 另一种方法是使用shell的条件判断,但这样可能不够跨平台,且不符合Makefile的最佳实践。 综上所述,正确的做法可能是使用filter函数来判断变量是否不在指定的列表中,然后使用ifeqifneq来处理。例如,如果用户想当VAR不等于A或B时执行: 如果VAR不在A或B中: ifeq ($(filter $(VAR),A B),) # 执行操作 endif 或者使用ifneqifneq ($(filter $(VAR),A B),A B) # 如果VAR不是A或B中的任何一个,这里可能不太对 endif 但这样可能不太准确。正确的做法是,当VAR不在列表A B中时,filter返回空,所以ifeq ($(filter ...),) 就会成立。 因此,用户可能需要使用filter函数而不是多个ifneq来实现多条件的判断,尤其是当条件为“或”的时候。 不过用户的问题明确要求使用ifneq,所以可能需要给出一个使用多个ifneq语句的例子,或者解释如何组合它们。 例如,用户可能需要这样的结构: ifneq ($(VAR),A) # 执行操作 else ifneq ($(VAR),B) # 执行同样的操作 else # 都不满足 endif 但这样会导致重复的代码块,可能需要使用变量来控制流程。 或者,可以组合条件到一个变量中: CONDITION_MET = no ifneq ($(VAR),A) CONDITION_MET = yes endif ifneq ($(VAR),B) CONDITION_MET = yes endif ifeq ($(CONDITION_MET),yes) # 执行操作 endif 这样,只要VAR不等于A或者不等于B,CONDITION_MET就会被设置为yes,从而执行操作。 但用户可能希望更简洁的写法。因此,最终的示例可能需要结合多个ifneq条件,并通过变量来记录是否满足任何一个条件。 现在,我需要将上述思考整理成一个清晰的步骤,并给出示例。</think>在Makefile中,`ifneq` 不支持直接使用逻辑运算符(如 `||` 或 `&&`),但可以通过 **组合条件判断** 或 **函数辅助** 实现多条件"或"逻辑。以下是两种常见方法: --- ### 方法1:通过`filter`函数实现(推荐) ```makefile VAR := B # 检查VAR是否不是A或B中的任何一个(逻辑"或") ifneq ($(filter $(VAR),A B),) # 如果VAR是A或B,条件成立(因为filter返回非空) $(info VAR是A或B) else $(info VAR既不是A也不是B) endif ``` #### 解释: 1. `$(filter $(VAR),A B)`:若`VAR`在列表`A B`中,返回`VAR`值;否则返回空。 2. `ifneq` 判断结果是否非空,若成立,则说明`VAR`等于A或B。 --- ### 方法2:通过多个`ifneq`嵌套(手动组合) ```makefile VAR := C # 定义条件标志 CONDITION_MET := # 检查VAR是否不等于A ifneq ($(VAR),A) CONDITION_MET := yes endif # 检查VAR是否不等于B ifneq ($(VAR),B) CONDITION_MET := yes endif # 根据条件标志执行操作 ifdef CONDITION_MET $(info VAR不等于A或B) else $(info VAR同时等于A和B(不可能的情况)) endif ``` #### 解释: 1. 分别用两个`ifneq`判断变量是否不等于A或B。 2. 若任一条件成立,设置标志`CONDITION_MET`为`yes`。 3. 根据标志执行最终操作。 --- ### 示例:根据变量值编译不同目标 ```makefile TARGET := linux # 如果目标不是linux或macos,报错退出 ifneq ($(filter $(TARGET),linux macos),) $(info 编译目标: $(TARGET)) else $(error 不支持的编译目标: $(TARGET)) endif ``` #### 输出: - 若`TARGET=linux`或`TARGET=macos`,正常编译。 - 若`TARGET=windows`,报错终止。 --- ### 关键点总结 1. **优先使用`filter`函数**:简洁高效,适合判断变量是否在指定列表中。 2. **嵌套`ifneq`+标志变量**:灵活性高,可处理复杂逻辑。 3. **避免直接逻辑运算符**:Makefile语法不支持`||`或`&&`,需通过条件组合实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星际工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值