[Nix-dev] Announcing support for GHCJS
Bas van Dijk
v.dijk.bas at gmail.com
Thu Jan 8 10:52:32 CET 2015
Hi Oliver,
At work (I'm now at Lumi Guide) I currently use the following setup. I
use a Makefile which defines some convenient targets for building the
client and server and for entering shells for development:
Makefile:
# Builds the server.
.PHONY: server
server:
nix-build -I . packages.nix -A server
# Builds the Haskell (GHCJS) client (*.html / *.js):
.PHONY: client
client:
nix-build -I . packages.nix -A client
# Enters a shell which has access to all server dependencies
# (like python and the client):
.PHONY: server.dev
server.dev:
nix-shell -I . packages.nix -A server
# Enters a shell which has access to all client dependencies
# (like GHCJS, cabal-js, etc.):
.PHONY: client.dev
client.dev:
nix-shell -I . packages.nix -A client
Note that I have a clone of nixpkgs checked out as a git submodule in
the "nixpkgs" directory. I update nixpkgs every two weeks or so.
The top-level "packages.nix" file defines the server and client projects:
packages.nix:
{ originalPkgs ? import <nixpkgs> {} }:
let pkgs = import ./nix { pkgs = originalPkgs; }; in
rec {
client = pkgs.haskellPackages_ghcjs.callPackage ./client {
cabalInstall_HEAD =
pkgs.haskellPackages_ghcjs.ghc.ghc.parent.cabalInstall_HEAD;
...
server = pkgs.callPackage ./server { inherit client }
};
...
The client uses a regular cabal.mkDerivation but since it's called
with pkgs.haskellPackages_ghcjs.callPackage it uses GHCJS.
client/default.nix:
{
# Tools
cabal
, cabalInstall_HEAD
# Library dependencies
, aeson, attoparsec, blazeHtml, blazeReact
, either, ghcjsFfiqq, ghcjsJquery, httpTypes, languagePython, lens
, lumiFacilityCommon, networkUri, process, safe, scientific
, semigroups, systemFilepath, text, transformers
, unorderedContainers, vector, zenc, void
}:
cabal.mkDerivation (self: {
pname = "lumi-facility-client";
version = "0.0.1";
src = ./.;
isLibrary = false;
isExecutable = true;
buildDepends = [
aeson attoparsec blazeHtml blazeReact either ghcjsFfiqq ghcjsJquery
httpTypes languagePython lens networkUri process safe scientific
semigroups systemFilepath text transformers unorderedContainers vector
zenc void
];
buildTools = [
# The following is only needed when running in nix-shell to give
# access to cabal with GHCJS support.
#
# TODO (BvD): See if we can use a shell.nix file which uses
# haskellPackages_ghcjs.ghcWithPackages
# so that we don't need to use this hack...
cabalInstall_HEAD
];
preConfigure = ''
rm -r dist
# Remove symoblic link to locally build client. This prevents the
# link from being deployed.
rm ./static/hs
'';
postInstall = ''
mkdir $out/static
cp -r ./generated $out
cp ./static/{index.html,default.css,favicon.ico} $out/static
'';
meta = {
license = self.stdenv.lib.licenses.unfree;
platforms = self.ghc.meta.platforms;
};
})
"nix" is the directory below which all extensions to nixpkgs are defined:
nix/default.nix:
{ pkgs ? import <nixpkgs> {} }:
# This returns the set of packages from nixpkgs
# extended with packages defined by us.
let self = pkgs // {
callPackage = self.lib.callPackageWith self;
haskellPackages = import ./haskell pkgs.haskellPackages;
haskellPackages_ghcjs = import ./haskell pkgs.haskellPackages_ghcjs;
...
};
in self
"nix/haskell" is the directory below which all extensions to
haskellPackages are defined:
nix/haskell/default.nix:
# This function takes a haskellPackages collection like
# pkgs.haskellPackages or pkgs.haskellPackages_ghcjs and returns the
# same collection extended with our custom Haskell packages.
hsPkgs : hsPkgs.override {
extension = self: super: {
languagePython = self.callPackage ./language-python {};
zenc = self.callPackage ./zenc {};
ghcjsJquery = self.callPackage ./ghcjs-jquery {};
GenericPretty = self.callPackage ./GenericPretty {};
ghcjsFfiqq = self.callPackage ./ghcjs-ffiqq {};
blazeReact = self.callPackage ./blaze-react {};
};
}
Note that "nix/haskell/default.nix" can be used to extend both
pkgs.haskellPackages as well as pkgs.haskellPackages_ghcjs.
Note that I'm using Simon Meier's and Alex Sayer's awesome blaze-react
library. See [1] for a video tutorial on blaze-react. Here's the
derivation I use to build it:
nix/haskell/blaze-react/default.nix:
{ cabal, either, fetchgit, ghcjsFfiqq, lens
, mtl, prettyShow, text, time, transformers
, stdenv, nodePackages, writeTextFile
}:
let src = ./blaze-react;
# TODO (BvD): Once blaze-react stabilizes we should move to get
# the sources from git instead of using a git submodule:
#
# fetchgit {
# url = "https://github.com/LumiGuide/blaze-react.git";
# sha256 =
"a918fe77fb8b3fdd63a5ba5f20ad925a83f547492114b56170d35ba101ea52ba";
# rev = "1624db561f4153eaa8133b9b5f3047c7fea9c8be";
# };
version = "0.1.0.0";
in
cabal.mkDerivation (self: rec {
inherit src;
inherit version;
pname = "blaze-react";
isLibrary = true;
isExecutable = false;
buildDepends = [
either ghcjsFfiqq lens mtl prettyShow text time transformers
];
reactjsBindings = stdenv.mkDerivation {
name = "reactjs-bindings-${version}";
inherit src;
buildInputs = [ nodePackages.browserify nodePackages.react ];
builder = writeTextFile {
name = "reactjs-bindings-builder.sh";
text = ''
source $stdenv/setup
cd $src/reactjs-bindings
mkdir $out
browserify lib.require.js -o $out/lib.js
'';
};
};
preConfigure = ''
ln -s $reactjsBindings/lib.js reactjs-bindings/lib.js
'';
meta = {
description = "Experimental ReactJS bindings for GHCJS";
license = self.stdenv.lib.licenses.mit;
platforms = self.ghc.meta.platforms;
};
})
BTW doing client development with GHCJS and blaze-react is awesome!. I
used to be Haskell back-end developer at Better not just because I
really liked working on servers but also a bit because of fear of
loosing my sanity with JavaScript. Now that I can use Haskell and all
the goodies of GHC like threads, stm and a lot of excellent libraries
from hackage I'm quite enjoying being a front-end developer also :-)
Cheers,
Bas
[1] https://www.youtube.com/watch?v=4nTnC0t7pzY
On 6 January 2015 at 12:06, Oliver Charles <ollie at ocharles.org.uk> wrote:
> Ertugrul Söylemez <ertesx at gmx.de> writes:
>
>> Hi everybody,
>>
>>> I was going to try it out and found the compiler itself, but couldn't
>>> figure out how to make a derivation for a JS package. Is there any
>>> documentation on that? If not, in which files should I look? Something
>>> like ghcjsWithPackages and cabal.mkJsDerivation would be great.
>>
>> Nevermind, I think I got it.
>
> Could you update this thread with your solution, for posterity?
>
> -- ocharles
>
> _______________________________________________
> nix-dev mailing list
> nix-dev at lists.science.uu.nl
> http://lists.science.uu.nl/mailman/listinfo/nix-dev
>
More information about the nix-dev
mailing list