It's unclear from the original question, but I presume that file1 is part of the useful output of the Makefile, and needs to be kept around after the Perl script runs.
Regardless, it seems fine to use a command substitution here, which saves you from having to create extra targets or temp files, and clean those up afterwards.
file1 = path/to/some/file
$(file1):
some steps to create the file
call_perl_script: $(file1)
perl script.pl in="`sed -n '/^col1;col2;col3/p' $<`"
The double quotes around the backticks are absolutely required here to prevent the shell from treating the ;s as command separators, which would otherwise result in an error. You could use GNU Make's $(shell …) function here instead of backticks, but it doesn't save any typing, and isn't portable to non-GNU systems, if that's a concern.
Assuming the header is the first line of the file, you can simplify that last target further, to just:
call_perl_script: $(file1)
perl script.pl in="`head -n 1 $<`"
The head command is specified by POSIX, so it's basically guaranteed to be available. You could also use sed -n 1p.
If you're unfamiliar with command substitutions (the commands in `backticks` here), they run a command and return its output, with trailing newlines removed. In Bash and other modern shells, you usually see this as $(command with args). However, by default, Makefile recipes run with /bin/sh, the POSIX/Bourne shell—not your user's login shell—unless otherwise specified.
The $< above refers to the rule's first dependency, $(file1); see "Automatic Variables" in the manual, if this was unfamiliar to you.
Confusion about passing variables between Makefile targets
I think the OP's question originates from the somewhat-confusing concept of variables' "scope" in Makefiles. There are really two separate ones:
- a "global" scope for make variables, defined outside any recipes
- —and— a scope for shell variables
- because each Make recipe line runs in its own subshell, each recipe line is a separate scope for shell variables*
You can send Make variables in to the scope of a recipe with
- direct substitution, using Make's
$(VARNAME) or ${VARNAME} variable syntax
- —or— export a Make variable to the recipe's environment with
export VARNAME outside the recipe, then $$VARNAME using shell variable syntax inside the recipe
…but you can't go the other way. This means it's just not possible to pass values between Makefile targets with variables alone.
If you're thinking of reaching for $(eval …), now you have two problems. There is almost definitely a simpler solution for what you're trying to do.
Aside about quoting
For clarity, I recommend omitting quotes from Makefile variable definitions for simple string values like header in the OP's first example. Make itself doesn't care about those quotes, but the shell does.
Instead, wrap the Make variables in quotes when referenced within your recipes, where the shell would require them. For example:
all: works-but-not-optimal quotes-cause-problems better also-okay
works-but-not-optimal: GREET = "\nHi! How are you?\n"
works-but-not-optimal:
@printf $(GREET)
quotes-cause-problems: GREET = "Hallo! Wie geht es Ihnen?"
quotes-cause-problems:
@printf "\n$(GREET)\n"
better: MSG = ¡Hola, buenos días!
better:
@printf "\n$(MSG)\n"
also-okay: export MSG = Buon giorno!
also-okay:
@printf "\n$$MSG\n"
In Makefiles, leading whitespace for top-level variable definitions is trimmed, but all remaining internal or trailing whitespace is preserved intact. That does mean, however, that you need to watch out for trailing whitespace (:set list for the vi users) in variable definitions. It's never easy!
Make isn't great about handling filenames with spaces in them either, as targets or dependencies, so these are best avoided. You'll also have challenges if you need to represent quotes within quotes—good luck with those backslashes! Consider using typographic quotes instead, if they're just for display purposes.
By the way, all three examples above demonstrate target-specific variables as that phrase is used in the GNU Make manual.
Hope that helps (someone)!
* …unless you take steps to force multiple recipe lines to run in the same subshell, which is out of scope for this already-sprawling answer. ;)