Why .SECONDARY does not work with patterns (%) whi

2019-01-09 15:34发布

问题:

My question is to understand better what i missed in make process and .SECONDARY purpose vs .PRECIOUS, not to get my script working, since it does work already.

I am using make to either open a emacs editor on a file ( java but irrelevant for purpose of this question ) or to create it with a template if not existing.

If it works well with existing files, when using generated file it is removed at the end.

I added prerequisite in .SECONDARY but didn't help, i had to add it in .PRECIOUS.

This is question why wasn't it working in .SECONDARY ? .

From what i found on SO .SECONDARY does not work with patterns ( % ), but even with knowing that i wonder if it is by design or if it is a bug in make. ( .SECONDARY for a pattern rule with GNU Make and Makefile pattern rule either ignores phony rule or spontaneously deletes output file )

Here a stripped down content of my Makefile to reproduce my problem ( please create a com/stackoverflow/question directory to test it ).

PACKAGE=com.stackoverflow.question
PACKAGE_DIR=$(subst .,/,$(PACKAGE))
OUT=out

clean:
    find $(OUT) -name "*.class" -type f -print0|xargs -0 rm

# does not work : deleted at end due to intermediate file removal.
$(PACKAGE_DIR)/%.java:
    @echo "package com.stackoverflow.question;\npublic class $(subst .java,,$(subst $(PACKAGE_DIR)/,,$@))\n{\n /** TODO */ \n}" >$@ 

work/%: $(PACKAGE_DIR)/$(subst work/,,%).java
    emacs $<

.PHONY: clean work/%

# tried to avoid intermediate file removal : does not work
.SECONDARY: $(PACKAGE_DIR)/%.java 

# if not commented this does work : once precious intermediate file is not removed.
#.PRECIOUS: $(PACKAGE_DIR)/%.java 

try

make work/SoTest

I understand this is flagged intermediate.

then looking in SO i tried to set it in .SECONDARY: target list : does not work either.

looking at make source code i spotted that make intermediate files removal is done within this context :

if (f->intermediate && (f->dontcare || !f->precious)
    && !f->secondary && !f->cmd_target)

so i set my file in .PRECIOUS: and now it works.

it displays to console :

com/stackoverflow/question/SoTest.java

it run emacs with right template in it so creation is OK here i exit emacs

and it removes the file at the end

rm com/stackoverflow/question/SoTest.java

Removal at end is due to intermediate file, this can be seen with -d option on make

LANG=C make -d work/SoTest

...
Must remake target 'work/SoTest'.
emacs com/stackoverflow/question/SoTest.java
Putting child 0xc3b580 (work/SoTest) PID 20681 on the chain.
Live child 0xc3b580 (work/SoTest) PID 20681 
Reaping winning child 0xc3b580 PID 20681 
Removing child 0xc3b580 PID 20681 from chain.
Successfully remade target file 'work/SoTest'.
Removing intermediate files...
rm com/stackoverflow/question/SoTest.java

To have it working i need to uncomment the .PRECIOUS paragraph.

make --version

GNU Make 4.0
Construit pour x86_64-pc-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
Licence GPLv3+ : GNU GPL version 3 ou ultérieure <http://gnu.org/licenses/gpl.html>
Ceci est un logiciel libre : vous êtes autorisé à le modifier et à la redistribuer.
Il ne comporte AUCUNE GARANTIE, dans la mesure de ce que permet la loi.

回答1:

The answer to "Why .SECONDARY does not work with patterns (%) while .PRECIOUS does?" is here: the document says

You can also list the target pattern of an implicit rule (such as ‘%.o’) as a prerequisite file of the special target .PRECIOUS

but does not say this about .SECONDARY. But for the few explicit exceptions, none of the special targets accept patterns.



回答2:

Thanks to Alex (see answer) i went further in my search.

What i found is that it is recorded in TODO.private of make project for 15 years ....

Using git://git.savannah.gnu.org/make.git you can see history of TODO.private content :

 6) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY
    pseudo-targets have different capabilities.  For example, .PRECIOUS
    can take a "%", the others can't.  Etc.  These should all work the
    same, insofar as that makes sense.

These should all work the same, insofar as that makes sense. but was not coded.