Reputation: 158
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
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
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