Difference between revisions of "Packaging/Ruby"

From NixOS Wiki
Jump to: navigation, search
(Added gnumake, can be useful for many gems)
m (rollback unauthorized mass edits)
Tag: Rollback
 
(7 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 +
See [https://ryantm.github.io/nixpkgs/languages-frameworks/ruby/#packaging-applications Packaging Ruby programs] in the nixpkgs manual
 +
 +
 
Ruby projects are generally packaged with [https://github.com/manveru/bundix bundix]. This guide will show how to package a ruby project
 
Ruby projects are generally packaged with [https://github.com/manveru/bundix bundix]. This guide will show how to package a ruby project
 +
 +
See
 +
  
 
== Building '''BeEF''' ==
 
== Building '''BeEF''' ==
Line 20: Line 26:
 
     libxml2
 
     libxml2
 
     libxslt
 
     libxslt
     pkgconfig
+
     pkg-config
 
     bundix
 
     bundix
 
     gnumake
 
     gnumake
Line 30: Line 36:
 
<syntaxHighlight lang=console>
 
<syntaxHighlight lang=console>
 
$ nix-shell
 
$ nix-shell
# generate Gemfile.lock
+
$ bundle install      # generates Gemfile.lock
$ bundle install
+
$ bundix              # generates gemset.nix
# generate gemset.nix
 
$ bundix
 
 
</syntaxHighlight>
 
</syntaxHighlight>
  
Line 58: Line 62:
 
     cat > $bin <<EOF
 
     cat > $bin <<EOF
 
#!/bin/sh -e
 
#!/bin/sh -e
exec ${gems}/bin/bundle exec ${ruby}/bin/ruby $i "\$@"
+
exec ${gems}/bin/bundle exec ${ruby}/bin/ruby $out/share/beef/beef "\$@"
 
EOF
 
EOF
 
     chmod +x $bin
 
     chmod +x $bin
Line 111: Line 115:
 
   };
 
   };
 
</syntaxHighlight>
 
</syntaxHighlight>
 
  
 
=== set the local gemConfig ===
 
=== set the local gemConfig ===
 
'''TODO''': also merge with the <code>defaultGemConfig</code> somehow
 
'''TODO''': also merge with the <code>defaultGemConfig</code> somehow
 +
 +
== Using Bundler 2 ==
 +
 +
Bundler 2 comes included with Ruby, so instead of importing <code>ruby.devEnv</code> import Ruby and Bundix separately.

Latest revision as of 10:55, 6 April 2024

See Packaging Ruby programs in the nixpkgs manual


Ruby projects are generally packaged with bundix. This guide will show how to package a ruby project

See


Building BeEF

$ git clone https://github.com/beefproject/beef/

Create shell.nix with all dependencies

we create a shell.nix in the project directory:

with import <nixpkgs> {};
stdenv.mkDerivation {
  name = "env";
  buildInputs = [
    ruby.devEnv
    git
    sqlite
    libpcap
    postgresql
    libxml2
    libxslt
    pkg-config
    bundix
    gnumake
  ];
}

Build Gemfile.lock and gemset.nix

$ nix-shell
$ bundle install      # generates Gemfile.lock
$ bundix              # generates gemset.nix

Build default.nix

This will be the package configuration:

{ stdenv, bundlerEnv, ruby }:
let
  # the magic which will include gemset.nix
  gems = bundlerEnv {
    name = "beef-env";
    inherit ruby;
    gemdir  = ./.;
  };
in stdenv.mkDerivation {
  name = "beef";
  src = ./.;
  buildInputs = [gems ruby];
  installPhase = ''
    mkdir -p $out/{bin,share/beef}
    cp -r * $out/share/beef
    bin=$out/bin/beef
# we are using bundle exec to start in the bundled environment
    cat > $bin <<EOF
#!/bin/sh -e
exec ${gems}/bin/bundle exec ${ruby}/bin/ruby $out/share/beef/beef "\$@"
EOF
    chmod +x $bin
  '';
}

Build the package

$ nix-build -E '((import <nixpkgs> {}).callPackage (import ./default.nix) { })' --keep-failed
....
do_sqlite3 build FAILED!

Our Problem is that do_sqlite3 wants to build native extensions and requires sqlite as dependency. There are two ways to solve this issue:

  1. add a global override to your nixpkgs
  2. set the gemConfig for the bundleEnv manually

Adding a global override for a gem

We edit: <nixpkgs/pkgs/development/ruby-modules/gem-config/default.nix:

{
   ...
   do_sqlite3 = attrs: {
     buildInputs = [ sqlite ];
   };
   ...
}


After this change we build the package again.

Defining groups

Sophisticated applications use groups to organize their gems like development, test and production. bundlerEnv only makes the default group available in the environment, that is all gems which are not in a group. To make other groups available, they need to be provided as an array. Don't forget to include the default group.

Example:

  gems = pkgs.bundlerEnv {
    name = "exampleApp";
    inherit ruby;
    gemfile = ./Gemfile;
    lockfile = ./Gemfile.lock;
    gemset = ./gemset.nix;
    groups = [ "default" "production" "development" "test" ];
  };

set the local gemConfig

TODO: also merge with the defaultGemConfig somehow

Using Bundler 2

Bundler 2 comes included with Ruby, so instead of importing ruby.devEnv import Ruby and Bundix separately.