【问题标题】:Gnu Make : Slice variable (keep all but last element)Gnu Make:切片变量(保留除最后一个元素之外的所有元素)
【发布时间】: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_SOURCEDIRsrc,而C_BUILD_DIRobj,那么subst 将返回obj/myobj.c,这不是您想要的。 patsubst 只替换匹配的模式一次,所以它会在这里做正确的事情。

标签: makefile build slice gnu-make


【解决方案1】:

感谢 Vroomfondel 的评论,我意识到“切片”不起作用仅仅是因为 make 正在处理字符串,因此不知道 -1 的含义。

另一方面:C_OBJS 行中有一个错字(不知何故,这些类型的错误总是需要最长时间才能修复); C_SOURCEDIR 不是一个存在的变量!因此 make 将其视为空字符串,这反过来又使 subst 命令无法按预期工作...

课程:注意忍者拼写错误

【讨论】:

    【解决方案2】:

    这将评估除$(VAR) 的最后一个单词之外的所有内容:

    VAR2 := $(wordlist 2,$(words $(VAR)),x $(VAR))
    

    你也可以把它做成一个函数:

    define firstwords
    $(wordlist 2,$(words $(1)),x $(1))
    endef
    
    VAR2 := $(call firstwords,$(VAR)) 
    

    【讨论】:

      猜你喜欢
      • 2023-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 2011-02-04
      相关资源
      最近更新 更多