HeidiSalami
HeidiSalami

Reputation: 158

GNU make ifeq comparison not working

I am trying to have a command executed depending on the current target from a list of targets (currently only one entry in that list) before another makefile is executed.

i have this:

$(LIBS):            
ifeq ($@,libname)
        my command here
endif
        $(MAKE) -C ./lib/$@

the problem is, that the ifeq does not get executed even if the target name is correct. Using an $(info $@) shows exactly the libname but the expression is not evaluated as true. I thought maybe there is a problem with expansion of the automatic variable in a conditional so i tried using an eval like this:

$(LIBS):
        $(eval CURRENT_LIB := $@)
ifeq ($(CURRENT_LIB),libname)
        my command here
endif
        $(MAKE) -C ./lib/$@

info shows that the variable now equals exactly the libname but the ifeq does not get excuted. When i enter something like ifeq (libname,libname) it works so the statement is working, but the comparison between variable and text does not evaluate to true even if the two are equal and it should work. GNU make version is 4.1

What am i missing here?

Complete Makefile:

CC := g++
CFLAGS := -v -std=c++0x -pthread -Wall -g -O3

OBJ := mycode.o
OBJ += moreobjects.o
#more objects in here

LIBS = libname

.PHONY: libs $(LIBS)

SRC = $(OBJ:%.o=%.cpp)
DEPFILE := .depend

mytarget: libs $(OBJ)
        $(CC) $(CFLAGS) -o $@ $(OBJ)

-include $(DEPFILE)

%.o: %.cpp
        $(CC) $(CFLAGS) -c $<
        $(CC) -MM -std=c++11 $(SRC) > $(DEPFILE)

libs: $(LIBS)

$(LIBS):
        $(eval CURRENT_LIB := $@)
ifeq ($(CURRENT_LIB),libname)
        ./lib/$(CURRENT_LIB)/configure
endif
        $(MAKE) -C ./lib/$@

.PHONY: clean_all
clean_all: clean
        $(foreach dir,$(LIBS),$(MAKE) clean -C ./lib/$(dir))


.PHONY: clean
clean:
        rm -rf mytarget $(OBJ) $(DEPFILE)

Thank You very much!

Upvotes: 5

Views: 8419

Answers (2)

user10008009
user10008009

Reputation:

"Normal" conditionals, don't work in a recipe with GNU make. Unfortunately that's true.

Workaround:

But you can use Functions for Conditionals and The eval Function instead. A small example for error detection from my build system. Here I use the eval and if function.

Snippet from Makefile.xu, which use eval and if:

xubuild_check_objects:
    $(eval RESULT = $(call xu-obj_func-valid,$(xu-src-c-y)))
    @echo 'echo nothing (dummy)' >/dev/null
    $(if $(filter n,$(RESULT)), \
    $(error XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting),)

NOTE:

    @echo 'echo nothing (dummy)' >/dev/null

This here is required. When no command will be executed after eval, you get a make: Nothing to be done for 'xubuild_check_objects message.

Project Makefile (root directory) with error:

# XUbuild system (MUST included first)
include Makefile.xu

# This produces an error and aborts the build
xu-src-c-y = test.c

all: xubuild_check_objects

Error output:

$ make
Makefile.xu:104: *** XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting.  Stop.
$

Project Makefile (root directory) without error:

# XUbuild system (MUST included first)
include Makefile.xu

# My build system is happy with this:
xu-src-c-y += test.c

all: xubuild_check_objects

Output (no error):

$ make
$

The full error detection from my build system simplified. I removed the most Makefile.xu "code" and only post the error detection here. (I don't explain my whole build system in this answer):

# XUbuild generic object
xu-obj          := :xu-obj
xu-obj_del      := :

# XUbuild object types
xu-obj_nop      := n
xu-obj_yes      := y
xu-obj_module   := m
xu-obj_src      := s
xu-obj_flag     := f

# XUbuild source priority
xu-obj_src_head     := 0
xu-obj_src_normal   := 1

# XUbuild source types
xu-obj_src_a        := 0
xu-obj_src_c        := 1
xu-obj_src_cpp      := 2

# XUbuild object functions
xu-obj_func-get     = $(filter $(xu-obj)%,$(1))
xu-obj_func-remove  = $(filter-out $(xu-obj)%,$(1))
xu-obj_func-valid   = $(if $(call xu-obj_func-get,$(1)),y,n)

# XUbuild source objects
xu-src          := $(xu-obj)$(xu-obj_del)

# XUbuild C source
xu-src-c        := $(xu-src)$(xu-obj_src_normal)$(xu-obj_del)$(xu-obj_src_c)$(xu-obj_del)
xu-src-c-       := $(xu-src-c)$(xu-obj_nop)
xu-src-c-y      := $(xu-src-c)$(xu-obj_yes)

XUBUILD_PHONY   += xubuild_check_objects
xubuild_check_objects:
    $(eval RESULT = $(call xu-obj_func-valid,$(xu-src-c-y)))
    @echo 'echo nothing (dummy)' >/dev/null
    $(if $(filter n,$(RESULT)), \
    $(error XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting),)

.PHONY: $(XUBUILD_PHONY)

Upvotes: 2

Louis
Louis

Reputation: 151380

What you are trying to do cannot work. From the documentation:

Conditionals control what 'make' actually "sees" in the makefile, so they cannot be used to control recipes at the time of execution.

The way I put it is that conditionals are evaluated at the time the Makefile is read. So make reads your Makefile, your conditional is false and it is removed.

Upvotes: 10

Related Questions