使用命令行,我得到了所需的输出
$ ./program $(< file.txt)
./program 1 2 3 4 5
但是使用makefile
all: program file.txt
./program $(< file.txt)
@rm -f program
program: program.c
gcc program.c -o program
我得到了输出
gcc program.c -o program
./program
因为在makefile中,$(...)
语法用于变量插值。因此,您的makefile尝试展开名为< file.txt
的makefile变量/环境变量的值。如果未设置,则展开为空字符串。
证明:
all:
echo $(< file.txt)
和包含
的file.txtnow it works
然后执行
% env '< file.txt=Hello world' make
echo Hello world
Hello world
。通过将环境变量< file.txt
设置为值Hello world
,打印问候语。修复方法是通过将$
字符加倍来转义:
all:
echo $$(< file.txt)
和
% make
echo $(< file.txt)
now it works
Q.E.D.
最后,当POSIXshell中的$()
插值语法$(< file.txt)
不是,但您可以用$(cat file.txt)
替换它,因此它可以与最低限度的posix兼容shell一起工作。当然,在makefile中,您需要再次将美元翻倍,因此获得最大兼容的
$$(cat file.txt)
或者您可以使用类似的makefile工具,即$(shell )
,即
$(shell cat file.txt)
也可以…(现在有一个$
)。最后你也可以使用$(file )
GNU makefile函数来读取文件,即
all:
echo $(file <file.txt)
的工作原理类似,但根本不会调用shell。
您尝试使用的替换是Bash特性,但是make
开箱运行常规的Bourne shellsh
,其中该语法不可用(即使sh
是Bash的符号链接,这在某些Linux发行版中仍然很常见)。
无论如何,要求在命令行上指定文件的内容看起来像是一个设计缺陷;如果您的C程序只是读取和处理标准输入(或者可能接受一个文件名列表,如果没有指定,则返回到stdin,就像许多Unix文件处理实用程序一样),则可能要好得多。
如果这只是一个测试用例来运行带有文件参数的程序,请查看xargs
。
xargs ./program <file.txt
如果您坚持只使用bash语法,请添加
SHELL=/bin/bash
(或任何在您的系统上正确的完整路径);但要理解这限制了Makefile
的可移植性。
但是,您仍然需要将任何应该传递并暴露给shell的美元符号的字面量加倍。