Skip to content

lbf-nix for Rust #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions extras/flake-rust.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,36 @@ let
};
craneLib = crane.lib.${pkgs.system}.overrideToolchain rustWithTools;

cleanSrc = craneLib.cleanCargoSource (craneLib.path src);

# Library source code with extra dependencies attached
fullSrc = pkgs.stdenv.mkDerivation {
src = craneLib.cleanCargoSource (craneLib.path src);
name = "lbf-rust-build-env";
unpackPhase = ''
mkdir $out
cp -r $src/* $out
cd $out
${copyExtraSources}
${copyData}
'';
};
fullSrc =
pkgs.stdenv.mkDerivation
{
src = cleanSrc;
name = "${crateName}-build-env";
unpackPhase = ''
mkdir $out
cp -r $src/* $out
cd $out
${copyExtraSources}
${copyData}
'';
};

vendoredSrc =
pkgs.stdenv.mkDerivation
{
src = cleanSrc;
name = "${crateName}-vendored-src";
unpackPhase = ''
mkdir $out
cp -r $src/* $out
cd $out
sed -i 's/.extras/../g' Cargo.toml
'';
};

commonArgs = {
src = fullSrc;
pname = crateName;
Expand All @@ -28,6 +46,7 @@ let

# Extra sources
extra-sources = pkgs.linkFarm "extra-sources" extraSources;

hasExtraSources = builtins.length extraSources > 0;
linkExtraSources = pkgs.lib.optionalString hasExtraSources ''
echo "Linking extra sources"
Expand Down Expand Up @@ -68,6 +87,8 @@ in
doInstallCargoArtifacts = true;
});

packages."${crateName}-rust-src" = vendoredSrc;

checks."${crateName}-rust-test" = craneLib.cargoNextest (commonArgs // {
inherit cargoArtifacts;
nativeBuildInputs = testTools;
Expand Down
4 changes: 4 additions & 0 deletions extras/lbf-nix/build.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ _: {
lbg-haskell = "${config.packages.lbg-haskell}/bin/lbg-haskell";
lbg-plutarch = "${config.packages.lbg-plutarch}/bin/lbg-plutarch";
lbg-purescript = "${config.packages.lbg-purescript}/bin/lbg-purescript";
lbg-rust = "${config.packages.lbg-rust}/bin/lbg-rust";

in
{
Expand All @@ -18,6 +19,9 @@ _: {
lbfPurescript = import ./lbf-purescript.nix pkgs config.packages.lbf lbg-purescript;
lbfPreludePurescript = import ./lbf-prelude-purescript.nix pkgs config.packages.lbf lbg-purescript;
lbfPlutusPurescript = import ./lbf-plutus-purescript.nix pkgs config.packages.lbf lbg-purescript;
lbfRust = import ./lbf-rust.nix pkgs config.packages.lbf lbg-rust;
lbfPreludeRust = import ./lbf-prelude-rust.nix pkgs config.packages.lbf lbg-rust;
lbfPlutusRust = import ./lbf-plutus-rust.nix pkgs config.packages.lbf lbg-rust;
};

};
Expand Down
27 changes: 27 additions & 0 deletions extras/lbf-nix/lbf-plutus-rust.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Build .lbf schemas that use LB Plutus (and by extension LB Prelude) package and targets Rust's plutus-ledger-api library.
pkgs: lbf: lbg-rust: lbfRustOpts:
let
utils = import ./utils.nix pkgs;

lbfRust = import ./lbf-rust.nix pkgs lbf lbg-rust;
lbfRustOptsForPlutus = utils.overrideAttrs
{
imports = {
default = { };
override = libs: libs // {
lbf-prelude = ../../libs/lbf-prelude;
lbf-plutus = ../../libs/lbf-plutus;
};
};
classes = {
default = [ ];
override = cls: cls ++ [ "Prelude.Eq" "Plutus.V1.PlutusData" ];
};
configs = {
default = [ ];
override = _: [ ../../lambda-buffers-codegen/data/rust-prelude-base.json ../../lambda-buffers-codegen/data/rust-plutus-pla.json ];
};
}
lbfRustOpts;
in
lbfRust lbfRustOptsForPlutus
25 changes: 25 additions & 0 deletions extras/lbf-nix/lbf-prelude-rust.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Build .lbf schemas that use LB Prelude package and targets Rust's std (and friends) library.
pkgs: lbf: lbg-rust: lbfRustOpts:
let
utils = import ./utils.nix pkgs;

lbfRs = import ./lbf-rust.nix pkgs lbf lbg-rust;
lbfRustOptsForPrelude = utils.overrideAttrs
{
imports = {
default = { };
override = libs: libs // { lbf-prelude = ../../libs/lbf-prelude; };
};
classes = {
default = [ ];
override = cls: cls ++ [ "Prelude.Eq" "Prelude.Json" ];
};
configs = {
default = [ ];
override = cfgs: cfgs ++ [ ../../lambda-buffers-codegen/data/rust-prelude-base.json ];
};
}
lbfRustOpts;

in
lbfRs lbfRustOptsForPrelude
154 changes: 154 additions & 0 deletions extras/lbf-nix/lbf-rust.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Base API for constructing Rust packages given .lbf schemas

# Nixpkgs
pkgs:
# LambdaBuffers Frontend
lbf:
# LambdaBuffers Rust Codegen
lbg-rust:
let
lbfRustOpts =
{
# Source that is passed to `lbf` as the `--import-path` flag and used to find `files`.
# Examples: src = ./api
src
, # Additional sources that are passed to `lbf` as the `--import-path` flag.
# Examples: imports = { lbf-prelude = ./lbf-prelude; }
imports ? { }
, # .lbf files in `src` to compile and codegen.
# Examples: files = [ "Foo.lbf" "Foo/Bar.lbf" ]
files
# Classes for which to generate implementations for (default lbf-prelude classes).
, classes ? [ ]
, # Dependencies to include in the Cabal's `build-depends` stanza.
# examples: dependencies = [ "lbf-prelude" ]
dependencies ? [ ]
, configs ? [ ]
, # Name of the package and also the name of the Cabal package.
# Examples: name = "lbf-myproject"
name
, # Version of the package and also the version of the Cabal package.
# Examples: version = "0.1.0.0"
version ? "0.1.0"
}: { inherit src imports files classes dependencies configs name version; };

lbf-build = import ./lbf-build.nix pkgs lbf;

lbfBuild = opts: with (lbfRustOpts opts);
let
findModules = root: map
(path: builtins.replaceStrings [ "/" ] [ "." ]
(pkgs.lib.strings.removePrefix "./" (pkgs.lib.strings.removeSuffix ".lbf"
(pkgs.lib.path.removePrefix root path))))
(builtins.filter (pkgs.lib.hasSuffix ".lbf")
(pkgs.lib.filesystem.listFilesRecursive root));
packageSet =
pkgs.writeTextFile {
name = "lb-packages";
text =
builtins.toJSON
({ crate = findModules src; } // builtins.mapAttrs (_: findModules) imports);
};

in
lbf-build.build
{
inherit src;
opts = {
inherit files;
import-paths = pkgs.lib.attrsets.attrValues imports;
gen = lbg-rust;
gen-classes = classes;
gen-dir = "autogen";
gen-opts = [ "--packages=${packageSet}" ] ++ builtins.map (c: "--config=${c}") configs; # WARN(bladyjoker): If I put quotes here everything breaks.
work-dir = ".work";
};
};

cargoTemplate = opts: with (lbfRustOpts opts);
pkgs.writeTextFile {
name = "lambda-buffers-cabal-template";
text = ''
[package]
name = "${name}"
version = "${version}"
edition = "2021"

[dependencies]
'';
};

#
crateVersions = pkgs.writeTextFile {
name = "lambda-buffers-crate-versions";
text = ''
num-bigint = "0.4.4"
serde_json = { version = "1.0.107", features = ["arbitrary_precision"] }
plutus-ledger-api = { git = "https://github.com/mlabs-haskell/plutus-ledger-api-rust", features = [ "lbf", ], rev = "fb93fa590908580eb40368369bf6614d42ce9a95" }
'';
};

build = opts: with (lbfRustOpts opts);
let
lbfBuilt = lbfBuild opts;
in
pkgs.stdenv.mkDerivation {
inherit src version;
pname = name;
outputs = [ "out" "buildjson" ];
buildInputs = [
pkgs.jq
];
buildPhase = ''
ln -s ${lbfBuilt} autogen;
ln -s ${lbfBuilt.workdir} .work-dir;
ln -s ${lbfBuilt.buildjson} build.json;

# Generating Cargo manifest file
DEPS=$(echo ${builtins.concatStringsSep " " dependencies} $(cat build.json | jq -r ".[]" | sort -u));
echo "Gathered Cargo deps $DEPS";
cat ${cargoTemplate opts} > Cargo.toml;
for DEP in $DEPS; do
if [ $DEP != "std" ]; then
echo "$(cat ${crateVersions} | grep "$DEP" || echo "$DEP = { path = \"../$DEP\" }")" >> Cargo.toml
fi
done
'';

installPhase = ''
cp build.json $buildjson;
echo "Dependencies collected"
cat $buildjson;

mkdir -p $out/src;
cp -r autogen/* $out/src
cp Cargo.toml $out/Cargo.toml;

# Generating module files
chmod -R u+w $out/src
pushd $out/src

MODS=$(find . -type f -name "*.rs")
MODS+=" "
MODS+=$(find . -type d)

for MOD in $MODS; do
if [ "$MOD" != "." ]; then
if [ $(dirname $MOD) = "." ];
then MODFILE="lib.rs";
else MODFILE=$(dirname $MOD).rs;
fi
DOC="pub mod $(basename $MOD .rs);"

if [ ! $(grep "$DOC" $MODFILE) ]; then
echo $DOC >> $MODFILE;
fi
fi
done

echo "Files generated"
find $out/;
'';
};
in
build
2 changes: 2 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@
./testsuites/lbt-prelude/golden/build.nix
./testsuites/lbt-prelude/lbt-prelude-haskell/build.nix
./testsuites/lbt-prelude/lbt-prelude-purescript/build.nix
./testsuites/lbt-prelude/lbt-prelude-rust/build.nix
./testsuites/lbt-plutus/api/build.nix
./testsuites/lbt-plutus/golden/build.nix
./testsuites/lbt-plutus/lbt-plutus-haskell/build.nix
./testsuites/lbt-plutus/lbt-plutus-purescript/build.nix
./testsuites/lbt-plutus/lbt-plutus-plutarch/build.nix
./testsuites/lbt-plutus/lbt-plutus-rust/build.nix
./experimental/build.nix
];
debug = true;
Expand Down
24 changes: 23 additions & 1 deletion lambda-buffers-codegen/app/LambdaBuffers/Codegen/Cli/GenRust.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ module LambdaBuffers.Codegen.Cli.GenRust (GenOpts (..), gen) where
import Control.Lens (makeLenses, (^.))
import Control.Monad (unless)
import Data.Aeson (decodeFileStrict')
import Debug.Trace (trace)
import LambdaBuffers.Codegen.Cli.Gen (logError)
import LambdaBuffers.Codegen.Cli.Gen qualified as Gen
import LambdaBuffers.Codegen.Rust (runPrint)
import LambdaBuffers.Codegen.Rust.Config qualified as R
import LambdaBuffers.Codegen.Rust.Print.Syntax qualified as RS
import Paths_lambda_buffers_codegen qualified as Paths
import System.Directory (doesFileExist)
import System.Directory.Internal.Prelude (exitFailure)

data GenOpts = MkGenOpts
{ _config :: [FilePath]
, _packages :: FilePath
, _common :: Gen.GenOpts
}

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

let pkgsCfg = opts ^. packages
pkgs <- readPackages pkgsCfg

Gen.gen
(opts ^. common)
(\ci -> fmap (\(fp, code, deps) -> Gen.Generated fp code deps) . runPrint cfg ci <$> (ci ^. #modules))
(\ci -> fmap (\(fp, code, deps) -> Gen.Generated fp code deps) . runPrint cfg pkgs ci <$> (ci ^. #modules))

readRustConfig :: FilePath -> IO R.Config
readRustConfig f = do
Expand All @@ -47,3 +53,19 @@ readRustConfig f = do
logError "" $ "Invalid Rust configuration file " <> f
exitFailure
Just cfg -> return cfg

readPackages :: FilePath -> IO RS.PkgMap
readPackages f = do
fExists <- doesFileExist f
unless
fExists
( do
logError "" $ "Provided Rust Codegen package manifest file doesn't exists: " <> f
exitFailure
)
mayPkgs <- decodeFileStrict' f
case mayPkgs of
Nothing -> do
logError "" $ "Invalid Rust package manifest file " <> f
exitFailure
Just pkgs -> trace (show pkgs) (R.mkPkgMap pkgs)
6 changes: 6 additions & 0 deletions lambda-buffers-codegen/app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ rustGenOptsP =
<> help "Configuration file for the Rust Codegen module (multiple `config`s are merged with left first merge conflict strategy)"
)
)
<*> strOption
( long "packages"
<> short 'g'
<> metavar "FILEPATH"
<> help "JSON file containing the package-set and all of its modules (including current package)"
)
<*> genOptsP

mkProgDesc :: forall {a}. String -> InfoMod a
Expand Down
2 changes: 1 addition & 1 deletion lambda-buffers-codegen/data/rust-plutus-pla.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"plutus-ledger-api",
"v1",
"interval",
"Interval"
"PlutusInterval"
],
"Plutus.V1.Extended": [
"plutus-ledger-api",
Expand Down
2 changes: 1 addition & 1 deletion lambda-buffers-codegen/data/rust-prelude-base.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"char"
],
"Prelude.Integer": [
"num_bigint",
"num-bigint",
"BigInt"
],
"Prelude.Bool": [
Expand Down
Loading