# Multiple possible inputs to Shake rule

**URL:** <https://discourse.haskell.org/t/multiple-possible-inputs-to-shake-rule/11006>\
**Category:** Learn\
**Created:** [December 11, 2024, 11:00pm UTC](https://discourse.haskell.org/t/multiple-possible-inputs-to-shake-rule/11006 "2024-12-11T23:00:56Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Camdar](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/camdar/32/4477_2.png) [@Camdar](https://discourse.haskell.org/u/Camdar)\
**Post date:** [December 11, 2024, 11:00pm UTC](https://discourse.haskell.org/t/multiple-possible-inputs-to-shake-rule/11006/1 "2024-12-11T23:00:56Z")

</div>

I’ve been trying to convert a project to use [Shake](https://shakebuild.com/), 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.
