curryrs
curryrs copied to clipboard
Let Haskell tell rustc which libs it needs.
(Note: I don't expect this to be merged in its current state. There are a few problems which I am looking for suggestions on.)
Description
A custom Setup.hs is used on the Haskell side which figures out what libs are needed and outputs that as "cargo:" keys. A custom build.rs is used on the Rust side to pass those keys onto Cargo.
Use case
Suppose you have a Rust project and you would like to use some Haskell functions in it. You have the Haskell part of your project managed by Cabal and you want an easy way to link to it from Cargo. Here's what to do:
To the Cabal part:
- Change the build-type to "Custom"
- Add "curryrs" to your setup-depends
- Change your "Setup.hs" to this:
import Curryrs.Build
main = curryrsMain
To the Cargo part:
- Add "curryrs" to your build-dependencies
- In your build script, add a call to
curryrs::build::link_package
Then just run "cargo build". It will build the Haskell package and link the required libs for you.
Currently, the shared lib versions are linked for all except for the package itself.
Problems
- No Stack support
- No support for choosing an rts
- Haskell's "curryrs" now depends on "Cabal" (Would it be better to put
Curryrs.Build
in a separate package?) - "htest" now depends on "curryrs"
Hey thanks for taking the time to work on this! If I'm understanding this correctly what this is doing is automatically building the Haskell packages via cargo build
rather than using a Makefile right? If so that's pretty cool!
So with your problems, I do want to maintain stack
support since it's a good build tool and some people might only use that rather than cabal
or vice versa. I'm not sure if there's a way to support custom Setup.hs
files in stack
so I'd look into that if possible.
If you look at the Rust code you might see the feature flags let you choose the runtime and that's what gets linked by curryrs so that when you tell the Haskell runtime to start it's using that. Did that functionality get removed somehow because that's how you should be able to choose the rts for programs when they run.
I'm not sure about a separate package. I kind of want to think this one over before making a decision.
htest already indirectly depended on curryrs to run so I think this is fine but I'll have to look it over just to be sure.
Hey thanks for taking the time to work on this! If I'm understanding this correctly what this is doing is automatically building the Haskell packages via cargo build rather than using a Makefile right? If so that's pretty cool!
Yes, that is correct. However, I forgot to mention that this requires the Haskell "curryrs" to already be installed.
So with your problems, I do want to maintain stack support since it's a good build tool and some people might only use that rather than cabal or vice versa. I'm not sure if there's a way to support custom Setup.hs files in stack so I'd look into that if possible.
I've never used Stack before but it seems that Stack supports .cabal files. Is a Stack project required to have a valid .cabal file or is it just there for comparability with Cabal?
If you look at the Rust code you might see the feature flags let you choose the runtime and that's what gets linked by curryrs so that when you tell the Haskell runtime to start it's using that. Did that functionality get removed somehow because that's how you should be able to choose the rts for programs when they run.
I use Cabal's InstalledPackageIndex
to find out how to link to everything. Unfortunately, Cabal doesn't know about the different flavors of rts. I'm going to try hardcoding the different flavors of rts since they seem to be the same across platforms.
Yes, that is correct. However, I forgot to mention that this requires the Haskell "curryrs" to already be installed. Ohhh I was wondering what that meant. You're saying it has to be installed locally for it to work? Is there some way to just get this into the package alone so as to not have people to install extra stuff as part of the setup process?
Stack uses cabal files under the hood to figure things out and how to compile everything. stack.yaml
is used to specify other things needed that aren't in the LTS. If you haven't I'd recommend taking a look at it, but it's not required. This package just is meant to work for both. Stack uses cabal to do it's compilation it seems. It looks like in this article they mention that Setup.hs
is used.
I use Cabal's InstalledPackageIndex to find out how to link to everything. Unfortunately, Cabal doesn't know about the different flavors of rts. I'm going to try hardcoding the different flavors of rts since they seem to be the same across platforms.
That should be fine. Not a big fan of hardcoding if avoidable but It's not always possible. I don't think the RTS will change much anytime soon and it's only like 4 versions so adding to them later if needed is fine.
Ohhh I was wondering what that meant. You're saying it has to be installed locally for it to work? Is there some way to just get this into the package alone so as to not have people to install extra stuff as part of the setup process?
The only way I can think of is to copy src/Curryrs/Build.hs to htest/Curryrs/Build.hs and keep the two in sync.
Stack uses cabal files under the hood to figure things out and how to compile everything. stack.yaml is used to specify other things needed that aren't in the LTS. If you haven't I'd recommend taking a look at it, but it's not required. This package just is meant to work for both. Stack uses cabal to do it's compilation it seems. It looks like in this article they mention that Setup.hs is used.
I've had a bit of a play around with Stack. Unfortunately, Stack doesn't allow specifying a --work-dir
above the current directory. This is needed to ensure all Haskell output goes into Cargo's target directory.
That should be fine. Not a big fan of hardcoding if avoidable but It's not always possible. I don't think the RTS will change much anytime soon and it's only like 4 versions so adding to them later if needed is fine.
Ok, my latest commit re-adds the ability to select an RTS. Also, on my system there seems to be a couple extra RTS flavors available so I updated the feature flags to make them selectable.
You could do a symlink for the build file. It'll just point to one file but it's treated as if it's in the same directory.
I've had a bit of a play around with Stack. Unfortunately, Stack doesn't allow specifying a --work-dir above the current directory. This is needed to ensure all Haskell output goes into Cargo's target directory.
Really? That seems like a bad idea on Stack's part but they might have a reason.
You could do a symlink for the build file. It'll just point to one file but it's treated as if it's in the same directory.
Right, I forgot about symlinks. But would that still work on Windows?
Really? That seems like a bad idea on Stack's part but they might have a reason.
They have an open issue here: commercialhaskell/stack#1731
Looks like it's blocked by this causing windows to not work.
Symlink would work on one but not the other I would think and it would conflict. I wonder if Haskell has a macro like Rust's include!()
that could solve the issue.
Haskell has #include
directives via CPP but the Setup.hs file gets copied to a different location before it gets compiled so it wont be as simple as
#include "../src/Curryrs/Build.hs"
Yeah and I'm not too much of a fan of #include. It's a bit too hand wavy and compiler magic.