如何将输出重定向到特定文件到sed命令?

时间:2016-12-25 23:34:20

标签: shell gcc sed makefile io-redirection

某些上下文:我尝试构建一个通用的Makefile,使用自动依赖生成(使用GCC描述here,非递归,可以在我的项目的任何级别使用。 为此,生成的依赖项文件需要具有以下形式:

$(DIR)file.o: $(DIR)file.c $(DIR)file.h

$(DIR)file.h

这样,无论make调用的级别如何,make都可以正确定位文件。

为了做到这一点,我有以下隐含规则:

DEPFLAGS = -MT $@ -MP -MMD -MF $(word 2,$^).tmp
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
POSTCOMPILE = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)\2|g' $(word 2,$^).tmp > $(word 2,$^)

%.o: %.c %.dep
    $(COMPILE)
    $(POSTCOMPILE)
    $(RM) $(word 2,$^).tmp
    touch $@

sed调用将文件名之前的任何目录部分替换为$(DIR)

问题是,由于依赖文件是在目标文件之后生成的,因此每次都会导致Makefile重新链接。所以我必须添加一个触摸命令,以确保目标文件被认为是最新的。哪个不是很优雅。 所以我有这个问题:有没有办法直接将gcc输出(定向到.tmp文件中)重定向到sed命令?

换句话说,有没有办法相当于管道重定向,但对于其他流/文件描述符而不是stdout?

1 个答案:

答案 0 :(得分:0)

如果您处于完全成熟的Linux环境中,您确实可以跳过.tmp文件的创建并将依赖项直接传递到sed

# This is needed, because the default shell does not support
# process substitution
SHELL = /bin/bash

SED_COMMAND = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)\2|g' > $(word 2,$^)
DEPFLAGS = -MT $@ -MP -MMD -MF >($(SED_COMMAND))
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<

%.o: %.c %.dep
        $(COMPILE)
        touch $@

但是,由于上面@MadScientist的评论中正确提到的原因,最后仍然需要touch命令:

  

在编译器完成目标文件编写之前,没有办法100%确定sed命令会完成其文件的编写:它们并行运行,因此您无法保证哪一个将首先完成。

相关问题