我想知道以下makefile片段中的分号是什么:
define Package/xxsim/CopyLocalFiles
$(call cp, files/Adapter20Sim.h, $(PKG_BUILD_DIR)/xxsim);
$(call cp, files/Adapter20Sim.cpp, $(PKG_BUILD_DIR));
endef
Hooks/Prepare/Post+=Package/xxsim/CopyLocalFiles
如果重要,makefile用于OpenWRT构建系统中的自定义组件(xxsim)。
我希望分号是不必要的,例如,这个例子(source):
define two-lines =
echo foo
echo $(bar)
endef
但是,如果我们在没有这些分号的情况下构建,则对cp
的第二次调用失败(第一次调用cp
隐式成功):
[CP] files/Adapter20Sim.h
[CP] files/Adapter20Sim.cpp
cp: target ' [MKDIR] xxsim docinfo in staging dir' is not a directory
显然,cp收到错误的输入参数。那么,添加分号实际上做了什么,为什么组件正确地用分号构建?
更新:在下面添加了构建系统上下文,由Etan在评论中提供了帮助:
Hooks/Prepare/Post
用于foreach语句,其中每个值都用于调用函数:
$(foreach hook,$(Hooks/Prepare/Post),$(call $(hook))$(sep))
foreach
:
$(STAMP_PREPARED) : export PATH=$$(TARGET_PATH_PKG)
$(STAMP_PREPARED):| $(PKG_BUILD_DIR) $(STAGING_DIR)/include $(STAGING_DIR)/lib$(LIB_SUFFIX)
$(foreach hook,$(Hooks/Prepare/Pre),$(call $(hook))$(sep))
$(Build/Prepare)
$(foreach hook,$(Hooks/Prepare/Post),$(call $(hook))$(sep))
$(call touch,$$@,Prepared $(PKG_NAME))
答案 0 :(得分:2)
这里的问题是如何在配方上下文中扩展多行定义(具体而言,定义的内容是什么)。
在配方上下文中,多行定义被扩展为多行,因此make手册中的示例可以正常工作。
因此,您可以假设此处讨论的场景也可以正常运行,但显然不会。有两件事情会导致这个问题。
第一个是定义的值是什么。
您可以假设给定此代码段:
PKG_BUILD_DIR := build
cp = @echo '[CP] $1'; cp '$1' '$2'
define Package/xxsim/CopyLocalFiles
$(call cp, files/Adapter20Sim.h, $(PKG_BUILD_DIR)/xxsim)
$(call cp, files/Adapter20Sim.cpp, $(PKG_BUILD_DIR))
endef
Package/xxsim/CopyLocalFiles
的值为:
@echo '[CP] files/Adapter20Sim.h'; cp 'files/Adapter20Sim.h' 'build/xxsim'
@echo '[CP] files/Adapter20Sim.cpp'; cp 'files/Adapter20Sim.cpp' 'build'
它是......除了。
你可能假设这是两行有两条换行符,所以真的这样:
@echo '[CP] files/Adapter20Sim.h'; cp 'files/Adapter20Sim.h' 'build/xxsim'\n
@echo '[CP] files/Adapter20Sim.cpp'; cp 'files/Adapter20Sim.cpp' 'build'\n
但事实并非如此。实际上是这样的:
@echo '[CP] files/Adapter20Sim.h'; cp 'files/Adapter20Sim.h' 'build/xxsim'\n
@echo '[CP] files/Adapter20Sim.cpp'; cp 'files/Adapter20Sim.cpp' 'build'
否最终换行符。
现在正常(并且在makefile中的示例中)无关紧要,因为define的使用方式如下:
tgt:
$(Package/xxsim/CopyLocalFiles)
并且define的最后一个字符紧跟一个换行符(在配方行本身上)。
但这不是在这种情况下发生的事情。在这种情况下,定义正在$(foreach)
循环中展开,手册说明foreach
:
连接 text 的多个扩展,并在它们之间留有空格,以生成 foreach 的结果。
所以当循环扩展两个这样的定义背靠背时:
mkdir = @echo '[MKDIR] $1'; mkdir '$1'
define Package/xxsim/CopyLocalFiles
$(call cp, files/Adapter20Sim.h, $(PKG_BUILD_DIR)/xxsim)
$(call cp, files/Adapter20Sim.cpp, $(PKG_BUILD_DIR))
endef
HOOKS += Package/xxsim/CopyLocalFiles
define Package/xxsim/MkdirStaging
$(call mkdir, $(PKG_BUILD_DIR)/xxsim/staging)
endef
HOOKS += Package/xxsim/MkdirStaging
tgt:
$(foreach hook,$(HOOKS),$(call $(hook)))
你得到的扩展输出是这样的:
tgt:
@echo '[CP] files/Adapter20Sim.h'; cp 'files/Adapter20Sim.h' 'build/xxsim'
@echo '[CP] files/Adapter20Sim.cpp'; cp 'files/Adapter20Sim.cpp' 'build' @echo '[MKDIR] build/xxsim/staging'; mkdir build/xxsim/staging
导致您看到的错误以及包括尾部分号修复的错误。
在define中包含一个额外的空行也可以解决问题(如果make只在文字定义值的末尾选择一个换行符。)
像这样:
define Package/xxsim/CopyLocalFiles
$(call cp, files/Adapter20Sim.h, $(PKG_BUILD_DIR)/xxsim)
$(call cp, files/Adapter20Sim.cpp, $(PKG_BUILD_DIR))
endef
答案 1 :(得分:0)
分号在define函数中没有特殊功能。 $(call MyDefine)
只是扩展define函数,即call
函数被define
函数的内容替换。
(call
函数实际上做了其他一些事情,比如参数扩展,但这似乎对这个主题没有影响。)
在您的情况下,分号是必需的,因为复制命令的扩展方式是一次执行。 shell(如bash)需要在两个命令之间使用分号。
Makefile语法使用选项卡定义属于目标的命令。你的错误
cp:target'[MKDIR] xxsim docinfo in staging dir'不是目录`
建议您将其中一个命令(或某些东西...... ??)作为目标而不是命令处理。如果define
函数的内容具有空格作为缩进,您可能希望用制表符替换它们,因此完整的内容将作为命令而不是目标插入。
另一个解决方案是在每一行之后添加反斜杠,使内容为“单行”。在这种情况下,分号是必需的,因为shell执行单行,因此所有命令都需要用它们分隔。