为什么使用引号表现不同?

时间:2015-10-22 17:33:48

标签: makefile

我知道引号不应该在Makefile中使用,但出于好奇,为什么makemake foobarmake的行为不同。请参阅下面的详细代码。

生成文件:

TARGET = 'foobar'

$(TARGET): foobar.cpp
    g++ -g $^ -o $@

clean:
    rm foobar

输出:

$ make
g++ -g foobar.cpp -o 'foobar'           <-- correct
$ make clean
rm foobar
$ make foobar
g++     foobar.cpp   -o foobar          <-- incorrect but works. Why?
$ make clean
rm foobar
$ make baz                              <-- doesn't work, which is normal
make: *** No rule to make target 'baz'.  Stop.
$ 

2 个答案:

答案 0 :(得分:1)

这是因为make在找不到构建目标的特定规则时会使用默认规则。

即使没有空program,也可以从program.cpp汇总Makefile。尝试

make -f /dev/null foobar

默认规则由POSIX指定,您的make实现可能有一些。

尝试构建baz失败,因为没有一个默认规则知道如何构建baz.cbaz.cpp或任何其他可用于构建{{1}的内置源文件}}

答案 1 :(得分:1)

这只是“有效”,因为shell正在从你的第一个例子中删除单引号。

引号在$(TARGET) make变量的值中字面上。 make不会取消TARGET = 'foobar'作业的右侧。

您可以在makefile中使用$(info $(TARGET))来查看此内容。

所以你的目标行:

$(TARGET): foobar.cpp

正在创建一个名称为'foobar'而不是foobar的目标。

这就是运行make执行“正确”操作而make foobar执行其他操作的原因。

make foobar正在为%: %.cpp运行make built in规则。

您的默认'foobar'目标用于创建foobar这一事实是因为 shell 会看到单引号并将其删除。

您会注意到,如果您make; make制作'foobar'目标两次,但make foobar; make foobar会告诉您没有任何事情要做第二次。那是因为第一个目标创建的文件与<期望不同

如果您在食谱线中引用$@,您会看到不同的行为。

$(TARGET): foobar.cpp
    g++ -g $^ -o '$@'
例如,

会生成g++ -g foobar.cpp -o ''foobar''并在

时生成foobar文件
$(TARGET): foobar.cpp
    g++ -g $^ -o "$@"

会运行g++ -g foobar.cpp -o "'foobar'"并生成'foobar'文件(这会导致make; make报告第二次make运行无法执行任何操作。

您希望配方行中的引号不在此变量中。

TARGET = foobar

$(TARGET): foobar.cpp
    g++ -g $^ -o '$@'

clean:
    rm foobar

这就是说,因为你不能在make目标名中有空格(至少不可靠),这些单引号(或任何引用)的需求会减少,因为如果文件名包含shell元字符,你只需要它。