【问题标题】:Make: extract the target path segment that follows a known oneMake:提取跟随已知路径的目标路径段
【发布时间】:2019-08-03 15:16:05
【问题描述】:

我正在尝试优化我们的构建目标。在我们当前的流程中,我们有单独的 32 位和 64 位构建目标。由于目标不同,我们的构建流程中有数百个目标。我们试图使其全球化,即 32 位和 64 位构建的一个目标。我正在尝试使用下面的代码来实现这一点。

32 位构建的目标/输出目录应该是这样的:

/test/scratch/<client_name>/Linux/... 

64 位构建的目标/输出目录应如下所示:

/test/scratch/<client_name>/Linux-64bit/... 

因此,基于上述目标目录路径,我正在使用 $(findstring) 函数搜索字符串 Linux 并继续使用 32 位命令运行。否则它将运行 64 位命令,如下所示。

RELEASE_FILES := $(TARGET_DIR)/build/test/csimtime.c
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq (Linux,$(findstring $(OS),$@))
    $(test_lib_32)
else
    $(test_lib_64)
endif

$(TARGET_DIR) 变量作为参数传递给 make 命令

make TARGET_DIR=$(TGT32) all32

对于 64 位,我们将改为传递 TARGET_DIR=$(TGT64)

注意:上面的 test_lib_32/64 是我们在当前 make 文件中包含的其他 make 文件中的宏定义。

按预期工作正常,但我不确定这是否是最好的方法?我注意到这里有一个问题,通常我们传递的TGT32/TGT64 变量具有值:

/test/scratch/<client_name>/Linux/ (for 32bit)

/test/scratch/<client_name>/Linux-64bit/... (for 64bit)

如果有人使用 client_name 'Linux' 字符串创建客户端,它将无法工作。即使我们运行 64 位构建,它也会始终转到 if 块并尝试运行 32 位命令。我该如何处理?

我正在寻找在上述路径中获取“client_name”之后的字符串。请问可以帮忙吗?

【问题讨论】:

  • 也许您想看看gmtt,它可以让您在列表中从头到尾搜索。您首先必须通过将“/”替换为空格来分隔路径元素。

标签: makefile gnu-make gnu


【解决方案1】:

如果你的目标目录名称总是这样的:

/test/scratch/<client_name>/Linux/...

并且&lt;client-name&gt; 中没有/ 字符和空格,您可以根据路径中Linux(或Linux-64bit)的确切位置进行测试:

TYPE := $(word 4,$(subst /, ,$(TARGET_DIR)))

ifeq ($(TYPE),Linux)
<something>
else ifeq ($(TYPE),Linux-64bit)
<something-else>
else
$(error Unknown type: $(TYPE))
endif

EDIT如果位置不固定但知道&lt;client-name&gt;是什么,并且&lt;client-name&gt;中没有/字符和空格,可以提取目录名在$(TARGET_DIR) 中跟随&lt;client-name&gt; 如下:

TAIL := $(subst /, ,$(TARGET_DIR))
$(foreach w,$(TAIL),$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))$(if $(patsubst $(CLIENT_NAME),,$(w)),,$(eval TYPE := $(word 1,$(TAIL)))))

all:
    @printf 'TYPE = $(TYPE)\n'

演示:

$ make TARGET_DIR=/a/b/test-client/Linux/c/d CLIENT_NAME=test-client
TYPE = Linux
$ make TARGET_DIR=/a/b/c/d/test-client/Linux-64bit/e/f/g CLIENT_NAME=test-client
TYPE = Linux-64bit

解释:

  • TAIL := $(subst /, ,$(TARGET_DIR))$(TARGET_DIR) 中的/ 字符替换为一个空格,使其成为单词列表(路径中每个目录一个),并将结果分配给变量TAIL
  • $(foreach w,$(TAIL),...) 评估 ...,变量 w 依次设置为 $(TAIL) 的每个单词。
  • $(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL))) 通过删除前导词重新分配变量 TAIL
  • 如果$(w) 等于$(CLIENT_NAME),则$(if $(patsubst $(CLIENT_NAME),,$(w)),,...) 评估...
  • $(eval TYPE := $(word 1,$(TAIL)))$(TAIL) 的第一个字分配给变量TYPE

可能有更简单的方法来做同样的事情......

【讨论】:

  • Renaud,谢谢您的回复... Linux/Linux-64bit 的位置一直不一样.. 这取决于用户 perforce 客户端根目录... 那么有什么方法可以找到 之后的字符串,而不是使用上面的索引“4”?
  • 但是你知道&lt;client-name&gt; 是什么吗?我可以建议您用更准确的描述更新您的问题吗?您可以删除大部分内容并仅保留以下内容:如何提取已知路径之后的路径段?或类似的东西。
  • 取决于用户...让我们暂时认为它是静态的...请将客户端名称视为“测试客户端”..您能否相应地更新答案.. 这样我就可以根据该条件更改我的制作脚本。
【解决方案2】:

如果我正确理解您的问题,那么您会遇到以下$(TARGET_DIR) 值的问题:

 /.../Linux/.../Linux-64bit

问题是你正在测试$@的值:

 /.../Linux/.../Linux-64bit/some/other/file

如您所见,这使得无法确定路径中的哪个Linux 应该用于决策。

我建议你试试这个:

# if $(TARGET_DIR) ends with /Linux -> 32-bit build
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq ($(filter %/Linux,$(TARGET_DIR)),)
        $(test_lib_32)
else
        $(test_lib_64)
endif

【讨论】:

  • Stefan,谢谢您的回复。如果我的问题不清楚,我很抱歉。在我的情况下,没有办法让 Linux/Linux-64 位在同一路径中。正如我提到的 32 位目标路径应该是 '/test/scratch//Linux/ ' & 对于 64 位 /test/scratch//Linux-64bit/ .. Linux/ Linux-64bit 不会在最后出现.. 它会在 之后出现.. 路径不会改变它是恒定的.. 你能帮我解析目标文件路径并获取 之后的字符串并检查它是否是 Linux /Linux-64bit .. 我想它会工作吗?
  • 但是必须在某个地方定义所有$(TARGET_DIR) 变量的,即不包括/&lt;path continues&gt; 的路径。这是您需要在条件中检查的变量。如果你没有这样的根变量,那么你应该引入一个。
  • 好的...是的,我在 config.mak 文件之一中有根变量 'TGT32'。你的意思是说 .. 而不是检查 $@ ,我应该有条件的 'if'检查 $(TARGET_DIR) 看它是否有'Linux'/'Linux-64bit' 对吗?根变量值分配给 /build/Linux 或 Linux-64bit 所以我想在字符串“build”之后获取字符串。你能否告诉我在 make 中有什么方法可以在“build”之后获取该子字符串'
  • 你给的命令行是make TARGET_DIR=$(TGT32) all32,所以$(TARGET_DIR)是你在makefile中的根目录。我的解决方案检查 那个根 是如何结束的,即在LinuxLinux-64bit 中。如果那不能解决您的问题,那么我担心您的问题太不完整而无法回答。可能是您有一个递归构建系统,其中每个子目录级别都通过$(MAKE) TARGET_DIR=$(TARGET_DIR)/subdir ... 传递其自己的值?
  • 我认为测试 TARGET_DIR 是完全有效的。正如您指出的那样,您的测试有点臭。恕我直言,最好在/ 上拆分成单词并简单地使用$(filter…)is-64bit := $(filter Linux-64bit,$(subst /, ,${TARGET_DIR}))。为了获得额外的稳健性,您可能希望处理 TARGET_DIR 中预先存在的空格,并检查是否存在 LinuxLinux-64bit 中的一个。如果断言失败,则抛出 $(error…) 错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 2016-06-20
  • 2014-09-22
  • 2015-02-26
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多