【发布时间】:2021-03-05 09:54:31
【问题描述】:
我正在尝试对我的 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 的最后一个元素出现。 (我也不完全确定为什么会这样……)
作为一种技巧,我决定删除 C_OBJS 的最后一个元素(将其切掉,保留所有 n - 1 个第一个元素),并尝试这样做:
C_OBJS := $(wordlist, 1, $(words $(C_OBJS)) - 1, $(C_OBJS))
但是这会导致 C_OBJS 为空! 我已经阅读了documentation for text functions,但除非我没有正确理解某些内容,否则这应该可以按预期工作:使 C_OBJS = C_OBJS 中除最后一个之外的所有元素。
任何帮助表示赞赏! (对于任何能够解释为什么 CLIENT_BUILD_DIR 的人首先会出现在 C_OBJS 中的奖励 cookie;以及可能如何避免它)[编辑:查看该部分的答案]
如果需要,这是相关生成文件的完整部分:
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)
谢谢!
【问题讨论】:
-
您可能想看看github.com/markpiffer/gmtt#call-wildcard-reclist-of-globs,而不是修复
wildcard的不需要的属性。也许您可以直接制定您想要的内容,而不是使用临时make编程。 -
顺便说一句:您希望在
$(words $(C_OBJS)) - 1中计算长度 1 作为wordlist函数的第二个参数是命运多舛,因为make不知道如何计算。它接收到一个字符串123 - 1,它未能将其转换为整数,因此wordlist的评估也失败了。巧合的是,gmtt-Library 也可以计算,尽管我在这里说恕我直言,最好直接制定您尝试实现的目标。 -
@Vroomfondel 哦,你是对的 - 1 ! (我会调查 GMTT,谢谢!)但我假设我也可以使用 bash 完成工作,那么不是吗?我实际上不知道是否有可能在 makefile 中让 bash 与 make 变量交互
-
我建议您不要为此使用
subst。你应该使用patsubst:$(patsubst $(C_SOURCEDIR)/%,$(CLIENT_BUILD_DIR)/%,$(C_SOURCES:.cpp=.o))。它更安全。 -
subst将替换所有出现的单词。因此,如果您的文件是src/mysrc.c,而您的C_SOURCEDIR是src,而C_BUILD_DIR是obj,那么subst将返回obj/myobj.c,这不是您想要的。patsubst只替换匹配的模式一次,所以它会在这里做正确的事情。
标签: makefile build slice gnu-make