In a makefile, I want to have a macro that inserts some symbols/source code from one variable into another one if those symbols/source code do not exist in the destination variable:
the way I want to call it is something like this:
$( call insert_non_existing_symbols, source1.o $(OBJS_SYMBOLS_1) $(OBJS_SYMBOLS_2) another_source.o, $(DESINATION_VARIABLE), $(DESINATION_VARIABLE) )
I'm currently defining my macro as follows:
################################################################################
# Macro to insert symbols in one variable not existing in another variable.
# From the symbols in $(1), check that the symbol is not available in $(2), and
#inserts in $(3) the symbols not available
insert_non_existing_symbols = \
for i in $(1); do \
exist = 0; \
$(call member,$i,$(2),$(ret_val)) \
ifeq $ret_val,0 \
$(3) += $i; \
endif \
done
################################################################################
# Macro to determine if a symbol $(1) exisit in another variable/symbol $(2)
# returns $(3) = 1 if it does.
member = \
$(3) = 0; \
for i in $(2); do \
ifeq $(1),$i \
$(3)=1; \
endif \
done
I have the following symbol/variable OBJS_COLL := obj1.o obj2.o
, and DESINATION_VARIABLE := obj3.o obj4.o
so that after calling $( call insert_non_existing_symbols, $( OBJS_COLL), $(DESINATION_VARIABLE), $(DESINATION_VARIABLE) )
DESINATION_VARIABLE
will be DESINATION_VARIABLE := obj1.o obj2.o obj3.o obj4.o
since the $(call insert_non_existing_symbols,..)
will add to DESINATION_VARIABLE
the symbols/source code not exiting previously on it and that exist on OBJS_COLL . You can see that at the beginning DESINATION_VARIABLE
was DESINATION_VARIABLE := obj3.o obj4.o
--- Edit
Sorry for the confusion here is a new edit to my question. This is part of what I want to achieve. I think this complete example is much better explanation:
VARIABLE_2 := source1.cpp source2.cpp
DEST_VAR_1 := source3.cpp
DEST_VAR_2 := source4.cpp
SOURCE_VAR := source
SOURCE_VAR_2 := no_source
ifeq ("$(filter source,$(SOURCE_VAR))","source")
DEST_VAR_1 := $(call insert_non_existing_symbols, $(VARIABLE_2),$(DEST_VAR_1))
endif
ifeq ("$(filter source,$(SOURCE_VAR_2))","source")
DEST_VAR_2 := $(call insert_non_existing_symbols, $(VARIABLE_2),$(DEST_VAR_2))
endif
my_exe_source : $(DEST_VAR_1)
$(CXX) -o $@ $(filter %.o,$^)
my_exe_no_source : $(DEST_VAR_2)
$(CXX) -o $@ $(filter %.o,$^)
$(call insert_non_existing_symbols
is defined as @Renaud Pacalet shows in his answer below.
Edit 2
The following lines illustrate two makefile I'm using for my case:
Makefile
.PHONY : all
all: my_exe_source my_exe_no_source
include terminal.mk
MAKEFILES += terminal.mk
VARIABLE_2 := source1.cpp source2.cpp
DEST_VAR_1b := $(DEST_VAR_1)
DEST_VAR_2b := $(DEST_VAR_2)
SOURCE_VAR := source.cpp
SOURCE_VAR_2 := no_source.cpp
insert_non_existing_symbols = \
$1 $(filter-out $1,$2)
ret_val := $(filter source.cpp,$(SOURCE_VAR))
ifeq ($(ret_val),source.cpp)
DEST_VAR_1 := $(call insert_non_existing_symbols, $(VARIABLE_2),$(DEST_VAR_1))
endif
ret_val := $(filter source.cpp,$(SOURCE_VAR_2))
ifeq ($(ret_val),source.cpp)
DEST_VAR_2 := $(call insert_non_existing_symbols, $(VARIABLE_2),$(DEST_VAR_2))
endif
my_exe_source : $(DEST_VAR_1b)
@echo $@ $(filter %.cpp,$^)
@echo $(DEST_VAR_1b)
my_exe_no_source : $(DEST_VAR_2b)
@echo $@ $(filter %.cpp,$^)
@echo $(DEST_VAR_2b)
terminal.mk
DEST_VAR_1 := source3.cpp
DEST_VAR_2 := source4.cpp
while running make I got:
$ make
my_exe_source source3.cpp
source3.cpp
my_exe_no_source source4.cpp
source4.cpp
This is due to the fact that I have
DEST_VAR_1b := $(DEST_VAR_1)
DEST_VAR_2b := $(DEST_VAR_2)
and that I'm using :=
which means immediate translation of $(DEST_VAR_1)
and $(DEST_VAR_2)
and it is not anymore translated.
But if I use =
:
DEST_VAR_1b = $(DEST_VAR_1)
DEST_VAR_2b = $(DEST_VAR_2)
it gets recursive translation so it will get reinterpreted to the latest value when I use it. Which gives me:
$ make
my_exe_source source1.cpp source2.cpp source3.cpp
source1.cpp source2.cpp source3.cpp
my_exe_no_source source4.cpp
source4.cpp
Explanation is here Difference between :=, and = in makefile
Any ideas or thoughts on how to do this is welcome and appreciated.
Thanks
You are mixing shell (for i in ...; do ... done
) and make (call
, ifeq
) constructs. This cannot work. Make and shell are 2 different languages. Make variables and shell variables, for instance, are completely different things, while you try to use some variables interchangeably as shell ($ret_val
) or make ($(ret_val)
) variables.
Note: in a Makefile the recipes of rules are frequently a mixture of shell and make syntax but it is a special case. Make first expands the recipes, the result shall be correct shell syntax, and then it passes this to the shell. In other parts of a Makefile mixing the 2 languages is simply not working.
But you don't need a complex macro for this. GNU make functions are powerful enough:
DESINATION_VARIABLE := $(OBJS_COLL) $(filter-out $(OBJS_COLL),$(DESINATION_VARIABLE))
$(filter-out pattern…,text)
Returns all whitespace-separated words in text that do not match any of the pattern words, removing the words that do match one or more
This simply concatenates the value of OBJS_COLL
(make variable) and all words in the value of DESINATION_VARIABLE
(make variable) that are not already in the value of OBJS_COLL
. The result is assigned to make variable DESINATION_VARIABLE
. If there are duplicates in OBJS_COLL
or DESINATION_VARIABLE
they are kept. The order is preserved.
If there are no duplicates in OBJS_COLL
and DESINATION_VARIABLE
, or if removing them is OK, and if you do not care about the final order, you can also use the sort
make function:
$(sort list)
Sorts the words of list in lexical order, removing duplicate words. The output is a list of words separated by single spaces. So:
DESINATION_VARIABLE := $(sort $(OBJS_COLL) $(DESINATION_VARIABLE))
Finally, if you really want to define a macro:
insert_non_existing_symbols = $1 $(filter-out $1,$2)
Or:
insert_non_existing_symbols = $(sort $1 $2)
And then:
DESINATION_VARIABLE := $(call insert_non_existing_symbols,$(OBJS_COLL),$(DESINATION_VARIABLE))