Reputation: 118
Using the command line I get the desired output
$ ./program $(< file.txt)
./program 1 2 3 4 5
But with a makefile
all: program file.txt
./program $(< file.txt)
@rm -f program
program: program.c
gcc program.c -o program
I get the output
gcc program.c -o program
./program
Upvotes: 2
Views: 218
Reputation: 133929
Because in a makefile, the $(...)
syntax is used for variable interpolation. So your makefile tries to expand the value of a makefile variable / environment variable named < file.txt
. And if unset, it expands to an empty string.
Proof:
all:
echo $(< file.txt)
and file.txt containing
now it works
Then execute
% env '< file.txt=Hello world' make
echo Hello world
Hello world
i.e. by setting an environment variable named < file.txt
to value Hello world
, the greeting was printed. The fix is to escape the $
character by doubling it:
all:
echo $$(< file.txt)
and then
% make
echo $(< file.txt)
now it works
Q.E.D.
Finally, while the $()
interpolation syntax in POSIX shells, the $(< file.txt)
is not but you can replace it with $(cat file.txt)
so it works with minimally POSIX-conforming shells. Of course in a makefile you again need to double the dollar, therefore getting the maximally compatible
$$(cat file.txt)
Alternatively you can use the similar makefile facility which is $(shell )
, i.e.
$(shell cat file.txt)
would work too... (now with one $
). Finally you can read files with $(file )
GNU makefile function too, i.e.
all:
echo $(file <file.txt)
would work alike but wouldn't call shell at all.
Upvotes: 4
Reputation: 189457
The substitution you are trying to use is a Bash feature, but make
out of the box runs the regular Bourne shell sh
, where this syntax is not available (even when sh
is a symlink to Bash, as is still common on some Linux distributions).
Requiring the contents of the file to be specified on the command line looks like a design flaw, anyway; it's probably much better if your C program simply reads and processes standard input (or perhaps accepts a list of file names, and falls back to stdin if none are specified, like many Unix file processing utilities).
If this is just for a test case to run the program with parameters from a file, check out xargs
.
xargs ./program <file.txt
If you insist on using Bash-only syntax, add
SHELL=/bin/bash
(or whatever full path is correct on your system); but understand that this limits the portability of your Makefile
.
Still, you'll need to double any literal dollar sign which should be passed through and exposed to the shell.
Upvotes: 0