'Makefile 'ifeq'/'findstring' Seemingly Incorrect String Comparison Behavior

I have several makefile variables defined similar to this ...

BUILD_DIR = build

APP_SRCS =    \
  ./main.c    \
  ./module1.c \
  ./module2.c \
  etc.        \

APP_OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(APP_SRCS:.c=.o)))

... and a rule defined similar to this ...

$(BUILD_DIR)/%.o: %.c
    echo "---"$@"---" "---"$(findstring $@, $(APP_OBJS))"---"
    ifeq ($(findstring $@, $(APP_OBJS)), $@)
        echo "---App---"
    else
        echo "---Lib---"
    endif

When this rule is executed, the if block is always executed. For example, consider the following terminal output:

---build/main.o--- ---build/main.o---
---App---

---build/lib1.o--- ------
---App---

In both cases, findstring works correctly. The problem I'm having is that whether the substring is found in the string or not, that is, $@ is found in $(APP_OBJS) or not, the if block is always taken. I want to use such a construct to compile application and library source files with different warning flags to mute all library warnings.



Solution 1:[1]

This statement:

ifeq ($(findstring $@, $(APP_OBJS)), $@)

is a Make conditional, and Make will evaluate before executing any rule, and therefore before the automatic variable $@ has a value. So Make expands "$@" to nothing:

ifeq ($(findstring , $(APP_OBJS)),)

the findstring returns the empty list since it didn't find a match:

ifeq (,)

and the conditional evaluates as true.

You already have one solution: use a shell conditional. Or you could use a static pattern rule:

$(APP_OBJS): $(BUILD_DIR)/%.o: %.c
    echo "---"$@"---" "---"$@"---"
    echo "---App---"

$(BUILD_DIR)/%.o: %.c
    echo "---"$@"---" "---""---"
    echo "---Lib---"

Solution 2:[2]

The following works as expected:

$(BUILD_DIR)/%.o: %.c
    if test $(findstring $@, $(APP_OBJS)); then \
        echo "---App---"; \
    else \
        echo "---Lib---"; \
    fi;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Beta
Solution 2