1

I want to have file, when I can list of names (one in the line), so that when make is invoked, rules are generated on the fly from this names with some string appended to it.

Example:

file contents:

target1
target2
target3

String to concatenate: my_task_

From this I want to have 3 rules:

my_task_target1:
    <some things to do>

my_task_target2:
    <some things to do>

my_task_target3:
    <some things to do>

I know, that when I have array with all this targets names, I can do this like in this answer, but I need to read data from file.

I want it to be this way, because I will have many targets, and there is different list of tasks for every target. Each task will have it's own file with list of targets. At the end I will also create rules with names after target, but without prefix, and this rules will have all tasks, that are assigned to some target, so that I can invoke separated tasks, and also all needed tasks for target with one make command.

How can I achieve this? Or maybe there is a better way to do what I want to do?

Staszek
  • 849
  • 11
  • 28
  • You should create an array from file https://stackoverflow.com/questions/30988586/creating-an-array-from-a-text-file-in-bash – Iurii Drozdov Dec 06 '17 at 13:55
  • The scope of your problem isn't clear (IMHO) and the workflow you're describing would need more sample data for us to help. Agree that `arrays` are the place to start. Good luck. – shellter Dec 06 '17 at 13:58
  • 1
    If you want to do more (and more complex) configuration tasks in your makefile, you may want to take a look at [the GNUmake table toolkit](https://github.com/markpiffer/gmtt) which lets you configure with a database approach in mind. – Vroomfondel Dec 07 '17 at 10:17

1 Answers1

5

The following Makefile dynamically creates the targets read from the file list:

# the file with the targets
targets-file := list

# the string to concatenate
prefix := my_tasks_

# read the targets from the file indicated by the variable targets-file 
targets != cat "$(targets-file)"

# concatenate the string to each target
targets := $(addprefix $(prefix),$(targets))

.PHONY: all
all: $(targets)

# function for creating a target
define create_target
$(eval $1:; @echo "some things to do for $$@")
endef

# create the targets
$(foreach target,$(targets),$(call create_target,$(target)))

Considering that the contents of the file list is:

target1
target2
target3

By running make with the Makefile above:

$ make
some things to do for my_tasks_target1
some things to do for my_tasks_target2
some things to do for my_tasks_target3
JFMR
  • 23,265
  • 4
  • 52
  • 76
  • 1
    Nice answer. Note that you do not need `tr` to substitute `\n` with spaces. `targets != cat "$(targets-file)"` does exactly that: suppress the last `\n` if any and substitutes the others with a space. – Renaud Pacalet Dec 06 '17 at 14:31
  • 1
    Good to know that I can read files like that. The other solution would be to just read the file, and do that is done in answer, that I linked. But good to know that I can do it this way. Thanks! – Staszek Dec 06 '17 at 14:36
  • 1
    @Staszek It is the same. `targets != cat "$(targets-file)"` and `targets := $(shell cat "$(targets-file)")` do exactly the same. Use one or the other, it makes no difference. – Renaud Pacalet Dec 06 '17 at 14:38
  • @RenaudPacalet Thanks! I didn't know the *shell assignment operator*. – JFMR Dec 06 '17 at 14:43