GNU make: Execute target but take dependency from

2019-08-19 13:05发布

I want the rules of a target to be executed but all dependent targets shall regard this target as satisfied.

How can I achieve this?

Example:

$(NETWORK_SHARE)/foo.log:
    @echo Warning: server offline, still continue ...
    @exit 0

foo.csv: $(NETWORK_SHARE)/foo.log
    @echo Long export from a (different) server
    @echo sleep 20
    @echo foo > $@

If $(NETWORK_SHARE)/foo.log exists: foo.csv shall be rebuilt if $(NETWORK_SHARE)/foo.log is newer than foo.csv; otherwise nothing should happen (default)

If $(NETWORK_SHARE)/foo.log does not exist (e.g., server offline, failure, ...) only a message indicating a problem should be printed but foo.csv shall only be built if foo.csv does not exist.

I played around with .PHONY and returning different return values but for case 2, the expensive "export" happens as soon as I execute something on $(NETWORK_SHARE)/foo.log ...

Regards divB

2条回答
时光不老,我们不散
2楼-- · 2019-08-19 13:24

Great, thanks to Thiton's answer in my related question (Force make to find out-of-date condition from file) I can now provide a hack to solve this:

.PHONY: always-remake

NETWORK_SHARE = //server/dfs/common/logs

.PHONY: all
all: foo.csv

# file does not exist ...
ifeq "$(wildcard $(NETWORK_SHARE)/foo.log)" ""

old_file: always-remake
    @echo Warning: network is not available ....

foo.csv: old_file
    @echo Expensive export
    @sleep 10
    @echo $@ > $@
else
foo.csv: $(NETWORK_SHARE)/foo.log
    @echo Doing expensive export since log file changed ...
    @sleep 10
    @echo $@ > $@
endif

"old_file" is a dummy file which must exist and should never be newer than any other file (e.g. 1/1/1971, 00:00)

Regards divB

查看更多
贼婆χ
3楼-- · 2019-08-19 13:29

Looks like instead of using some old file (that someone can accidentally touch), you can use an order-only prerequisite. Here's a quote from the GNU makefile manual (chapter 4.3)

Occasionally, however, you have a situation where you want to impose a specific ordering on the rules to be invoked without forcing the target to be updated if one of those rules is executed. In that case, you want to define order-only prerequisites. Order-only prerequisites can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only:

 targets : normal-prerequisites | order-only-prerequisites
查看更多
登录 后发表回答