bucklescript自体をnixでbuild

1

ここ最近の自由研究としてbucklescript、厳密にはbs-platform自体をnixでbuildしようとてしました。

大変な部分もあって難航したが、一旦なんとかなったっぽいので公開します。

2

bs-platformは結構たくさんのツールチェーンの集合体なので、まず付属のOCamlをビルドしていきます。

ちょっとバージョンが古いのですがそこはまぁ取り組んでいた期間を想像してください。

あと、ビルド方法はいろんなところにいろんな手法が記述されていますが、CONTRIBUTING.mdを見るのが現状正しいです。

nixなのでopamは使いません。

{ stdenv, fetchFromGitHub, }:
let
  src = fetchFromGitHub {
    owner = "BuckleScript";
    repo = "bucklescript";
    rev = "484740cd56981130573efc81757c41f5662f4f0e";
    sha256 = "1mcz283jjwbwq52r51nzz5wjwc7y6g4fhgv0zbgs1wwp496mpjpy";
  };
in
stdenv.mkDerivation {
  version = "4.02.3";
  name = "ocaml-4.02.3+buckle-master";
  inherit src;
  configurePhase = ''
    cd vendor/ocaml
    ./configure -prefix $out
  '';
  buildPhase = ''
    make world.opt
  '';
  installPhase = ''
    make install
  '';

  meta = with stdenv.lib; {
    homepage = http://caml.inria.fr/ocaml;
    branch = "4.02";
    description = "Most popular variant of the Caml language";
    platforms = with platforms; linux ++ darwin;
  };
}

結構昔はgit submoduleになっていたのですが、現在はvendor/ocamlにcommitされています。 nixなので./configure -prefix $outをするのを忘れなければそんなに問題ないです

3

ここからが面倒でbsc.exeなどをビルドしていく上でopam install camlp4 cppoする必要がありますがopam抜きで済まします。

(ここに)https://github.com/NixOS/nixpkgs/blob/13882234569e75df7ecc39e97bdac98709b57530/pkgs/top-level/ocaml-packages.nix便利なツールがあるのでこれを使うといい感じになります。

しかしcamlp4OCamlのversionを見てDLしてくるようなnixが書かれているのが若干不安ですが一旦なんとかなりました。(要検証)

最終的に以下のようになります。

{ stdenv, fetchFromGitHub, callPackage, ninja, nodejs }:

let
  src = fetchFromGitHub {
    owner = "BuckleScript";
    repo = "bucklescript";
    rev = "484740cd56981130573efc81757c41f5662f4f0e";
    sha256 = "1mcz283jjwbwq52r51nzz5wjwc7y6g4fhgv0zbgs1wwp496mpjpy";
  };
  ocaml = callPackage ./ocaml.nix {};
  mkOcamlPackages =  (callPackage <nixpkgs/pkgs/top-level/ocaml-packages.nix> {}).mkOcamlPackages;
  ocamlPackages = mkOcamlPackages ocaml (self: super: { });
in
stdenv.mkDerivation rec {
    name = "bucklescript-${version}";
    version = "4.0.6";
    inherit src;
    buildInputs = [ ocaml ocamlPackages.cppo ocamlPackages.camlp4 ];
    phase = [ "buildPhase" "installPhase" ];
    buildPhase = ''
      mkdir -p $out
      cp -R lib jscomp Makefile bsconfig.json package.json $out
      cd $out
      make
      make install
      ln -s ${ninja}/bin/ninja $out/lib/ninja.exe
    '';
    installPhase = ''
      mkdir -p $out/bin
      ln -s $out/lib/bsb $out/bin/bsb
      ln -s $out/lib/bsc $out/bin/bsc
      ln -s $out/lib/bsrefmt $out/bin/bsrefmt
    '';
}

Makefile中に中間ファイルを容赦無くsrc中にぶっこんでくるので、一旦全て$outにcpするなど辛い構成になっています。

document中ではnpm -g install .するように書いてありますが、npmのinstall hookなどでアクロバットにninjaなどがdlしたりビルドしたりするためのものなので不要です。 突然pythonが要求されて何故?ってなります。 今回はnixpkgsからninjaを持ってきてlinkしていますが、若干versionがずれてしまうのできにする場合がninjaのversionを固定するようなnixが必要になります。

4

最終的なnixファイルを見るとそんなに辛そうに見えませんがビルド周りがイケてない場合、このファイルを各仮定でかなりのソースを読むことになります。 終わり。