GNU make file pairwise combinations of files in folder

17 views Asked by At

I have the following makefile to make pairwise combinations of all files in a directory and then execute a command for each pair. In the generation of pairwise combinations, say, in my folder, i have

  • f1.txt
  • f2.txt
  • f3.txt

I want to avoid the situation "f1.txt_f2.txt" and "f2.txt_f1.txt" to happen since they are the same combination.

However, when i run make, the output is make: Nothing to be done for 'all'., is there any place to change to make it work?

FOLDER := .
FILES := $(wildcard $(FOLDER)/*.txt)
PAIRS := $(foreach file1,$(FILES),$(foreach file2,$(filter-out $(file1),$(FILES)), $(if $(filter-out $(file2)_$(file1),$(PAIRS)),$(file1)_$(file2))))

.PHONY: all

all: $(PAIRS)

define execute_command
$(1)_$(2):
        ls "$(1)" "$(2)"
endef

# $(word 1,...) and $(word 2,...): These functions extract specific words from a space-separated list. In this case, it seems to be extracting the first and second words after splitting the pair on underscores.
# $(subst _, ,$(pair)): This function substitutes all underscores in the pair variable with spaces, effectively splitting the pair into two separate words.
$(foreach pair,$(PAIRS),$(eval $(call execute_command,$(word 1,$(subst _, ,$(pair))),$(word 2,$(subst _, ,$(pair))))))
1

There are 1 answers

0
MadScientist On

You should add $(info PAIRS = $(PAIRS)) and other similar debugging to your makefile so you can see what it's doing.

Similarly, you should add a line to see what the eval function is doing; duplicate the line using eval and replace the eval with info to see what make sees and evaluates:

$(foreach pair,$(PAIRS),$(info $(call execute_command,$(word 1,$(subst _, ,$(pair))),$(word 2,$(subst _, ,$(pair))))))

For example, this cannot work:

PAIRS := $(foreach file1,$(FILES),$(foreach file2,$(filter-out $(file1),$(FILES)), $(if $(filter-out $(file2)_$(file1),$(PAIRS)),$(file1)_$(file2))))

It's useless to try to reference the value $(PAIRS) inside the variable assignment for PAIRS; the value of the variable is not set until the right-hand side is completely expanded. So it will always expand to the empty string, until after this entire statement is evaluated.