Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If condition inside a target in a Makefile

Tags:

makefile

I want to do something like this, where I want to run a svn commit if a file has changed. The file has a timestamp which always changes. So if anything more than timestamp changes , then I want to commit the file.

The makefile will have something similar to this. But the If condition is not working properly. It is getting executed even when if is not satisfied. Can someone help me out what is the problem in If here.

    UPDATE_STATE_FILE :
        $(eval NO_LINES_CHANGES_IN_STATE = $(shell svn di STATE/build.state --diff-cmd=diff -x --normal | grep "^[<>]" | wc -l))
        @echo $(NO_LINES_CHANGES_IN_STATE)
    ifneq ($(strip $(NO_LINES_CHANGES_IN_STATE)), 2)
    ifneq ($(strip $(NO_LINES_CHANGES_IN_STATE)), 0)
        @echo $(NO_LINES_CHANGES_IN_STATE)
        $(SVN) commit;
        $(SVN) update;
    endif
    endif
like image 424
naveen Avatar asked May 21 '13 09:05

naveen


People also ask

How do I add a condition in makefile?

Syntax of Conditionals Directives The text-if-true may be any lines of text, to be considered as part of the makefile if the condition is true. If the condition is false, no text is used instead. If the condition is true, text-if-true is used; otherwise, text-if-false is used.

What is := in makefile?

Expanded assignment = defines a recursively-expanded variable. := defines a simply-expanded variable.

What does target mean in makefile?

A simple makefile consists of “rules” with the following shape: target … : prerequisites … recipe … … A target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out, such as ' clean ' (see Phony Targets).


2 Answers

You cannot mix make conditionals inside command rules. Make conditionals are like preprocessor statements in C or C++; they are handled as the file is read in, before any processing (like running rules) is performed.

If you want conditionals inside the rules you have to write the rule using shell conditionals, not make conditionals:

UPDATE_STATE_FILE :
        @NO_LINES_CHANGES_IN_STATE=`svn di STATE/build.state --diff-cmd=diff -x --normal | grep "^[<>]" | wc -l`; \
        echo $$NO_LINES_CHANGES_IN_STATE; \
        if [ $$NO_LINES_CHANGES_IN_STATE -ne 2 ] && [ $$NO_LINES_CHANGES_IN_STATE -ne 0 ]; then \
            echo $$NO_LINES_CHANGES_IN_STATE; \
            $(SVN) commit; \
            $(SVN) update; \
        fi
like image 63
MadScientist Avatar answered Sep 24 '22 02:09

MadScientist


After reading the answer given by @MadScientist, I came up with a different approach.

Not knowing if shell conditionals will work in any environment (windows vs. linux), I wrapped the rules inside the conditional instead of having a conditional inside the rule. i.e.

ifdef MY_FLAG
%.o: %.c
    $(CC) -o $@ -c $^ $(CFLAGS)

else
%.o: %.c
    @$(CC) -o $@ -c $^ $(CFLAGS)

endif

Good luck to anyone visiting here.

EDIT

As pointed out by James Moore in the comments, this different approach requires care and notice as to when and how variables are defined in relation to the placement of the if statement in the control flow.

like image 32
Myst Avatar answered Sep 23 '22 02:09

Myst