If you want to hack on GHCJS, please join our friendly community on IRC at #ghcjs
on freenode (You're also
welcome if you only use the compiler or just want to chat about it!). The channel can be quiet from time
to time, but with a little patience you should be able to find people to get you started or point you in
the right direction.
The repositories you will be interested in are:
-
https://github.com/ghcjs/ghcjs
The compiler itself, code generator, linker, test suite
examples:
- Executables (
src-bin
) - Main code generator (
src/Gen2/Generator.hs
) - Optimizer (
src/Gen2/Optimizer.hs
) - Linker (
src/Gen2/Linker.hs
) - Generated runtime code (
h$ap_x_y
etc): (src/Gen2/RtsApply.hs
)
- Executables (
-
https://github.com/ghcjs/shims
Implementation of much of the runtime system and JavaScript dependencies. Code from this repository is linked into the
lib.js
andlib1.js
files when generating a.jsexe
. Installed byghcjs-boot
, the default installation location is~/.ghcjs/version/ghcjs/shims
.examples:
- thread scheduler, MVar implementation (
src/thread.js
) - STM implementation (
src/stm.js
) - IO system (
pkg/base.js
) (buffered IO forputStrLn
etc) - Heap scanner for weak references and finalizers, finding deadlocks and heap profiling (
src/gc.js
) - package-specific dependencies (
pkg
), dependencies listed inpackagename.yaml
(temporary measure until Cabal supports JavaScript dependencies directly) - third party libraries (
lib
)
- thread scheduler, MVar implementation (
-
https://github.com/ghcjs/ghcjs-prim
GHCJS primitives used by the runtime system, some basic utilities for converting JS data (for packages that cannot depend on
ghcjs-base
) and Template Haskell communication code. This package is treated in a special way by the compiler, symbol names are not versioned, similar to wired-in packages. -
https://github.com/ghcjs/ghcjs-base
GHCJS base library, basic marshalling between JavaScript and Haskell data
If you've changed something that affects the code generated by GHCJS, you'll need to rebuild the base packages (reboot the compiler). Often,
a full reboot is not required. You can run a quick boot to install only the essential packages (e.g. base
, integer-gmp
, array
, but not ghcjs-base
).
Adjust the -j4
flag (number of concurrent jobs) for your system:
$ ghcjs-boot --dev --no-haddock --no-prof --quick -j4
After a change, please run the test suite to
check that it does not break anything. Install jsshell
and node.js first to make sure that the tests run correctly (js
and node
executables should
be in your PATH
)).
When the compiler has been booted, run cabal test
, or run the test program directly for more options:
$ ./dist/build/test/test --help
For example to run a specific test or tests that match a pattern:
$ ./dist/build/test/test -t pattern
New test cases, in particular if you add new features, are always welcome. The testrunner automatically picks up new tests
(.hs
files that start with a lowercase letter) in the existing categories.
If some change prevents your GHCJS from booting correctly, you can manually run boot steps to track down the problem.
First run ghcjs-boot
with the -v2
or -v3
options to get more information
about the problem. Then set some environment variables to make the compiler skip
the check that it's been booted:
$ export GHCJS_BOOTING=1
Additionally, if you are fixing a problem in stage 1 (before GHCJS has a working Cabal package):
$ export GHCJS_BOOTING_STAGE1=1
TODO add better instructions here
- link your program with
-debug
:ghcjs -debug -o test test.hs
, this adds debugging information to the generated code - get more information from the runtime system by enabling various tracing and logging options. See the code in the shims repository for more info. Examples:
-DGHCJS_LOG_BUFFER
: output log/trace messages to theh$logBuffer
variable instead of the console. useful in the browser to avoid overloading the console.-DGHCJS_TRACE_SCHEDULER
: messages from the thread scheduler-DGHCJS_TRACE_CALLS
: print all function calls from the main loop. warning: lots of output. Requires-debug
for name information-DGHCJS_TRACE_STACK
: print top of stack for every call in the main loop. warning: even more output-DGHCJS_TRACE_WEAK
: output related to weak references-DGHCJS_TRACE_STM
: output for software transactional memory-DGHCJS_TRACE_GC
: output garbage collector (heap scanner) related messages-DGHCJS_TRACE_PROF
: output profiling related messages
- see the utility programs in
utils
in the ghcjs repository for tools for inspecting object files, quickly bisecting bugs in the optimizer etc.
You can use the JavaScript profiler to get a basic idea where the majority of time in your program is spent. Non-exported
names (like stack frame functions) start with h$$
, scroll up in the code to find an exported name to which they belong.
Unfortunately due to Haskell's lazy evaluation and GHCJS's tail-call optimization, the information here is far less useful than GHC profiles for native code. Work on full profiling support has started. Cost centre stacks have been implemented and stack traces work, but there is no front end yet.