Multiple possible inputs to Shake rule

I’ve been trying to convert a project to use Shake, but have been stalled on the following issue.

The project configuration is made up of a (user-defined) list of modules, let’s say foo.m. The file foo.m is built from a .o file generated by one of two different compilers (let’s say gcc or gas).

In make, this is easy – simply have a rule relating %.m to %.o, then have multiple rules for generating %.o files. However, I am completely at a loss for how to express this with Shake.

The documentation states that, in situations where multiple compilers produce the same extension, we should adjust the filename accordingly (so, creating foo.asm.o or foo.c.o). However, I’m not sure how to write a rule choosing either foo.asm.o or foo.c.o to transform into foo.m.

As far as I can tell, need requires a concrete filepath, meaning I need to know which of foo.asm.o or foo.c.o to choose. I can’t use doesFileExist, because foo.c.o is a build artifact (and I can’t push the check to look for foo.c either, because there are some places where foo.c is generated). The actual action is the same either way, only the dependency differs. I also cannot change the extension of foo.m to foo.c.m (etc), because the configuration only uses foo.

The only way I can think to get around this is to scan the project folder ahead of time to make a bunch of explicit rules (relating foo.m to foo.c.o specifically instead of a generic rule from *.m to *.c.o if foo.c exists), but going through that kind of manual effort seems like it defeats the purpose of the build system.

For situations where both foo.c.o or foo.asm.o exist, I’d prefer to error out at (Shake-)runtime, but I’m happy to choose one or the other by default if needed.

1 Like