我试图在我的makefile中对变量执行切片。我用这个:
C_SOURCES := $(foreach dir, $(C_SOURCEDIRS), $(wildcard $(dir)/*.cpp))
生成所有代码源文件的列表,然后使用:
C_OBJS := $(subst $(C_SOURCEDIR), $(CLIENT_BUILD_DIR), $(C_SOURCES:.cpp=.o))
生成所有关联对象文件的所有名称。但是,构建目录本身(CLIENT_BUILD_DIR)一直作为C_OBJS的最后一个元素出现。(我也不完全确定为什么会这样…)
作为一种hack,我决定删除C_OBJS的最后一个元素(将其切片,保留所有的n - 1个第一个元素),并尝试这样做:
C_OBJS := $(wordlist, 1, $(words $(C_OBJS)) - 1, $(C_OBJS))
但是这会导致C_OBJS为空!我已经阅读了文本函数的文档,但除非我不理解正确的东西,这应该像预期的那样工作:使C_OBJS = C_OBJS中的所有元素,除了最后一个。
感谢任何帮助!(对于那些能够解释为什么CLIENT_BUILD_DIR首先出现在C_OBJS中的人来说,这是一个额外的饼干;以及如何避免它)[编辑:见答案]
如果需要,这是正在讨论的makefile的完整段:
CLIENT_SRC_DIR := $(SOURCEDIR)/Client
CLIENT_BUILD_DIR := $(BUILDDIR)/Client
C_DIRS := $(notdir $(shell find $(CLIENT_SRC_DIR) -type d -print | tail -n +2))
C_SOURCEDIRS := $(foreach dir, $(C_DIRS), $(addprefix $(CLIENT_SRC_DIR)/, $(dir)))
C_TARGETDIRS := $(foreach dir, $(C_DIRS), $(addprefix $(CLIENT_BUILD_DIR)/, $(dir)))
C_SOURCES := $(foreach dir, $(C_SOURCEDIRS), $(wildcard $(dir)/*.cpp))
C_OBJS := $(subst $(C_SOURCEDIR), $(CLIENT_BUILD_DIR), $(C_SOURCES:.cpp=.o))
C_OBJS := $(wordlist, 1, $(words $(C_OBJS)) - 1, $(C_OBJS))
C_DEPS := $(C_OBJS:.o=.d)
谢谢!
多亏了Vroomfondel的评论,我意识到'slice'不工作仅仅是因为make正在处理字符串,因此不知道-1是什么意思。
另一个注意事项:在C_OBJS行中有一个错别字(不知何故,总是这些类型的错误需要最长的时间来修复);C_SOURCEDIR
不是一个存在的变量!因此make将其视为空字符串,这反过来使subst
命令不能按预期工作…
教训:小心忍者的错别字
这将计算除$(VAR)
的最后一个字以外的所有内容:
VAR2 := $(wordlist 2,$(words $(VAR)),x $(VAR))
你也可以把它变成一个函数:
define firstwords
$(wordlist 2,$(words $(1)),x $(1))
endef
VAR2 := $(call firstwords,$(VAR))