Hi folks,

I'm interested in making it easier to specify some of the build system
behaviours I want and I saw https://savannah.gnu.org/bugs/?42125 which is
one of the things I want to improve. I saw a way to improve it that
supports this feature and several others at once in a pretty regular and
predictable way.

I will be happy to do the bulk of the work to implement this, if some
guidance can be provided and help with the hard bits.

The feature requested is to support rules that generate several targets at
once. I saw that there is a related feature missing which is to succinctly
define several implicit pattern rules at once like you can for static rules
(for example, each one targeting a different build folder for different
build settings).

I think this could be supported using static pattern rules. Static pattern
rules are essentially a "foreach" loop of the form A: B: C ; D meaning "for
each word in A, generate one rule with one static target A and
prerequisites generated roughly with the substitution ref $(A:B=C) having
recipe D".

This part of make could be extended because the form is not allowed if:
- the resulting target or prerequisites contain %, or
- more than one word is in B
- B contains '='

So there is a space of inputs that is currently disallowed that could
support both multiple rule types:
1. a single target for each of multiple rules, and
2. a single rule having multiple targets
for both implicit and explicit rules.

The static pattern syntax could be extended to support all the things I
described earlier, changing
targets …: target-pattern: prereq-patterns … ; recipe
to
factors …: factors-pattern[=substitutions …]: prereq-patterns … ; recipe

This would now be a "foreach" loop of the same form but meaning "for each
word in A, generate one rule A with multiple simultaneous targets generated
with the substitution ref specified in B (ie, $(A:B)) and prerequisites
generated roughly with the substitution ref $(A:$(lhs B)=C) and having
recipe D". This would support implicit rules if the words that result from
the substitution contain "%" - ie, the words in A or $(rhs B) or C contain
double-percent "%%". I suggest %% is required in A even though it shouldn't
logically need it because the example rule below wasn't clear enough to the
eye otherwise.

Hopefully this can be implemented quite easily by using existing make
functionality,


A few more details of this idea.

This would default to the current behaviour when [=substitutions]: is
missing so there is no change to existing static pattern rules. ie, if an
equal sign '=' is not given then the behaviour is as if the equal sign is
given and the substitution is the factors-pattern is repeated to provide a
one-to-one mapping by default (eg "%.o" behaves as "%.o=%.o").

To support commandline tab completion (eg bash-completion), if an explicit
rule is generated with multiple targets then the make database lists each
target separately with a note that this target is a sibling of a multiple
target rule. The multiple target rule itself is listed as '# Not a target'
and '# Multiple targets' so that existing commandline tab completion is not
broken by what would look like a multiword target.

Please consider making each rule defined like this fail if any of the
targets for one loop of the "foreach" is not updated unless that target is
also a prerequisite of .PHONY. This will avoid incorrect builds due to
mistakes. ie, all non-phony targets must be updated when this rule's recipe
runs. I can imagine easy-to-make mistakes in the recipes for multiple
simultaneous outputs causing bad incremental builds without this check.

eg:
build/x86-64/main.o build/x86/main.o build/armel/main.o: %.o=%.o: %.c ;
true
# same as build/x86-64/main.o build/x86/main.o build/armel/main.o: %.o: %.c
; true
# same as
# build/x86-64/main.o: build/x86-64/main.c ; true
# build/x86/main.o: build/x86/main.c ; true
# build/armel/main.o: build/armel/main.c ; true

x86-64 x86 armel: %=build/%/main.o: main.c ; true
# same as
# build/x86-64/main.o: main.c ; true
# build/x86/main.o: main.c ; true
# build/armel/main.o: main.c ; true

%%.o: %.o=%.o %.log .%.deps %.symbols: %.c ; true
# same as
# %.o %.log .%.deps %.symbols: %.c ; true

x86-64 x86 armel: %=build/%/%%.o log/%/%%.log .deps/%/%%.d
symbols/%/%%.symbols: %%.c ; true
# same as
# build/x86-64/%.o log/x86-64/%.log .deps/x86-64/%.d
symbols/x86-64/%.symbols: %.c ; true
# build/x86/%.o log/x86/%.log .deps/x86/%.d symbols/x86-64/%.symbols: %.c ;
true
# build/armel/%.o log/armel/%.log .deps/armel/%.d symbols/x86-64/%.symbols:
%.c ; true

main.o err.o: %.o=%.o %.log .%.deps %.symbols: %.c ; true
# same as this where all targets of one rulesare generated in a single step
(as if there is a
# % sign in there but $* must be the empty string)
# main.o main.log .main.deps main.symbols: main.c ; # err.o err.log
.err.deps err.symbols: err.c ; true
Regards
Tristan Wibberley
_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-make

Reply via email to