2
votes

I have a target in a gnu-make Makefile that looks like this:

Makefile fragment:

rateplots: binattrate.bin
    gnuplot -c $(src)\Plot.gp binattrate.bin

The utilty gnuplot interpretes $1 as special field in the Plot.gp script and when invoked directly from the shell terminal, the script runs correctly. When run as a rule from the Makefile fragment shown above, it fails in gnuplot-.

I have discovered that I can substitute a doubled $ in the Plot.gp script. That is, substitute $$1 for $1 in Plot.gp and the make rule functions just as it does without substitution from the shell terminal. It appears that gnuplot sees command arguments $0, $1, $2 etc passed from make. I don't want this. I want gnuplot to interpret $1 as it's own field variable.

I can hack a sed script in the make before calling gnuplot to substitute $ for $$ in Plot.gp but I prefer a solution that does not modify the original code as the hack increases the complexity of the code and makes it harder for others to understand the makefile. In summary, I want gnu-make to call the rule without substituting $1 command arguments variables or any other occult variables.

I'm working on a Windows 10 platform with cygwin64

  1. and GNU Make 4.3 and
  2. gnuplot 5.2 (patchlevel 8) {see note added at end of post}

Here is the line in Plot.gp that fails:

plot inputfile every ::1 binary format=fileformat \
   using (gtime+$1):2  with lines linestyle 1 linecolor rgbcolor "black" linewidth 3 title 'GPS1/GPS2'

if I replace $1 with $$1, the code works just as it would when invoked manually from the command shell.

I have worked around this by adding a rule that uses sed to substitute $$ for $, emitting a "scratch.gp" thus:

rateplots: binattrate.bin
  cat $(src)/Plot.gp | sed 's/\$$/\$$\$$/g' >scratch.gp
  gnuplot -c scratch.gp binattrate.bin

I've found the workaround to be robust in 5 other related scripts but it should not be doing this.

I speculate it is a bug in gnuplot (which is fairly new) under cygwin or some element of the Windows cmd shell -- but I don't know. The thing I'm experiencing should be impossible. It's quite important that I find a solution.

Thank you all.

NB: I discovered that when I call gnuplot from my shell terminal window thus:

gnuplot --version

the following is returned:

gnuplot 5.2 patchlevel 8

however when create a makefile to issue the same command in a recipe:

all:
     gnuplot --version

the command

make all

returns

gnuplot --version
gnuplot 5.4 patchlevel 0

In summary, somehow gnu make calls gnuplot 5.4 patchlevel 0 whereas manually issuing the same command in the shell terminal calls gnuplot 5.2 patchlevel 8. Why would that be the case?

I have further observed that gnuplot 5.4 patchlevel 0 contains version 4 backward compatibility features (which may include interpretation of $n environment variables.

1
Could you please show the line in the gnuplot script Plot.gp that is triggering an error? I cannot see how the normal use inside a using spec could ever be subject to substitution. E.g. If command plot ARGV[1] using ($1):($2) is invoked by the makefile rule shown, it should plot columns 1 and 2 in binattrate.bin. - Ethan
Said more simply: it's not possible for make to "reach into" your file Plot.gp and interfere with any content there, variables or not. The gnuplot program will open the file directly, make is not reading that file. Are you sure that the problem isn't with your backslash? If you use a forward slash in your path like $(src)/Plot.gp does it work? - MadScientist
@MadScientist --Thank you for the reply. It does not work with forward slash. The make function does not construct the path to the Plot.gp file name correctly and make fails at that point. Recall I'm operating in cygwin environment using, in this case, the windows cmd shell. It is not true that it is impossible for make to ""reach into"" Plot.gp as my experience here shows and the work around is to substitute $$1 for $1 which causes the plot to be created normally as it does from the command line shell. - Burton
Well, there's something else going on that is not obvious. However, I'm intimately familiar with the code implementing GNU make and I know for a fact that there's no way it will do anything with Plot.gp, given the makefile you've described above. GNU make doesn't even know that file exists: it takes the text of the recipe and passes it to the shell. It doesn't try to figure out what words in the recipes are files, or options, or whatever, it just passes the whole thing along and lets the shell deal with it. - MadScientist
Perhaps you have another, different part of your makefile that constructs the Plot.gp file, using a different recipe, and that one might be doing the wrong thing? All I can say is that given the makefile above, what you are stating as the problem (that make is expanding the contents of that file) is simply not possible. Maybe gnuplot itself has some option that does expansion differently in different contexts or something. - MadScientist

1 Answers

3
votes

All elements of my problem result from:

  1. bug in gnuplot 5.4.0
  2. make invokes /bin/sh (linux bash) instead of the windows shell.

I submitted a bug report on gnuplot 5.4.0 in cygwin distribution to the gnuplot development group (https://sourceforge.net/p/gnuplot/bugs/2368/). The developer says it will be fixed in 5.4.1.

The bug results from deprecated $0, $1, $2 etc symbols being erroneously enabled and assigned to gnuplot (5.4.0) to command line arguments.

The bugged Gnuplot 5.4.0 is “gnuplot-base.exe” and the “obsolete” gnuplot 5.2.8 appears in the cygwin distribution as “gnuplot.exe”.

I observe command “gnuplot”:

  1. from a windows cmd shell runs “gnuplot.exe” (5.2.8).
  2. whereas from /bin/sh links to gnuplot point to “gnuplot-base.exe”(5.4.0).

The “make” utility submits rules through /bin/sh explaining why gnuplot fails in “make” but not from the command shell.

I’m working around by calling “gnuplot.exe” instead of “gnuplot” in "make" rules. “gnuplot.exe is the obsolete version 5.2.8.

Thank you. I love you all.