Skip to content

Commit a3157c1

Browse files
authored
Merge pull request #164 from mlabs-haskell/szg251/rust-nix
lbf-nix for Rust
2 parents 59d3fb6 + 2730faf commit a3157c1

File tree

39 files changed

+2139
-296
lines changed

39 files changed

+2139
-296
lines changed

extras/flake-rust.nix

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,36 @@ let
77
};
88
craneLib = crane.lib.${pkgs.system}.overrideToolchain rustWithTools;
99

10+
cleanSrc = craneLib.cleanCargoSource (craneLib.path src);
11+
1012
# Library source code with extra dependencies attached
11-
fullSrc = pkgs.stdenv.mkDerivation {
12-
src = craneLib.cleanCargoSource (craneLib.path src);
13-
name = "lbf-rust-build-env";
14-
unpackPhase = ''
15-
mkdir $out
16-
cp -r $src/* $out
17-
cd $out
18-
${copyExtraSources}
19-
${copyData}
20-
'';
21-
};
13+
fullSrc =
14+
pkgs.stdenv.mkDerivation
15+
{
16+
src = cleanSrc;
17+
name = "${crateName}-build-env";
18+
unpackPhase = ''
19+
mkdir $out
20+
cp -r $src/* $out
21+
cd $out
22+
${copyExtraSources}
23+
${copyData}
24+
'';
25+
};
26+
27+
vendoredSrc =
28+
pkgs.stdenv.mkDerivation
29+
{
30+
src = cleanSrc;
31+
name = "${crateName}-vendored-src";
32+
unpackPhase = ''
33+
mkdir $out
34+
cp -r $src/* $out
35+
cd $out
36+
sed -i 's/.extras/../g' Cargo.toml
37+
'';
38+
};
39+
2240
commonArgs = {
2341
src = fullSrc;
2442
pname = crateName;
@@ -28,6 +46,7 @@ let
2846

2947
# Extra sources
3048
extra-sources = pkgs.linkFarm "extra-sources" extraSources;
49+
3150
hasExtraSources = builtins.length extraSources > 0;
3251
linkExtraSources = pkgs.lib.optionalString hasExtraSources ''
3352
echo "Linking extra sources"
@@ -68,6 +87,8 @@ in
6887
doInstallCargoArtifacts = true;
6988
});
7089

90+
packages."${crateName}-rust-src" = vendoredSrc;
91+
7192
checks."${crateName}-rust-test" = craneLib.cargoNextest (commonArgs // {
7293
inherit cargoArtifacts;
7394
nativeBuildInputs = testTools;

extras/lbf-nix/build.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ _: {
44
lbg-haskell = "${config.packages.lbg-haskell}/bin/lbg-haskell";
55
lbg-plutarch = "${config.packages.lbg-plutarch}/bin/lbg-plutarch";
66
lbg-purescript = "${config.packages.lbg-purescript}/bin/lbg-purescript";
7+
lbg-rust = "${config.packages.lbg-rust}/bin/lbg-rust";
78

89
in
910
{
@@ -18,6 +19,9 @@ _: {
1819
lbfPurescript = import ./lbf-purescript.nix pkgs config.packages.lbf lbg-purescript;
1920
lbfPreludePurescript = import ./lbf-prelude-purescript.nix pkgs config.packages.lbf lbg-purescript;
2021
lbfPlutusPurescript = import ./lbf-plutus-purescript.nix pkgs config.packages.lbf lbg-purescript;
22+
lbfRust = import ./lbf-rust.nix pkgs config.packages.lbf lbg-rust;
23+
lbfPreludeRust = import ./lbf-prelude-rust.nix pkgs config.packages.lbf lbg-rust;
24+
lbfPlutusRust = import ./lbf-plutus-rust.nix pkgs config.packages.lbf lbg-rust;
2125
};
2226

2327
};

extras/lbf-nix/lbf-plutus-rust.nix

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Build .lbf schemas that use LB Plutus (and by extension LB Prelude) package and targets Rust's plutus-ledger-api library.
2+
pkgs: lbf: lbg-rust: lbfRustOpts:
3+
let
4+
utils = import ./utils.nix pkgs;
5+
6+
lbfRust = import ./lbf-rust.nix pkgs lbf lbg-rust;
7+
lbfRustOptsForPlutus = utils.overrideAttrs
8+
{
9+
imports = {
10+
default = { };
11+
override = libs: libs // {
12+
lbf-prelude = ../../libs/lbf-prelude;
13+
lbf-plutus = ../../libs/lbf-plutus;
14+
};
15+
};
16+
classes = {
17+
default = [ ];
18+
override = cls: cls ++ [ "Prelude.Eq" "Plutus.V1.PlutusData" ];
19+
};
20+
configs = {
21+
default = [ ];
22+
override = _: [ ../../lambda-buffers-codegen/data/rust-prelude-base.json ../../lambda-buffers-codegen/data/rust-plutus-pla.json ];
23+
};
24+
}
25+
lbfRustOpts;
26+
in
27+
lbfRust lbfRustOptsForPlutus
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Build .lbf schemas that use LB Prelude package and targets Rust's std (and friends) library.
2+
pkgs: lbf: lbg-rust: lbfRustOpts:
3+
let
4+
utils = import ./utils.nix pkgs;
5+
6+
lbfRs = import ./lbf-rust.nix pkgs lbf lbg-rust;
7+
lbfRustOptsForPrelude = utils.overrideAttrs
8+
{
9+
imports = {
10+
default = { };
11+
override = libs: libs // { lbf-prelude = ../../libs/lbf-prelude; };
12+
};
13+
classes = {
14+
default = [ ];
15+
override = cls: cls ++ [ "Prelude.Eq" "Prelude.Json" ];
16+
};
17+
configs = {
18+
default = [ ];
19+
override = cfgs: cfgs ++ [ ../../lambda-buffers-codegen/data/rust-prelude-base.json ];
20+
};
21+
}
22+
lbfRustOpts;
23+
24+
in
25+
lbfRs lbfRustOptsForPrelude

extras/lbf-nix/lbf-rust.nix

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Base API for constructing Rust packages given .lbf schemas
2+
3+
# Nixpkgs
4+
pkgs:
5+
# LambdaBuffers Frontend
6+
lbf:
7+
# LambdaBuffers Rust Codegen
8+
lbg-rust:
9+
let
10+
lbfRustOpts =
11+
{
12+
# Source that is passed to `lbf` as the `--import-path` flag and used to find `files`.
13+
# Examples: src = ./api
14+
src
15+
, # Additional sources that are passed to `lbf` as the `--import-path` flag.
16+
# Examples: imports = { lbf-prelude = ./lbf-prelude; }
17+
imports ? { }
18+
, # .lbf files in `src` to compile and codegen.
19+
# Examples: files = [ "Foo.lbf" "Foo/Bar.lbf" ]
20+
files
21+
# Classes for which to generate implementations for (default lbf-prelude classes).
22+
, classes ? [ ]
23+
, # Dependencies to include in the Cabal's `build-depends` stanza.
24+
# examples: dependencies = [ "lbf-prelude" ]
25+
dependencies ? [ ]
26+
, configs ? [ ]
27+
, # Name of the package and also the name of the Cabal package.
28+
# Examples: name = "lbf-myproject"
29+
name
30+
, # Version of the package and also the version of the Cabal package.
31+
# Examples: version = "0.1.0.0"
32+
version ? "0.1.0"
33+
}: { inherit src imports files classes dependencies configs name version; };
34+
35+
lbf-build = import ./lbf-build.nix pkgs lbf;
36+
37+
lbfBuild = opts: with (lbfRustOpts opts);
38+
let
39+
findModules = root: map
40+
(path: builtins.replaceStrings [ "/" ] [ "." ]
41+
(pkgs.lib.strings.removePrefix "./" (pkgs.lib.strings.removeSuffix ".lbf"
42+
(pkgs.lib.path.removePrefix root path))))
43+
(builtins.filter (pkgs.lib.hasSuffix ".lbf")
44+
(pkgs.lib.filesystem.listFilesRecursive root));
45+
packageSet =
46+
pkgs.writeTextFile {
47+
name = "lb-packages";
48+
text =
49+
builtins.toJSON
50+
({ crate = findModules src; } // builtins.mapAttrs (_: findModules) imports);
51+
};
52+
53+
in
54+
lbf-build.build
55+
{
56+
inherit src;
57+
opts = {
58+
inherit files;
59+
import-paths = pkgs.lib.attrsets.attrValues imports;
60+
gen = lbg-rust;
61+
gen-classes = classes;
62+
gen-dir = "autogen";
63+
gen-opts = [ "--packages=${packageSet}" ] ++ builtins.map (c: "--config=${c}") configs; # WARN(bladyjoker): If I put quotes here everything breaks.
64+
work-dir = ".work";
65+
};
66+
};
67+
68+
cargoTemplate = opts: with (lbfRustOpts opts);
69+
pkgs.writeTextFile {
70+
name = "lambda-buffers-cabal-template";
71+
text = ''
72+
[package]
73+
name = "${name}"
74+
version = "${version}"
75+
edition = "2021"
76+
77+
[dependencies]
78+
'';
79+
};
80+
81+
#
82+
crateVersions = pkgs.writeTextFile {
83+
name = "lambda-buffers-crate-versions";
84+
text = ''
85+
num-bigint = "0.4.4"
86+
serde_json = { version = "1.0.107", features = ["arbitrary_precision"] }
87+
plutus-ledger-api = { git = "https://github.com/mlabs-haskell/plutus-ledger-api-rust", features = [ "lbf", ], rev = "fb93fa590908580eb40368369bf6614d42ce9a95" }
88+
'';
89+
};
90+
91+
build = opts: with (lbfRustOpts opts);
92+
let
93+
lbfBuilt = lbfBuild opts;
94+
in
95+
pkgs.stdenv.mkDerivation {
96+
inherit src version;
97+
pname = name;
98+
outputs = [ "out" "buildjson" ];
99+
buildInputs = [
100+
pkgs.jq
101+
];
102+
buildPhase = ''
103+
ln -s ${lbfBuilt} autogen;
104+
ln -s ${lbfBuilt.workdir} .work-dir;
105+
ln -s ${lbfBuilt.buildjson} build.json;
106+
107+
# Generating Cargo manifest file
108+
DEPS=$(echo ${builtins.concatStringsSep " " dependencies} $(cat build.json | jq -r ".[]" | sort -u));
109+
echo "Gathered Cargo deps $DEPS";
110+
cat ${cargoTemplate opts} > Cargo.toml;
111+
for DEP in $DEPS; do
112+
if [ $DEP != "std" ]; then
113+
echo "$(cat ${crateVersions} | grep "$DEP" || echo "$DEP = { path = \"../$DEP\" }")" >> Cargo.toml
114+
fi
115+
done
116+
'';
117+
118+
installPhase = ''
119+
cp build.json $buildjson;
120+
echo "Dependencies collected"
121+
cat $buildjson;
122+
123+
mkdir -p $out/src;
124+
cp -r autogen/* $out/src
125+
cp Cargo.toml $out/Cargo.toml;
126+
127+
# Generating module files
128+
chmod -R u+w $out/src
129+
pushd $out/src
130+
131+
MODS=$(find . -type f -name "*.rs")
132+
MODS+=" "
133+
MODS+=$(find . -type d)
134+
135+
for MOD in $MODS; do
136+
if [ "$MOD" != "." ]; then
137+
if [ $(dirname $MOD) = "." ];
138+
then MODFILE="lib.rs";
139+
else MODFILE=$(dirname $MOD).rs;
140+
fi
141+
DOC="pub mod $(basename $MOD .rs);"
142+
143+
if [ ! $(grep "$DOC" $MODFILE) ]; then
144+
echo $DOC >> $MODFILE;
145+
fi
146+
fi
147+
done
148+
149+
echo "Files generated"
150+
find $out/;
151+
'';
152+
};
153+
in
154+
build

flake.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,13 @@
8282
./testsuites/lbt-prelude/golden/build.nix
8383
./testsuites/lbt-prelude/lbt-prelude-haskell/build.nix
8484
./testsuites/lbt-prelude/lbt-prelude-purescript/build.nix
85+
./testsuites/lbt-prelude/lbt-prelude-rust/build.nix
8586
./testsuites/lbt-plutus/api/build.nix
8687
./testsuites/lbt-plutus/golden/build.nix
8788
./testsuites/lbt-plutus/lbt-plutus-haskell/build.nix
8889
./testsuites/lbt-plutus/lbt-plutus-purescript/build.nix
8990
./testsuites/lbt-plutus/lbt-plutus-plutarch/build.nix
91+
./testsuites/lbt-plutus/lbt-plutus-rust/build.nix
9092
./experimental/build.nix
9193
];
9294
debug = true;

lambda-buffers-codegen/app/LambdaBuffers/Codegen/Cli/GenRust.hs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ module LambdaBuffers.Codegen.Cli.GenRust (GenOpts (..), gen) where
33
import Control.Lens (makeLenses, (^.))
44
import Control.Monad (unless)
55
import Data.Aeson (decodeFileStrict')
6+
import Debug.Trace (trace)
67
import LambdaBuffers.Codegen.Cli.Gen (logError)
78
import LambdaBuffers.Codegen.Cli.Gen qualified as Gen
89
import LambdaBuffers.Codegen.Rust (runPrint)
910
import LambdaBuffers.Codegen.Rust.Config qualified as R
11+
import LambdaBuffers.Codegen.Rust.Print.Syntax qualified as RS
1012
import Paths_lambda_buffers_codegen qualified as Paths
1113
import System.Directory (doesFileExist)
1214
import System.Directory.Internal.Prelude (exitFailure)
1315

1416
data GenOpts = MkGenOpts
1517
{ _config :: [FilePath]
18+
, _packages :: FilePath
1619
, _common :: Gen.GenOpts
1720
}
1821

@@ -28,9 +31,12 @@ gen opts = do
2831
cfgs <- traverse readRustConfig fps
2932
return (mconcat cfgs)
3033

34+
let pkgsCfg = opts ^. packages
35+
pkgs <- readPackages pkgsCfg
36+
3137
Gen.gen
3238
(opts ^. common)
33-
(\ci -> fmap (\(fp, code, deps) -> Gen.Generated fp code deps) . runPrint cfg ci <$> (ci ^. #modules))
39+
(\ci -> fmap (\(fp, code, deps) -> Gen.Generated fp code deps) . runPrint cfg pkgs ci <$> (ci ^. #modules))
3440

3541
readRustConfig :: FilePath -> IO R.Config
3642
readRustConfig f = do
@@ -47,3 +53,19 @@ readRustConfig f = do
4753
logError "" $ "Invalid Rust configuration file " <> f
4854
exitFailure
4955
Just cfg -> return cfg
56+
57+
readPackages :: FilePath -> IO RS.PkgMap
58+
readPackages f = do
59+
fExists <- doesFileExist f
60+
unless
61+
fExists
62+
( do
63+
logError "" $ "Provided Rust Codegen package manifest file doesn't exists: " <> f
64+
exitFailure
65+
)
66+
mayPkgs <- decodeFileStrict' f
67+
case mayPkgs of
68+
Nothing -> do
69+
logError "" $ "Invalid Rust package manifest file " <> f
70+
exitFailure
71+
Just pkgs -> trace (show pkgs) (R.mkPkgMap pkgs)

lambda-buffers-codegen/app/Main.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ rustGenOptsP =
128128
<> help "Configuration file for the Rust Codegen module (multiple `config`s are merged with left first merge conflict strategy)"
129129
)
130130
)
131+
<*> strOption
132+
( long "packages"
133+
<> short 'g'
134+
<> metavar "FILEPATH"
135+
<> help "JSON file containing the package-set and all of its modules (including current package)"
136+
)
131137
<*> genOptsP
132138

133139
mkProgDesc :: forall {a}. String -> InfoMod a

lambda-buffers-codegen/data/rust-plutus-pla.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"plutus-ledger-api",
4040
"v1",
4141
"interval",
42-
"Interval"
42+
"PlutusInterval"
4343
],
4444
"Plutus.V1.Extended": [
4545
"plutus-ledger-api",

lambda-buffers-codegen/data/rust-prelude-base.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"char"
4040
],
4141
"Prelude.Integer": [
42-
"num_bigint",
42+
"num-bigint",
4343
"BigInt"
4444
],
4545
"Prelude.Bool": [

0 commit comments

Comments
 (0)