3

I would like to include the following command (taken from here) in a Makefile. A simple version of my Makefile script containing the command is:

copy_files:
    sed 's/^/\./' ./input_file | \
        rev | \
        LC_ALL=C sort -u | \
        awk 'p == "" || substr($0,1,length(p)) != p { print $0; p = $0 }' | \
        rev | \
        sed 's/^\.//' > ./output_file

The problem I am having is that when I execute it using make, it fails to recognise the $0 symbol:

awk: cmd. line:1: p == "" || substr(,1,length(p)) != p { print ; p =  }
awk: cmd. line:1:                   ^ syntax error
awk: cmd. line:1: p == "" || substr(,1,length(p)) != p { print ; p =  }
awk: cmd. line:1:                                                     ^ syntax error

I tried escaping the $0 using \$0 without success. What is the solution?

1
  • 1
    Makefiles are already free to use ;)
    – ggrant
    Apr 16 at 18:50

1 Answer 1

4

You were on the right path; to escape the dollar symbol in a Makefile, you need to use $$, not \$:

copy_files:
    sed 's/^/\./' ./input_file | \
        rev | \
        LC_ALL=C sort -u | \
        awk 'p == "" || substr($$0,1,length(p)) != p { print $$0; p = $$0 }' | \
        rev | \
        sed 's/^\.//' > ./output_file

Since you’re constructing an output file using an input file, you should tell Make about this explicitly:

output_file: input_file
    sed 's/^/\./' $< | \
        rev | \
        LC_ALL=C sort -u | \
        awk 'p == "" || substr($$0,1,length(p)) != p { print $$0; p = $$0 }' | \
        rev | \
        sed 's/^\.//' > $@

With this definition, Make will “rebuild” output_file if it is missing or if input_file is newer. $< references the input(s) (known as prerequisites), $@ references the output (known as the target).

If you want a copy_files target, declare that as depending on output_file:

copy_files: output_file

If your Make knows about phony targets, mention that too:

.PHONY: copy_files
copy_files: output_file
2
  • Thanks very much. I'm not experienced with Makefiles, I did not even know that "copy_files" had meaning.. Thanks very much.
    – ellat
    Apr 16 at 9:30
  • 2
    @Stewart not quite, it’s target: prerequisites \n\trecipe. Recipes are the sequences of commands used to produce a target using prerequisites (if any). The overall construct is referred to as a rule. copy_files is a target, and invoking it with make copy_files runs the corresponding recipe. See the “Rules” chapter in the GNU Make manual. Apr 16 at 14:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .