[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Suggested feature design for https://savannah.gnu.org/bugs/?42125

From: Tristan Wibberley
Subject: Re: Suggested feature design for https://savannah.gnu.org/bugs/?42125
Date: Thu, 21 Apr 2016 08:29:24 +0100

I think it makes sense to enhance substitution references somehow so users can define the cross-product of the variable and and the substitution.

maybe I could add


then users can define rules while that's set via:

factors :: path=subst : prerequisites ; recipe
factors :cross: path=subst : prerequisites ; recipe

They thus have a declarative way to produce rules via a standard form, and we could in future extend it by allowing users to register new functions as substitution methods without then having to resort to imperative rule generation because that becomes unclear and difficult to debug quite quickly.

On 20 April 2016 at 09:14, Tristan Wibberley <address@hidden> wrote:
Aaaand, there's the thinko ...

I just realised that substitution normally only applies to the first % in the replacement, rather than replacing all % characters as when applying an implicit rule's prerequisites - in which case the use of '=' is confusing by differing from it's other use.

How about some other token not used for this purpose elsewhere? Although I can't find one.

On 20 April 2016 at 07:48, Tristan Wibberley <address@hidden> wrote:
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
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.

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

Tristan Wibberley

reply via email to

[Prev in Thread] Current Thread [Next in Thread]