Make says file is up to date, but it does not exist












-1















I want



I am trying to compile some latex that has snippets of python code and the output of those snippets. I need the document to be always updated with the last changes made in the snippets and in their outputs, so the idea is maintain a makefile that could monitor this changes and generate the updated outputs.



So if I modify the file a/11.py, I want make to execute it to generate a new output a/11.out.



I have



This is my makefile



DOC=myPdf
STY=st
PY_DIR=a/
TEX=pdflatex -shell-escape -interaction=batchmode -file-line-error

$(DOC).pdf: $(PY_DIR)11.out $(PY_DIR)12.out $(DOC).tex $(STY).sty
$(TEX) $(DOC).tex

$(PY_DIR)11.out:
$(cd PY_DIR && python3 11.py > 11.out)

$(PY_DIR)12.out:
$(cd PY_DIR && python3 12.py > 12.out)

.PHONY: clean
clean:
rm *.aux *.log > /dev/null 2>&1


I wonder



Even when the file a/11.out doesn't exist, and I instruct make a/11.out make says: make: 'a/11.out' is up to date. (I am still learning make, so I probably have more mistakes).



I saw





  • Make in subfolder, but because I am not using $(MAKE), I cannot use it.


  • Similar question, but I don't think it is the same.


Thank you for your time :)





Update



This is my new version, based in the answer of Renaud (thanks for your help), some python scripts are intended to output text (xxxt.py), and others to plot images (xxxi.py), so there is no redirection for them:



DOC    :=myPdf
STY :=st
PY_DIR :=a/
TEX :=pdflatex -shell-escape -interaction=batchmode -file-line-error
PYS := $(wildcard $(PY_DIR)*.py)
OUTS := $(patsubst %.py,%.out,$(PYS))
.PHONY: all clean

all: $(DOC).pdf

%.pdf: %.tex $(STY).sty $(OUTS)
$(TEX) $<

$(PY_DIR)%.out: $(PY_DIR)%t.py
cd $(PY_DIR) && python3 $*t.py > $*.out

$(PY_DIR)%.png: $(PY_DIR)%i.py
cd $(PY_DIR) && python3 $*i.py

clean:
rm *.aux *.log > /dev/null 2>&1


The directory looks like this:



./st.sty
./myPdf.tex
./myPdf.pdf
./a/11t.py
./a/11.out
./a/12i.py
./a/12.png
./a/21t.py
./a/...


However, now right after modifying myPdf.tex, make says make: Nothing to be done for 'all'.



What am I doing wrong?










share|improve this question





























    -1















    I want



    I am trying to compile some latex that has snippets of python code and the output of those snippets. I need the document to be always updated with the last changes made in the snippets and in their outputs, so the idea is maintain a makefile that could monitor this changes and generate the updated outputs.



    So if I modify the file a/11.py, I want make to execute it to generate a new output a/11.out.



    I have



    This is my makefile



    DOC=myPdf
    STY=st
    PY_DIR=a/
    TEX=pdflatex -shell-escape -interaction=batchmode -file-line-error

    $(DOC).pdf: $(PY_DIR)11.out $(PY_DIR)12.out $(DOC).tex $(STY).sty
    $(TEX) $(DOC).tex

    $(PY_DIR)11.out:
    $(cd PY_DIR && python3 11.py > 11.out)

    $(PY_DIR)12.out:
    $(cd PY_DIR && python3 12.py > 12.out)

    .PHONY: clean
    clean:
    rm *.aux *.log > /dev/null 2>&1


    I wonder



    Even when the file a/11.out doesn't exist, and I instruct make a/11.out make says: make: 'a/11.out' is up to date. (I am still learning make, so I probably have more mistakes).



    I saw





    • Make in subfolder, but because I am not using $(MAKE), I cannot use it.


    • Similar question, but I don't think it is the same.


    Thank you for your time :)





    Update



    This is my new version, based in the answer of Renaud (thanks for your help), some python scripts are intended to output text (xxxt.py), and others to plot images (xxxi.py), so there is no redirection for them:



    DOC    :=myPdf
    STY :=st
    PY_DIR :=a/
    TEX :=pdflatex -shell-escape -interaction=batchmode -file-line-error
    PYS := $(wildcard $(PY_DIR)*.py)
    OUTS := $(patsubst %.py,%.out,$(PYS))
    .PHONY: all clean

    all: $(DOC).pdf

    %.pdf: %.tex $(STY).sty $(OUTS)
    $(TEX) $<

    $(PY_DIR)%.out: $(PY_DIR)%t.py
    cd $(PY_DIR) && python3 $*t.py > $*.out

    $(PY_DIR)%.png: $(PY_DIR)%i.py
    cd $(PY_DIR) && python3 $*i.py

    clean:
    rm *.aux *.log > /dev/null 2>&1


    The directory looks like this:



    ./st.sty
    ./myPdf.tex
    ./myPdf.pdf
    ./a/11t.py
    ./a/11.out
    ./a/12i.py
    ./a/12.png
    ./a/21t.py
    ./a/...


    However, now right after modifying myPdf.tex, make says make: Nothing to be done for 'all'.



    What am I doing wrong?










    share|improve this question



























      -1












      -1








      -1








      I want



      I am trying to compile some latex that has snippets of python code and the output of those snippets. I need the document to be always updated with the last changes made in the snippets and in their outputs, so the idea is maintain a makefile that could monitor this changes and generate the updated outputs.



      So if I modify the file a/11.py, I want make to execute it to generate a new output a/11.out.



      I have



      This is my makefile



      DOC=myPdf
      STY=st
      PY_DIR=a/
      TEX=pdflatex -shell-escape -interaction=batchmode -file-line-error

      $(DOC).pdf: $(PY_DIR)11.out $(PY_DIR)12.out $(DOC).tex $(STY).sty
      $(TEX) $(DOC).tex

      $(PY_DIR)11.out:
      $(cd PY_DIR && python3 11.py > 11.out)

      $(PY_DIR)12.out:
      $(cd PY_DIR && python3 12.py > 12.out)

      .PHONY: clean
      clean:
      rm *.aux *.log > /dev/null 2>&1


      I wonder



      Even when the file a/11.out doesn't exist, and I instruct make a/11.out make says: make: 'a/11.out' is up to date. (I am still learning make, so I probably have more mistakes).



      I saw





      • Make in subfolder, but because I am not using $(MAKE), I cannot use it.


      • Similar question, but I don't think it is the same.


      Thank you for your time :)





      Update



      This is my new version, based in the answer of Renaud (thanks for your help), some python scripts are intended to output text (xxxt.py), and others to plot images (xxxi.py), so there is no redirection for them:



      DOC    :=myPdf
      STY :=st
      PY_DIR :=a/
      TEX :=pdflatex -shell-escape -interaction=batchmode -file-line-error
      PYS := $(wildcard $(PY_DIR)*.py)
      OUTS := $(patsubst %.py,%.out,$(PYS))
      .PHONY: all clean

      all: $(DOC).pdf

      %.pdf: %.tex $(STY).sty $(OUTS)
      $(TEX) $<

      $(PY_DIR)%.out: $(PY_DIR)%t.py
      cd $(PY_DIR) && python3 $*t.py > $*.out

      $(PY_DIR)%.png: $(PY_DIR)%i.py
      cd $(PY_DIR) && python3 $*i.py

      clean:
      rm *.aux *.log > /dev/null 2>&1


      The directory looks like this:



      ./st.sty
      ./myPdf.tex
      ./myPdf.pdf
      ./a/11t.py
      ./a/11.out
      ./a/12i.py
      ./a/12.png
      ./a/21t.py
      ./a/...


      However, now right after modifying myPdf.tex, make says make: Nothing to be done for 'all'.



      What am I doing wrong?










      share|improve this question
















      I want



      I am trying to compile some latex that has snippets of python code and the output of those snippets. I need the document to be always updated with the last changes made in the snippets and in their outputs, so the idea is maintain a makefile that could monitor this changes and generate the updated outputs.



      So if I modify the file a/11.py, I want make to execute it to generate a new output a/11.out.



      I have



      This is my makefile



      DOC=myPdf
      STY=st
      PY_DIR=a/
      TEX=pdflatex -shell-escape -interaction=batchmode -file-line-error

      $(DOC).pdf: $(PY_DIR)11.out $(PY_DIR)12.out $(DOC).tex $(STY).sty
      $(TEX) $(DOC).tex

      $(PY_DIR)11.out:
      $(cd PY_DIR && python3 11.py > 11.out)

      $(PY_DIR)12.out:
      $(cd PY_DIR && python3 12.py > 12.out)

      .PHONY: clean
      clean:
      rm *.aux *.log > /dev/null 2>&1


      I wonder



      Even when the file a/11.out doesn't exist, and I instruct make a/11.out make says: make: 'a/11.out' is up to date. (I am still learning make, so I probably have more mistakes).



      I saw





      • Make in subfolder, but because I am not using $(MAKE), I cannot use it.


      • Similar question, but I don't think it is the same.


      Thank you for your time :)





      Update



      This is my new version, based in the answer of Renaud (thanks for your help), some python scripts are intended to output text (xxxt.py), and others to plot images (xxxi.py), so there is no redirection for them:



      DOC    :=myPdf
      STY :=st
      PY_DIR :=a/
      TEX :=pdflatex -shell-escape -interaction=batchmode -file-line-error
      PYS := $(wildcard $(PY_DIR)*.py)
      OUTS := $(patsubst %.py,%.out,$(PYS))
      .PHONY: all clean

      all: $(DOC).pdf

      %.pdf: %.tex $(STY).sty $(OUTS)
      $(TEX) $<

      $(PY_DIR)%.out: $(PY_DIR)%t.py
      cd $(PY_DIR) && python3 $*t.py > $*.out

      $(PY_DIR)%.png: $(PY_DIR)%i.py
      cd $(PY_DIR) && python3 $*i.py

      clean:
      rm *.aux *.log > /dev/null 2>&1


      The directory looks like this:



      ./st.sty
      ./myPdf.tex
      ./myPdf.pdf
      ./a/11t.py
      ./a/11.out
      ./a/12i.py
      ./a/12.png
      ./a/21t.py
      ./a/...


      However, now right after modifying myPdf.tex, make says make: Nothing to be done for 'all'.



      What am I doing wrong?







      makefile gnu-make






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 18 '18 at 19:38







      onlycparra

















      asked Nov 18 '18 at 8:45









      onlycparraonlycparra

      499




      499
























          1 Answer
          1






          active

          oldest

          votes


















          1














          Your recipes are wrong. Make expands the recipes before passing them to the shell. As there is no make variable named cd PY_DIR && python3 11.py > 11.out, $(cd PY_DIR && python3 11.py > 11.out) expands as the empty string and make considers that there is nothing to do for $(PY_DIR)11.out. Just write your recipes as plain shell (and fix the other bug with the unexpanded PY_DIR):



          $(PY_DIR)11.out:
          cd $(PY_DIR) && python3 11.py > 11.out

          $(PY_DIR)12.out:
          cd $(PY_DIR) && python3 12.py > 12.out


          Note: if you want make to re-run the recipes when your python scripts change you should let him know that the output files depend on the python scripts. The best is probably to use a pattern rule instead of one specific rule per file:



          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out


          ($* is a make automatic variable, it expands as the stem of the pattern).



          A few more improvements:




          • You could ask make to find alone the python scripts, compute the names of the output files and store all this in make variables that you can used in your other rules.

          • You can use a pattern rule for the xx.tex -> xx.pdf process. And use another make automatic variable for it: $< that expands as the first prerequisite.


          DOC    := myPdf
          STY := st
          PY_DIR := a/
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error

          PYS := $(wildcard $(PY_DIR)*.py)
          OUTS := $(patsubst %.py,%.out,$(PYS))

          .PRECIOUS: $(OUTS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(OUTS) $(STY).sty
          $(TEX) $<

          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out

          .PHONY: clean
          clean:
          rm *.aux *.log > /dev/null 2>&1


          Note: I declared $(OUTS) as precious such that make does not delete them when it is done with the building of $(DOC).pdf.



          Update with the new specifications and separated python scripts for xx.out and xx.png production:



          DOC    := myPdf
          STY := st
          PY_DIR := a
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error
          PYTS := $(wildcard $(PY_DIR)/*t.py)
          PYIS := $(wildcard $(PY_DIR)/*i.py)
          OUTS := $(patsubst $(PY_DIR)/%t.py,$(PY_DIR)/%.out,$(PYTS))
          PNGS := $(patsubst $(PY_DIR)/%i.py,$(PY_DIR)/%.png,$(PYIS))

          .PRECIOUS: $(OUTS) $(PNGS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(STY).sty $(OUTS) $(PNGS)
          $(TEX) $<

          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(PY_DIR) && python3 $*t.py > $*.out

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(PY_DIR) && python3 $*i.py

          clean:
          rm -f *.aux *.log > /dev/null 2>&1


          Notes:




          • I slightly modified the definition of PY_DIR such that, when used in other parts of the Makefile, it is clear that it is a directory path. Just a matter of taste, I guess.

          • I added the -f option to your clean recipe such that it doesn't fail if the files to delete do not exist.


          Update:



          As noted by MadScientist in a comment, using $* is less generic than referring to the target ($@) and the prerequisite ($<). But as we are operating not directly on them but on their directory ($(PY_DIR)) and base file names (xx[it].py, xx.out, xx.png), switching from $* to other, more generic, automatic variables is not that simple.



          But make has some more tricks that can help here: $@, $<... have variants ($(@F), $(@D)...) that expand to just the directory part or the file part. Note that, according the GNU make manual:




          These variants are semi-obsolete in GNU make since the functions dir
          and notdir can be used to get a similar effect.




          Anyway, if we wanted to avoid $* here is what we could use instead:



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(@D) && python3 $(<F) > $(@F)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(@D) && python3 $(<F)


          Or (modern version):



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(dir $@) && python3 $(notdir $<) > $(notdir $@)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(dir $@) && python3 $(notdir $<)





          share|improve this answer


























          • You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

            – MadScientist
            Nov 18 '18 at 14:21











          • Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

            – Renaud Pacalet
            Nov 18 '18 at 14:37











          • Oh you're right I missed the cd. Sorry!

            – MadScientist
            Nov 18 '18 at 17:30











          • wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

            – onlycparra
            Nov 18 '18 at 18:56











          • I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

            – onlycparra
            Nov 18 '18 at 19:17











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53359188%2fmake-says-file-is-up-to-date-but-it-does-not-exist%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Your recipes are wrong. Make expands the recipes before passing them to the shell. As there is no make variable named cd PY_DIR && python3 11.py > 11.out, $(cd PY_DIR && python3 11.py > 11.out) expands as the empty string and make considers that there is nothing to do for $(PY_DIR)11.out. Just write your recipes as plain shell (and fix the other bug with the unexpanded PY_DIR):



          $(PY_DIR)11.out:
          cd $(PY_DIR) && python3 11.py > 11.out

          $(PY_DIR)12.out:
          cd $(PY_DIR) && python3 12.py > 12.out


          Note: if you want make to re-run the recipes when your python scripts change you should let him know that the output files depend on the python scripts. The best is probably to use a pattern rule instead of one specific rule per file:



          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out


          ($* is a make automatic variable, it expands as the stem of the pattern).



          A few more improvements:




          • You could ask make to find alone the python scripts, compute the names of the output files and store all this in make variables that you can used in your other rules.

          • You can use a pattern rule for the xx.tex -> xx.pdf process. And use another make automatic variable for it: $< that expands as the first prerequisite.


          DOC    := myPdf
          STY := st
          PY_DIR := a/
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error

          PYS := $(wildcard $(PY_DIR)*.py)
          OUTS := $(patsubst %.py,%.out,$(PYS))

          .PRECIOUS: $(OUTS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(OUTS) $(STY).sty
          $(TEX) $<

          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out

          .PHONY: clean
          clean:
          rm *.aux *.log > /dev/null 2>&1


          Note: I declared $(OUTS) as precious such that make does not delete them when it is done with the building of $(DOC).pdf.



          Update with the new specifications and separated python scripts for xx.out and xx.png production:



          DOC    := myPdf
          STY := st
          PY_DIR := a
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error
          PYTS := $(wildcard $(PY_DIR)/*t.py)
          PYIS := $(wildcard $(PY_DIR)/*i.py)
          OUTS := $(patsubst $(PY_DIR)/%t.py,$(PY_DIR)/%.out,$(PYTS))
          PNGS := $(patsubst $(PY_DIR)/%i.py,$(PY_DIR)/%.png,$(PYIS))

          .PRECIOUS: $(OUTS) $(PNGS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(STY).sty $(OUTS) $(PNGS)
          $(TEX) $<

          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(PY_DIR) && python3 $*t.py > $*.out

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(PY_DIR) && python3 $*i.py

          clean:
          rm -f *.aux *.log > /dev/null 2>&1


          Notes:




          • I slightly modified the definition of PY_DIR such that, when used in other parts of the Makefile, it is clear that it is a directory path. Just a matter of taste, I guess.

          • I added the -f option to your clean recipe such that it doesn't fail if the files to delete do not exist.


          Update:



          As noted by MadScientist in a comment, using $* is less generic than referring to the target ($@) and the prerequisite ($<). But as we are operating not directly on them but on their directory ($(PY_DIR)) and base file names (xx[it].py, xx.out, xx.png), switching from $* to other, more generic, automatic variables is not that simple.



          But make has some more tricks that can help here: $@, $<... have variants ($(@F), $(@D)...) that expand to just the directory part or the file part. Note that, according the GNU make manual:




          These variants are semi-obsolete in GNU make since the functions dir
          and notdir can be used to get a similar effect.




          Anyway, if we wanted to avoid $* here is what we could use instead:



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(@D) && python3 $(<F) > $(@F)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(@D) && python3 $(<F)


          Or (modern version):



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(dir $@) && python3 $(notdir $<) > $(notdir $@)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(dir $@) && python3 $(notdir $<)





          share|improve this answer


























          • You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

            – MadScientist
            Nov 18 '18 at 14:21











          • Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

            – Renaud Pacalet
            Nov 18 '18 at 14:37











          • Oh you're right I missed the cd. Sorry!

            – MadScientist
            Nov 18 '18 at 17:30











          • wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

            – onlycparra
            Nov 18 '18 at 18:56











          • I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

            – onlycparra
            Nov 18 '18 at 19:17
















          1














          Your recipes are wrong. Make expands the recipes before passing them to the shell. As there is no make variable named cd PY_DIR && python3 11.py > 11.out, $(cd PY_DIR && python3 11.py > 11.out) expands as the empty string and make considers that there is nothing to do for $(PY_DIR)11.out. Just write your recipes as plain shell (and fix the other bug with the unexpanded PY_DIR):



          $(PY_DIR)11.out:
          cd $(PY_DIR) && python3 11.py > 11.out

          $(PY_DIR)12.out:
          cd $(PY_DIR) && python3 12.py > 12.out


          Note: if you want make to re-run the recipes when your python scripts change you should let him know that the output files depend on the python scripts. The best is probably to use a pattern rule instead of one specific rule per file:



          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out


          ($* is a make automatic variable, it expands as the stem of the pattern).



          A few more improvements:




          • You could ask make to find alone the python scripts, compute the names of the output files and store all this in make variables that you can used in your other rules.

          • You can use a pattern rule for the xx.tex -> xx.pdf process. And use another make automatic variable for it: $< that expands as the first prerequisite.


          DOC    := myPdf
          STY := st
          PY_DIR := a/
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error

          PYS := $(wildcard $(PY_DIR)*.py)
          OUTS := $(patsubst %.py,%.out,$(PYS))

          .PRECIOUS: $(OUTS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(OUTS) $(STY).sty
          $(TEX) $<

          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out

          .PHONY: clean
          clean:
          rm *.aux *.log > /dev/null 2>&1


          Note: I declared $(OUTS) as precious such that make does not delete them when it is done with the building of $(DOC).pdf.



          Update with the new specifications and separated python scripts for xx.out and xx.png production:



          DOC    := myPdf
          STY := st
          PY_DIR := a
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error
          PYTS := $(wildcard $(PY_DIR)/*t.py)
          PYIS := $(wildcard $(PY_DIR)/*i.py)
          OUTS := $(patsubst $(PY_DIR)/%t.py,$(PY_DIR)/%.out,$(PYTS))
          PNGS := $(patsubst $(PY_DIR)/%i.py,$(PY_DIR)/%.png,$(PYIS))

          .PRECIOUS: $(OUTS) $(PNGS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(STY).sty $(OUTS) $(PNGS)
          $(TEX) $<

          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(PY_DIR) && python3 $*t.py > $*.out

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(PY_DIR) && python3 $*i.py

          clean:
          rm -f *.aux *.log > /dev/null 2>&1


          Notes:




          • I slightly modified the definition of PY_DIR such that, when used in other parts of the Makefile, it is clear that it is a directory path. Just a matter of taste, I guess.

          • I added the -f option to your clean recipe such that it doesn't fail if the files to delete do not exist.


          Update:



          As noted by MadScientist in a comment, using $* is less generic than referring to the target ($@) and the prerequisite ($<). But as we are operating not directly on them but on their directory ($(PY_DIR)) and base file names (xx[it].py, xx.out, xx.png), switching from $* to other, more generic, automatic variables is not that simple.



          But make has some more tricks that can help here: $@, $<... have variants ($(@F), $(@D)...) that expand to just the directory part or the file part. Note that, according the GNU make manual:




          These variants are semi-obsolete in GNU make since the functions dir
          and notdir can be used to get a similar effect.




          Anyway, if we wanted to avoid $* here is what we could use instead:



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(@D) && python3 $(<F) > $(@F)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(@D) && python3 $(<F)


          Or (modern version):



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(dir $@) && python3 $(notdir $<) > $(notdir $@)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(dir $@) && python3 $(notdir $<)





          share|improve this answer


























          • You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

            – MadScientist
            Nov 18 '18 at 14:21











          • Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

            – Renaud Pacalet
            Nov 18 '18 at 14:37











          • Oh you're right I missed the cd. Sorry!

            – MadScientist
            Nov 18 '18 at 17:30











          • wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

            – onlycparra
            Nov 18 '18 at 18:56











          • I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

            – onlycparra
            Nov 18 '18 at 19:17














          1












          1








          1







          Your recipes are wrong. Make expands the recipes before passing them to the shell. As there is no make variable named cd PY_DIR && python3 11.py > 11.out, $(cd PY_DIR && python3 11.py > 11.out) expands as the empty string and make considers that there is nothing to do for $(PY_DIR)11.out. Just write your recipes as plain shell (and fix the other bug with the unexpanded PY_DIR):



          $(PY_DIR)11.out:
          cd $(PY_DIR) && python3 11.py > 11.out

          $(PY_DIR)12.out:
          cd $(PY_DIR) && python3 12.py > 12.out


          Note: if you want make to re-run the recipes when your python scripts change you should let him know that the output files depend on the python scripts. The best is probably to use a pattern rule instead of one specific rule per file:



          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out


          ($* is a make automatic variable, it expands as the stem of the pattern).



          A few more improvements:




          • You could ask make to find alone the python scripts, compute the names of the output files and store all this in make variables that you can used in your other rules.

          • You can use a pattern rule for the xx.tex -> xx.pdf process. And use another make automatic variable for it: $< that expands as the first prerequisite.


          DOC    := myPdf
          STY := st
          PY_DIR := a/
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error

          PYS := $(wildcard $(PY_DIR)*.py)
          OUTS := $(patsubst %.py,%.out,$(PYS))

          .PRECIOUS: $(OUTS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(OUTS) $(STY).sty
          $(TEX) $<

          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out

          .PHONY: clean
          clean:
          rm *.aux *.log > /dev/null 2>&1


          Note: I declared $(OUTS) as precious such that make does not delete them when it is done with the building of $(DOC).pdf.



          Update with the new specifications and separated python scripts for xx.out and xx.png production:



          DOC    := myPdf
          STY := st
          PY_DIR := a
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error
          PYTS := $(wildcard $(PY_DIR)/*t.py)
          PYIS := $(wildcard $(PY_DIR)/*i.py)
          OUTS := $(patsubst $(PY_DIR)/%t.py,$(PY_DIR)/%.out,$(PYTS))
          PNGS := $(patsubst $(PY_DIR)/%i.py,$(PY_DIR)/%.png,$(PYIS))

          .PRECIOUS: $(OUTS) $(PNGS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(STY).sty $(OUTS) $(PNGS)
          $(TEX) $<

          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(PY_DIR) && python3 $*t.py > $*.out

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(PY_DIR) && python3 $*i.py

          clean:
          rm -f *.aux *.log > /dev/null 2>&1


          Notes:




          • I slightly modified the definition of PY_DIR such that, when used in other parts of the Makefile, it is clear that it is a directory path. Just a matter of taste, I guess.

          • I added the -f option to your clean recipe such that it doesn't fail if the files to delete do not exist.


          Update:



          As noted by MadScientist in a comment, using $* is less generic than referring to the target ($@) and the prerequisite ($<). But as we are operating not directly on them but on their directory ($(PY_DIR)) and base file names (xx[it].py, xx.out, xx.png), switching from $* to other, more generic, automatic variables is not that simple.



          But make has some more tricks that can help here: $@, $<... have variants ($(@F), $(@D)...) that expand to just the directory part or the file part. Note that, according the GNU make manual:




          These variants are semi-obsolete in GNU make since the functions dir
          and notdir can be used to get a similar effect.




          Anyway, if we wanted to avoid $* here is what we could use instead:



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(@D) && python3 $(<F) > $(@F)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(@D) && python3 $(<F)


          Or (modern version):



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(dir $@) && python3 $(notdir $<) > $(notdir $@)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(dir $@) && python3 $(notdir $<)





          share|improve this answer















          Your recipes are wrong. Make expands the recipes before passing them to the shell. As there is no make variable named cd PY_DIR && python3 11.py > 11.out, $(cd PY_DIR && python3 11.py > 11.out) expands as the empty string and make considers that there is nothing to do for $(PY_DIR)11.out. Just write your recipes as plain shell (and fix the other bug with the unexpanded PY_DIR):



          $(PY_DIR)11.out:
          cd $(PY_DIR) && python3 11.py > 11.out

          $(PY_DIR)12.out:
          cd $(PY_DIR) && python3 12.py > 12.out


          Note: if you want make to re-run the recipes when your python scripts change you should let him know that the output files depend on the python scripts. The best is probably to use a pattern rule instead of one specific rule per file:



          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out


          ($* is a make automatic variable, it expands as the stem of the pattern).



          A few more improvements:




          • You could ask make to find alone the python scripts, compute the names of the output files and store all this in make variables that you can used in your other rules.

          • You can use a pattern rule for the xx.tex -> xx.pdf process. And use another make automatic variable for it: $< that expands as the first prerequisite.


          DOC    := myPdf
          STY := st
          PY_DIR := a/
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error

          PYS := $(wildcard $(PY_DIR)*.py)
          OUTS := $(patsubst %.py,%.out,$(PYS))

          .PRECIOUS: $(OUTS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(OUTS) $(STY).sty
          $(TEX) $<

          $(PY_DIR)%.out: $(PY_DIR)%.py
          cd $(PY_DIR) && python3 $*.py > $*.out

          .PHONY: clean
          clean:
          rm *.aux *.log > /dev/null 2>&1


          Note: I declared $(OUTS) as precious such that make does not delete them when it is done with the building of $(DOC).pdf.



          Update with the new specifications and separated python scripts for xx.out and xx.png production:



          DOC    := myPdf
          STY := st
          PY_DIR := a
          TEX := pdflatex -shell-escape -interaction=batchmode -file-line-error
          PYTS := $(wildcard $(PY_DIR)/*t.py)
          PYIS := $(wildcard $(PY_DIR)/*i.py)
          OUTS := $(patsubst $(PY_DIR)/%t.py,$(PY_DIR)/%.out,$(PYTS))
          PNGS := $(patsubst $(PY_DIR)/%i.py,$(PY_DIR)/%.png,$(PYIS))

          .PRECIOUS: $(OUTS) $(PNGS)
          .PHONY: all clean

          all: $(DOC).pdf

          %.pdf: %.tex $(STY).sty $(OUTS) $(PNGS)
          $(TEX) $<

          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(PY_DIR) && python3 $*t.py > $*.out

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(PY_DIR) && python3 $*i.py

          clean:
          rm -f *.aux *.log > /dev/null 2>&1


          Notes:




          • I slightly modified the definition of PY_DIR such that, when used in other parts of the Makefile, it is clear that it is a directory path. Just a matter of taste, I guess.

          • I added the -f option to your clean recipe such that it doesn't fail if the files to delete do not exist.


          Update:



          As noted by MadScientist in a comment, using $* is less generic than referring to the target ($@) and the prerequisite ($<). But as we are operating not directly on them but on their directory ($(PY_DIR)) and base file names (xx[it].py, xx.out, xx.png), switching from $* to other, more generic, automatic variables is not that simple.



          But make has some more tricks that can help here: $@, $<... have variants ($(@F), $(@D)...) that expand to just the directory part or the file part. Note that, according the GNU make manual:




          These variants are semi-obsolete in GNU make since the functions dir
          and notdir can be used to get a similar effect.




          Anyway, if we wanted to avoid $* here is what we could use instead:



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(@D) && python3 $(<F) > $(@F)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(@D) && python3 $(<F)


          Or (modern version):



          $(PY_DIR)/%.out: $(PY_DIR)/%t.py
          cd $(dir $@) && python3 $(notdir $<) > $(notdir $@)

          $(PY_DIR)/%.png: $(PY_DIR)/%i.py
          cd $(dir $@) && python3 $(notdir $<)






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 '18 at 7:24

























          answered Nov 18 '18 at 9:47









          Renaud PacaletRenaud Pacalet

          9,20821729




          9,20821729













          • You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

            – MadScientist
            Nov 18 '18 at 14:21











          • Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

            – Renaud Pacalet
            Nov 18 '18 at 14:37











          • Oh you're right I missed the cd. Sorry!

            – MadScientist
            Nov 18 '18 at 17:30











          • wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

            – onlycparra
            Nov 18 '18 at 18:56











          • I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

            – onlycparra
            Nov 18 '18 at 19:17



















          • You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

            – MadScientist
            Nov 18 '18 at 14:21











          • Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

            – Renaud Pacalet
            Nov 18 '18 at 14:37











          • Oh you're right I missed the cd. Sorry!

            – MadScientist
            Nov 18 '18 at 17:30











          • wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

            – onlycparra
            Nov 18 '18 at 18:56











          • I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

            – onlycparra
            Nov 18 '18 at 19:17

















          You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

          – MadScientist
          Nov 18 '18 at 14:21





          You should not use $*.out as the file to be generated. You must always use exactly $@ as the file to generate, otherwise your makefile will not work correctly (unless it so happens that $*.out and $@ are the same thing, which in this case they are not).

          – MadScientist
          Nov 18 '18 at 14:21













          Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

          – Renaud Pacalet
          Nov 18 '18 at 14:37





          Did you consider the cd $(PY_DIR) && ...? I don't think $@ would work here. But I would be glad to learn something new about make, of course. And no, we cannot really invoke python from the top directory: python is picky about where it is invoked from (modules path and so on). We need this cd $(PY_DIR) && ... stuff.

          – Renaud Pacalet
          Nov 18 '18 at 14:37













          Oh you're right I missed the cd. Sorry!

          – MadScientist
          Nov 18 '18 at 17:30





          Oh you're right I missed the cd. Sorry!

          – MadScientist
          Nov 18 '18 at 17:30













          wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

          – onlycparra
          Nov 18 '18 at 18:56





          wow, I need some time to digest this, I'll try it now and I will tell you how it goes, Thanks very much for your explanation.

          – onlycparra
          Nov 18 '18 at 18:56













          I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

          – onlycparra
          Nov 18 '18 at 19:17





          I don't understand the first improvement with the $(OUTS). Now make says nothing to be done for 'all'. even when I modify the .tex file

          – onlycparra
          Nov 18 '18 at 19:17


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53359188%2fmake-says-file-is-up-to-date-but-it-does-not-exist%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Academy of Television Arts & Sciences

          L'Équipe

          1995 France bombings