Evaluation of files in GNU make conditional

时间:2016-10-20 12:50:09

标签: gnu-make

all: start doSomeMagicToChangeRegFile end

start: $(OBJDIR)
    @$(TOUCH) build/$(CONFIG)/$(CONFIG).reg || exit
    @$(MD5SUM) build/$(CONFIG)/$(CONFIG).reg > build/$(CONFIG)/MD5SUM_REG_BEGIN
    ...........

end: $(APPL_OBJ)
    ...........
    @$(MD5SUM) build/$(CONFIG)/$(CONFIG).reg > build/$(CONFIG)/MD5SUM_REG_END
    @$(HEAD) build/$(CONFIG)/MD5SUM_REG_BEGIN
    @$(HEAD) build/$(CONFIG)/MD5SUM_REG_END
ifneq ($(HEAD) build/$(CONFIG)/MD5SUM_REG_BEGIN,$(HEAD) build/$(CONFIG)/MD5SUM_REG_END)
    @$(ECHO) "REBUILD"
    @$(RM) -fr build/$(CONFIG)/$(CONFIG)/*.o*
    @$(MAKE) -i $(CONFIG)
else
    @$(ECHO) "DONE"
endif

This gnu make file builds some code with the Keil compiler and creates a reg file within this context. The code should be recompiled until the reg file doesn't change any more. There is a md5 hash calculation at the start and at the end. Both hashs are compared at the end. But this check results in an infinite loop. The evaluation of the ifneq conditional doesn't seem to work. The result of @$(HEAD) build/$(CONFIG)/MD5SUM_REG_BEGIN and @$(HEAD) build/$(CONFIG)/MD5SUM_REG_END are correct, but apparently not in the conditional. Why?

1 个答案:

答案 0 :(得分:0)

You're confused about a few things. First ifeq/ifneq are string comparison functions: they compare the strings $(HEAD) build/$(CONFIG)/MD5SUM_REG_BEGIN and $(HEAD) build/$(CONFIG)/MD5SUM_REG_END, which by definition will never be equal so the ifneq is always true. ifeq/ifneq do not compare the contents of files.

Second, the make processor statements like include, ifeq, etc. are all parsed as the makefile is read in, long before make starts to actually run any rules. So at the time the ifneq is parsed none of the recipe has been invoked.

If you want a conditional that runs as part of the recipe, then you have to actually make it part of the recipe and use shell conditionals, not make conditionals.

ETA Something like this:

RMAKE = $(MAKE)

end: $(APPL_OBJ)
        ...........
        @$(MD5SUM) build/$(CONFIG)/$(CONFIG).reg > build/$(CONFIG)/MD5SUM_REG_END
        @$(HEAD) build/$(CONFIG)/MD5SUM_REG_BEGIN
        @$(HEAD) build/$(CONFIG)/MD5SUM_REG_END
        @if [ `$(HEAD) build/$(CONFIG)/MD5SUM_REG_BEGIN` != `$(HEAD) build/$(CONFIG)/MD5SUM_REG_END` ]; then \
            $(ECHO) "REBUILD"; \
            $(RM) -fr build/$(CONFIG)/$(CONFIG)/*.o*; \
            $(RMAKE) -i $(CONFIG); \
        else \
            $(ECHO) "DONE"; \
        fi

The RMAKE trick is needed if you ever want to run make -n and have it do the right thing.

@triplee is right, though, using @ before all these lines is a bad idea. It makes debugging your makefiles super-annoying. At the very least you should not add them until after your makefile is fully developed and working.