0
votes

I want to have a Makefile that is able to install files one by one, and also uninstall them one by one.

The install rule for a file should run only if the source file is newer than the dest file.

The uninstall rule for a file should run only if the file exists in the system.

Now I have:

SRC_FILES = ...
sys_files = ...

$(sys_files): $(DESTDIR)$(systemdir)/%: $(SRCDIR)/%
    @echo ' INSTALL $@';
    $(INSTALL_DATA) -T '$(SRCDIR)/$*' '$@';

uninstall_sys_files = $(addprefix uninstall-,$(sys_files))

$(unsinstall_sys_files): uninstall-%:
    @echo ' RM  $*';
    $(RM) '$*';

The problem with the code above is that it runs the uninstall (RM) targets even if the files don't exist, (I can live with it, but I would prefer to not print RM messages for files that are not removed. And yes, I can do that with a conditional, but I'd do that only if make can't handle this with a ?"static terminal pattern rule"?).

So, is there anything like?:

$(unsinstall_sys_files):: uninstall-%: %
    @echo ' RM  $*';
    $(RM) '$*';

which would make this rule terminal and depending on the existance of %.

Per my tests, this behaves as if the double colon was a single colon.


EDIT:

Although this would seem nice, it isn't, because then if a rule fails (because the file didn't exist), then the whole make fails, or you need to ignore errors in the uninstall part, which I'm not entirely happy with.

1

1 Answers

2
votes

I'm not really sure advantage you hope to gain by marking a rule terminal... unless I'm missing something it doesn't seem to have much to do with what you want to do.

Your final problem ("a rule fails because the file didn't exist"), by which I understand you to mean the uninstall recipe fails, is simple enough to fix: just set RM = rm -f so that rm won't fail if the file doesn't exist.

It would be great if you could give an example of what you really want to do; how you expect to invoke make and how you want it to behave (resulting operations).

Make is designed to update files, not delete files. That is, its whole goal is to find files that don't exist or are out of date, and make them exist / update them.

However, you could do something like this:

RM := rm -f

sys_exists := $(wildcard $(addprefix $(DESTDIR)$(systemdir)/,$(sys_files)))

uninstall: $(patsubst $(DESTDIR)$(systemdir)/%,uninstall-%,$(sys_exists)))

uninstall-%:
        @echo ' RM  $*'
        $(RM) '$(DESTDIR)$(systemdir)/$*'

This way uninstall would only remove files that actually existed.