#haskell #cargo-build #cabal #cargo-toml #bindings-generator #generate #hs-bindgen

bin+lib cargo-cabal

一个工具,帮助您将一个 Rust 包通过一条命令转换成 Haskell Cabal 库

8 个版本

0.9.0 2024 年 3 月 19 日
0.8.5 2023 年 2 月 16 日
0.8.0 2023 年 1 月 27 日
0.7.1 2023 年 1 月 3 日
0.1.0 2022 年 10 月 26 日

#271 in Rust 模式

Download history 1/week @ 2024-04-07 1/week @ 2024-06-09

每月 307 次下载

MIT/Apache

595KB
427

cargo-cabal

一个工具,帮助您将一个 Rust 包通过一条命令转换成 Haskell Cabal 库!

要生成绑定,您需要使用 hs-bindgen 宏来注释您想公开的 Rust 函数。

入门指南

这里有一个屏幕录像演示了它是如何工作的(命令遍历见下文)

asciinema

注意。 您需要在您的 $ 中有一个正常工作的 Rust 和 Haskell 环境,如果您使用 Nix,您只需输入: nix shell -p cabal install ghc cargo rustc


欢迎来到这个小 cargo-cabal / hs-bindgen 演示!

让我们先创建一个愚蠢的 Rust 库!

$ cargo new --lib greetings
     Created library `greetings` package

$ tree greetings
greetings
├── Cargo.toml
└── src
    └── lib.rs

1 directory, 2 files

$ cd greetings

hs-bindgen 添加到依赖项列表

$ cargo add hs-bindgen --features full
    Updating crates.io index
      Adding hs-bindgen v0.8.0 to dependencies.
             Features:
             + antlion
             + full
             + std

并使用它来装饰我们想要公开的函数

  • src/lib.rs:
use hs_bindgen::*;

#[hs_bindgen]
fn hello(name: &str) {
    println!("Hello, {name}!");
}
$ cargo build
   Compiling proc-macro2 v1.0.47
   Compiling quote v1.0.21
   Compiling unicode-ident v1.0.5
   Compiling syn v1.0.105
   Compiling serde_derive v1.0.149
   Compiling semver-parser v0.7.0
   Compiling serde v1.0.149
   Compiling thiserror v1.0.37
   Compiling antlion v0.3.1
   Compiling semver v0.9.0
   Compiling semver v1.0.14
   Compiling lazy_static v1.4.0
   Compiling hs-bindgen-traits v0.8.0
   Compiling rustc_version v0.2.3
   Compiling hs-bindgen-attribute v0.7.2
   Compiling thiserror-impl v1.0.37
   Compiling displaydoc v0.2.3
   Compiling hs-bindgen-types v0.8.0
   Compiling toml v0.5.9
   Compiling hs-bindgen v0.8.0
   Compiling greetings v0.1.0 (/Users/yvan/demo/greetings)
error: custom attribute panicked
 --> src/lib.rs:3:1
  |
3 | #[hs_bindgen]
  | ^^^^^^^^^^^^^
  |
  = help: message: fail to read content of `hsbindgen.toml` configuration file
          n.b. you have to run the command `cargo-cabal` to generate it: Os { code: 2, kind: NotFound, message: "No such file or directory" }

error: could not compile `greetings` due to previous error

所以,我们将使用 cargo-cabal 来检查我们的设置并生成 Cabal 文件

$ cargo install cargo-cabal
    Updating crates.io index
     Ignored package `cargo-cabal v0.7.0` is already installed, use --force to override

$ cargo cabal init
Error: Your `Cargo.toml` file should contain a [lib] section with a `crate-type` field
that contains either `staticlib` or `cdylib` value, e.g.:

[lib]
crate-type = ["staticlib"]

注意。 如果您是 Nix 用户,而不是依赖 impure cargo install,您可以直接运行: nix run github:yvan-sraka:cargo-cabal -- cabal init

好的,我们相应地编辑 Cargo.toml

  • Cargo.toml:
[package]
name = "greetings"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.net.cn/cargo/reference/manifest.html

[dependencies]
hs-bindgen = { version = "0.8.0", features = ["full"] }

[lib]
crate-type = ["staticlib"]
$ cargo cabal init
Cabal files generated!
**********************
You should now be able to compile your library with `cabal build` and should
add `hs-bindgen` to your crate dependencies list and decorate the Rust function
you want to expose with `#[hs_bindgen]` attribute macro.

$ ls
Cargo.lock  Cargo.toml  Setup.lhs  greetings.cabal  src  target
$ cargo build
   Compiling greetings v0.1.0 (/Users/yvan/demo/greetings)
    Finished dev [unoptimized + debuginfo] target(s) in 1.06s

$ cabal build
Build profile: -w ghc-9.0.2 -O1
In order, the following will be built (use -v for more details):
 - greetings-0.1.0 (lib:greetings) (first run)
[1 of 1] Compiling Main             ( omitted ... )
Linking /Users/yvan/demo/dist-newstyle/build/aarch64-osx/ghc-9.0.2/greetings-0.1.0/setup/setup ...
Configuring greetings-0.1.0...
Preprocessing library for greetings-0.1.0..
Building library for greetings-0.1.0..
[1 of 1] Compiling Greetings        ( src/Greetings.hs, omitted ... )

它工作!如果您只是想在 Rust 项目中使用这个库,那么 cargo build 也可以正常工作!


现在让我们尝试在我们的新生成的库中用 Haskell 应用程序来使用它 😉

$ cd ..
$ cabal init --non-interactive test
[Log] Guessing dependencies...
[Log] Using cabal specification: 3.8
[Warning] unknown license type, you must put a copy in LICENSE yourself.
[Log] Creating fresh file CHANGELOG.md...
[Log] Creating fresh directory ./app...
[Log] Creating fresh file app/Main.hs...
[Log] Creating fresh file test.cabal...
[Warning] No synopsis given. You should edit the .cabal file and add one.
[Info] You may want to edit the .cabal file and add a Description field.

$ tree test
test
├── app
│   └── Main.hs
├── CHANGELOG.md
└── test.cabal

1 directory, 3 files

我们创建一个 cabal.project(相当于 cargo workspace)来执行本地测试,而无需上传 greetings 到 hackage

  • cabal.项目:
packages: ./greetings ./test

我们编辑 test.cabal 使其依赖 greetings

  • test/test.cabal(部分内容省略)
executable test
    -- Other library packages from which modules are imported.
    build-depends:    base, greetings

我们编写了一个极简的 main 函数,该函数将从 Greetings 模块调用 hello

  • test/app/Main.hs:
module Main where

import Foreign.C.String
import Greetings

main :: IO ()
main = withCString "Rust 🦀" hello

让我们检查一切是否按预期工作

$ cabal run test
Build profile: -w ghc-9.0.2 -O1
In order, the following will be built (use -v for more details):
 - test-0.1.0.0 (exe:test) (first run)
Configuring executable 'test' for test-0.1.0.0..
Preprocessing executable 'test' for test-0.1.0.0..
Building executable 'test' for test-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, omitted ... )
Linking /Users/yvan/demo/dist-newstyle/build/aarch64-osx/ghc-9.0.2/test-0.1.0.0/x/test/build/test/test ...
Hello, Rust 🦀!

这就完了,朋友们!祝你们编程愉快 🙂

Nix 支持

--enable-nix 命令行参数使 cargo-cabal 生成基于 haskell.nix / naerskflake.nix,而不是 Setup.lhs

注意:当首次与 hs-bindgen 和 Nix flake 一起工作时,请检查 Cargo.lock 是否不在 .gitignore 中,并在 nix build 之前运行 cargo buildgit add --all,这将为您节省很多麻烦 😉

致谢

⚠️ 这仍然是一个工作实验,尚未准备好投入生产。

cargo-cabal 从其他互操作性倡议中汲取了大量灵感,如 wasm-packMaturin

这个项目是作为 IOG 合同工的一部分完成的。

许可

根据您的选择,受 Apache License 2.0 或 MIT 许可证 许可。

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交以包含在此项目中的任何贡献,将按上述方式双重许可,无需任何附加条款或条件。

依赖项

~1.5–2.4MB
~43K SLoC