首页 > 解决方案 > 执行 public01, public02, 时打印输出

问题描述

我有以下 Makefile:

CC = gcc
CFLAGS = -ansi -Wall -g -O0 -Wwrite-strings -Wshadow \
-pedantic-errors -fstack-protector-all 
PROGS = public01 public02 public03 public04 public05 public06 shell_jr

.PHONY: all clean

all: $(PROGS)

clean:
    rm -f *.o $(PROGS) a.out

$(PROGS): shell_jr.c
public0%:
    shell_jr < public0%.in > output
    cat output

每当输入 public0X 时,应该显示 shell_jr.c 的输出,当它使用来自 public0X.in 的输入运行时。public0% 标签是我试图做到这一点的尝试。但是,有3个问题。首先,我只能将 public0%.in 作为依赖项。这可以通过复制粘贴 public01、public02、...的单独命令来避免。其次,当我这样做并执行 make 时,命令会立即执行。如何确保在键入 public01 并按 Enter 之前不会执行该命令?

标签: cmakefile

解决方案


首先,我只能将 public0%.in 作为依赖项。

我认为这部分是询问如何在配方中表达与所选目标相对应的输入文件的正确名称。模式规则的%扩展仅在目标和先决条件中,而不是在配方中,但在任何 make配方中,自动变量$@表示正在构建的完整目标名称。由于想要的输入名称是通过将后缀附加.in到目标名称来形成的,因此可以表示为$@.in

此外,您没有将public0%目标命名为.PHONY(与cleanand不同all),但您对它们的规则实际上也不会创建它们。如果您同时尝试创建和显示这些文件,那么您还可以使用$@将输出定向到所需文件。否则,您也应该将这些目标标记为.PHONY.

此外,如果您打算(重新)创建这些文件而不管是否有任何更改,那么从先决条件列表中省略输入文件是合适的。但是,否则,将输入文件命名为先决条件将有助于make跳过不必要的重新生成%public0%文件。

其次,当我这样做并执行 make 时,命令会立即执行。如何确保在键入 public01 并按 Enter 之前不会执行该命令?

make不是交互式的。如果要指定要构建的特定目标或目标,而不是默认目标,则将它们表示为make命令行上的附加参数:

make public01

但是我认为您要解决的问题可能与您实际所说的不同。您的默认目标将构建所有在 中命名的目标$(PROGS),并且在先决条件不需要的情况下,make以串行模式运行的 GNU 将尝试按照它们命名的顺序构建目标。你们public0%所有人都依赖于该shell_jr程序,但他们并未将其指定为先决条件。(它们确实将其命名shell_jr.c为先决条件,但这实际上并不是直接依赖关系,并且将其指定为一个没有用处。)因此,make将在尝试构建所有public0%目标之前尝试构建shell_jr.

正确的做法是表达正确的依赖关系。这个版本是这样做的,假设它们public0%是实际构建的文件:

CC = gcc
CFLAGS = -ansi -Wall -g -O0 -Wwrite-strings -Wshadow \
    -pedantic-errors -fstack-protector-all 

PROGS = shell_jr
OUTPUTS = public01 public02 public03 public04 public05 public06

.PHONY: all clean

all: $(PROGS) $(OUTPUTS)

clean:
    rm -f *.o $(PROGS) $(OUTPUTS)

# shell_jr is built according to a built-in rule (as was already the case)

public0%: public0%.in shell_jr
    shell_jr < $@.in > $@
    cat $@

请注意,public0%仅当相应的输入文件已更改或shell_jr需要重建时,才会重建(并显示)文件。如果您希望在没有任何更改的情况下构建和显示它们,那么您可以添加一个没有先决条件或配方的目标,并将其作为public0%规则的先决条件:

public0%: public0%.in shell_jr FORCE
    shell_jr < $@.in > $@
    cat $@

FORCE:

.PHONY: FORCE

FORCE每次make运行都会认为目标已经重建,从而触发public0%要重建的目标。


推荐阅读