Project aims to provide solution to
- develop entire Ajax application in Haskell
Previous version of project is located at vir.mskhug.ru.
Native Only Quick Start
Installing the compiler will take a while. If you just want to try out some of the examples and perhaps make your own HTML based client app then check out the low level WebKitGtk DOM bindings. This should give you everything you need to build and run the GHCJS examples as native Haskell applications.
sudo apt-get install libwebkitgtk-dev cabal install gtk2hs-buildtools darcs get http://patch-tag.com/r/hamish/webkit cd webkit cabal install cd .. git clone https://github.com/ghcjs/ghcjs-dom.git cd ghcjs-dom cabal install cd .. git clone https://github.com/ghcjs/ghcjs-examples.git cd ghcjs-examples/webkit-sodium cabal install cd ../ghcjs-hello cabal install ghcjs-hello
This version of GHCJS can be built stand alone or integrated into GHC. You can install both (if you know you want both do Integrated first).
- A full GHC that also outputs .js files and .jsexe directories when you build.
- A patched Cabal that installs the .js files along with the .hi ones.
- Takes a while to install (mostly just follow the regular GHC build instructions).
- Uses GHC API to make a ghcjs executable.
- Quicker to install (because you don't have actually build 7.4).
- Good for trying out changes in the code generator itself.
- Still requires some messing with GHC source.
- Google Closure Compiler https://developers.google.com/closure/compiler/
- Google Closure Library https://developers.google.com/closure/library/
- Java (to run the Closure Compiler)
- GHC install capable of building GHC 7.4.1
- OS X 10.7 using 32bit GHC 7.4.1 to build 32bit GHC
- Ubuntu 12.04 64bit VM with 3.5GB of system RAM using 64bit GHC 7.4.1 to build 64bit GHC
Getting The Source
git clone https://github.com/ghcjs/ghc cd ghc git checkout ghc-7.4 ./sync-all -r https://github.com/ghc get ./sync-all -r https://github.com/ghc get ./sync-all -r https://github.com/ghc get ./sync-all -r https://github.com/ghc get ./sync-all -r https://github.com/ghcjs --ghcjs get ./sync-all checkout ghc-7.4
(I find the gets from github often fail hence the 4 of them)
Build GHC as per the normal instructions (remember you can use this GHC to build binaries too).
Typical install goes something like this.
cp mk/build.mk.sample mk/build.mk perl boot ./configure --prefix=$HOME/ghcjs make make install hash -r
That last step takes a long time. To use this compiler add $HOME/ghcjs/bin to your path ahead of any other ghc.
You should be able to switch back to your main compiler at any point by simply not including this in you path.
User cabal packages are installed to something like
Installing cabal-install with GHCJS
You need to make a version of cabal-install that uses the new Cabal package. So that which you run "cabal install" it will copy .js files and .jsexe directories to the install location.
export PATH=$HOME/ghcjs/bin:$PATH cabal install cabal-install --constraint='Cabal
There is a catch. Because your old cabal install installed the dependencies the .js files for these libraries will not have been installed. So you should unregister then so they will be installed again with the new cabal-install.
You can get a list of all the packages that were installed by runningghc-pkg list --user
The quickest way to do this delete the directory these are inrm -rf ~/ghcjs/lib/ghc-184.108.40.20620501
or you can unregister them using ghc-pkg something like thisghc-pkg unregister HTTP ghc-pkg unregister network ghc-pkg unregister parsec ghc-pkg unregister mtl ghc-pkg unregister transformers ghc-pkg unregister zlib ghc-pkg unregister random ghc-pkg unregister text ghc-pkg unregister time
Installing the GHCJS package
We still need to install GHCJS as well. This will include the stand alone compiler, but the integrated compiler just needs the ghcjs runtime system (rts) and the minifier (ghcjs-min) that are also installed.
You already have a clone of ghcjs inside the ghc folder, but we need to clone some others to build it.
Note: If you are using a 64bit GHC edit ghc/compiler/ghcjs/rts/rts-options.js and change WORD_SIZE_IN_BITS from 32 to a 64 before installing.git clone email@example.com:ghcjs/ghcjs-closure.git cd ghcjs-closure cabal install cd .. git clone firstname.lastname@example.org:ghcjs/ghcjs-hterm.git cd ghcjs-hterm/chromeapps/hterm cabal install cd ../../.. git clone email@example.com:ghcjs/source-map.git cd source-map cabal install cd .. cd ghc/compiler/ghcjs cabal install
Installing and running an application
First build the application as you normally would. Here are the instructions that you need do build the ghcjs-hello example (they work with a native compiler too).sudo apt-get install libwebkitgtk-dev darcs get http://patch-tag.com/r/hamish/webkit cd webkit cabal install cd .. git clone https://github.com/ghcjs/ghcjs-dom.git cd ghcjs-dom cabal install cd .. git clone https://github.com/ghcjs/ghcjs-examples.git cd ghcjs-examples/webkit-sodium cabal install cd ../ghcjs-hello cabal install ghcjs-hello
Then run ghcjs-min on the .jsexe this will have installed (allong side your normal executable)ghcjs-min ~/.cabal/bin/ghcjs-hello.jsexe
On OS X it will be something like this...ghcjs-min ~/Library/Haskell/ghc-220.127.116.1120701/lib/ghcjs-hello-0.0.1/bin/ghcjs-hello.jsexe
I find the easiest way to do this is to use apache with the FollowSymlinks options (not always on by default).
On Linux...cd ~/public_html ln -s ../.cabal ghcjs
On OS X you might need something like this...cd ~/Sites mkdir ghcjs mkdir ghcjs/share mkdir ghcjs/bin ln -s ../Library/Haskell/ghc-18.104.22.16820701/lib/ghcjs-0.1.0/share ghcjs/share/ghcjs-0.1.0 ln -s ../Library/Haskell/ghc-22.214.171.12420701/lib/ghcjs-closure-0.1.0.0/share ghcjs/share/ghcjs-closure-0.1.0.0 ln -s ../Library/Haskell/ghc-126.96.36.19920701/lib/ghcjs-hterm-0.1.0.0/share ghcjs/share/ghcjs-hterm-0.1.0.0 ln -s ../Library/Haskell/ghc-188.8.131.5220701/lib/ghcjs-hello-0.0.1/bin/ghcjs-hello.jsexe ghcjs/bin/
ghcjs-min will set up an index.html file (if one does not already exist in the .jsexe) that will run the app with hterm.http://127.0.0.1/~hamish/ghcjs/bin/ghcjs-hello.jsexe
You can run the unminified version using hterm.htmlhttp://127.0.0.1/~hamish/ghcjs/bin/ghcjs-hello.jsexe/hterm.html
If you don't want the overhead of hterm then there is a version that sends stdout to the console (and does not currently support stdin)http://127.0.0.1/~hamish/ghcjs/bin/ghcjs-hello.jsexe/console.html
If you want to minify the console.html version then run (and make it the one index.html uses then run)...ghcjs-min ~/.cabal/bin/freecell.jsexe ~/.cabal/bin/freecell.jsexe/console.js
The stand-alone compiler is an attempt to make GHCJS easier to use and install. It does not require you to replace your existing GHC. GHCJS stand-alone has its own package database in
~/.ghcjs/and its own programs
ghcjs-cabalto manage and install packages.
The stand-alone version is currently experimental, and the linker might not work yet. Cabal-dev is also unsupported at this point.
ghcjs-htermfrom their respective repositories
Now install GHCJS itself (assuming you use ghc 7.4.2 for building ghcjs):
$ git clone https://github.com/ghcjs/ghcjs.git $ cd ghcjs $ cabal install $ cd ..
Make sure that the directory containing the
ghcjs-cabalprograms is in your PATH before proceeding:
$ wget http://www.haskell.org/ghc/dist/7.4.2/ghc-7.4.2-src.tar.bz2 $ tar -xjvf ghc-7.4.2-src.tar.bz2 $ cd ghc-7.4.2 $ ./configure $ make -j4 $ ghcjs-boot $ cd ..
You should now have a working
ghcjsinstallation with the
integer-gmppackages installed, check with:
$ ghcjs-pkg list
Differences from old version
vir.mskhug.ru contains the first implementation of the idea. This version is a rewrite that inherit little code from previous version. The differences are the following.
integer-gmp (using goog.math.Integer)
Function level linker
File Input (uses HTTP and is text only)
More closure compiler friendly output
Foreign function interface is not supported. Only minimum of primitive operations is supported.
Tail recursion optimization is on by default.
If you don't want it use
$ ghcjs --calling-convention=plain
Reading The Code
Many of the names used have been shortened to a single character to reduce the size of the java script. Here is a key so you can work out what they do.
Some functions include "info" strings that to try to make debugging easier (controlled with the HS_DEBUG flag). Also some of the functions have a list of things to keep alive with the thunk. This is also striped out if you disable support for finalizers and weak pointers (controlled with the HS_WEAKS flag). It is a nice feature of the Closure Compiler that if you pass more parameters than the function needs it will remove them from the call site.
|$f||function (first param is the arity)|
|$R and $r||are short for return|
|$M||evaluates its first param (if not already evaluated) and and passes the result to the function provided|
|$A||evaluates if not already evaluated and returns the result|
|.C||calls the function with the list of arguments and passes the result to the function provided|
|.J||jump t a function|