Ruby package guidelines

From ArchWiki
Arch package guidelines

32-bitCLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustShellVCSWebWine

This document covers standards and guidelines on writing PKGBUILDs for software that uses ruby.

Package naming

For libraries, use ruby-$_name (where $_name is the upstream project name). For applications, use the project name (without the ruby- prefix) and optionally add ruby-$_name to provides.

Build and tests

Ruby packages should be built from upstream sources as this provides a transparent chain of trust for the build. To ensure integration with the existing set of Ruby packages, it is expected to run tests using ruby-rake.

Note: To detect dependency changes in between releases of a project, have a close look at the .gemspec or Gemfile upon update.

Template

There are two ways of building a ruby project: gem (part of rubygems) based and rake (part of ruby-rake) based. The decision which to use depends on the upstream project.

Note: If the upstream project includes a native extension (i.e. a shared object file), that has to be compiled, use rake. For all other purposes gem should suffice.

Gem based build

PKGBUILD
prepare() {
  cd "$_name-$pkgver"
  # we do not do version pinning
  sed --regexp-extended 's,~>,>=,g' --in-place *.gemspec Gemfile Rakefile
  # lockfiles should be removed
  rm -fv Gemfile.lock
  # do not rely on Gemfiles (unless the project *really* needs it)
  rm -fv Gemfile
}

build() {
  cd "$_name-$pkgver"
  gem build "$_name.gemspec"
}

check() {
  cd "$_name-$pkgver"
  rake test
}

package() {
  local _gemdir="$(gem env gemdir)"

  cd "$_name-$pkgver"
  gem install \
    --local \
    --ignore-dependencies \
    --no-user-install \
    --install-dir "$pkgdir/$_gemdir" \
    --bindir "$pkgdir/usr/bin" \
    "$_name-$pkgver.gem"
  
  # remove unrepreducible files
  rm -frv \
    "$pkgdir/$_gemdir/cache/" \
    "$pkgdir/$_gemdir/gems/$_name-$pkgver/vendor/" \
    "$pkgdir/$_gemdir/doc/$_name-$pkgver/ri/ext/"
  
  find "$pkgdir/$_gemdir/gems/" \
    -type f \
    \( \
        -iname "*.o" -o \
        -iname "*.c" -o \
        -iname "*.so" -o \
        -iname "*.time" -o \
        -iname "gem.build_complete" -o \
        -iname "Makefile" \
    \) \
    -delete

  find "$pkgdir/$_gemdir/extensions/" \
    -type f \
    \( \
      -iname "mkmf.log" -o \
      -iname "gem_make.out" \
    \) \
    -delete
}

Rake based build

Note: Rake targets are named by the upstream project and therefore may differ from the example below. For reference have a look at how upstream builds their project in CI or at the output of rake --tasks.
PKGBUILD
prepare() {
  cd "$_name-$pkgver"
  # we do not do version pinning
  sed --regexp-extended 's,~>,>=,g' --in-place *.gemspec Gemfile Rakefile
  # lockfiles should be removed
  rm -fv Gemfile.lock
  # do not rely on Gemfiles (unless the project *really* needs it)
  rm -fv Gemfile
}

build() {
  cd "$_name-$pkgver"
  rake compile
  rake gem
}

check() {
  cd "$_name-$pkgver"
  rake test
}

package() {
  local _gemdir="$(gem env gemdir)"

  cd $_name-$pkgver
  gem install \
    --local \
    --ignore-dependencies \
    --no-user-install \
    --install-dir "$pkgdir/$_gemdir" \
    --bindir "$pkgdir/usr/bin" \
    "pkg/$_name-$pkgver.gem"
  
  # remove unrepreducible files
  rm -frv \
    "$pkgdir/$_gemdir/cache/" \
    "$pkgdir/$_gemdir/gems/$_name-$pkgver/vendor/" \
    "$pkgdir/$_gemdir/doc/$_name-$pkgver/ri/ext/"
  
  find "$pkgdir/$_gemdir/gems/" \
    -type f \
    \( \
        -iname "*.o" -o \
        -iname "*.c" -o \
        -iname "*.so" -o \
        -iname "*.time" -o \
        -iname "gem.build_complete" -o \
        -iname "Makefile" \
    \) \
    -delete

  find "$pkgdir/$_gemdir/extensions/" \
    -type f \
    \( \
      -iname "mkmf.log" -o \
      -iname "gem_make.out" \
    \) \
    -delete
}

See also