1{ lib, stdenv, fetchFromGitHub, python3, nodejs, closurecompiler
2, jre, binaryen
3, llvmPackages
4, symlinkJoin, makeWrapper, substituteAll
5, mkYarnModules
6}:
7
8stdenv.mkDerivation rec {
9 pname = "emscripten";
10 version = "2.0.27";
11
12 llvmEnv = symlinkJoin {
13 name = "emscripten-llvm-${version}";
14 paths = with llvmPackages; [ clang-unwrapped clang-unwrapped.lib lld llvm ];
15 };
16
17 nodeModules = mkYarnModules {
18 name = "emscripten-node-modules-${version}";
19 inherit pname version;
20 # it is vitally important the the package.json has name and version fields
21 packageJSON = ./package.json;
22 yarnLock = ./yarn.lock;
23 yarnNix = ./yarn.nix;
24 };
25
26 src = fetchFromGitHub {
27 owner = "emscripten-core";
28 repo = "emscripten";
29 sha256 = "1dpfib2nmbvskqlaqw3kvaay69qpa7d155hd4w05c2xgmahmrd4n";
30 rev = version;
31 };
32
33 nativeBuildInputs = [ makeWrapper ];
34 buildInputs = [ nodejs python3 ];
35
36 patches = [
37 (substituteAll {
38 src = ./0001-emulate-clang-sysroot-include-logic.patch;
39 resourceDir = "${llvmEnv}/lib/clang/${llvmPackages.release_version}/";
40 })
41 ];
42
43 buildPhase = ''
44 runHook preBuild
45
46 patchShebangs .
47
48 # fixes cmake support
49 sed -i -e "s/print \('emcc (Emscript.*\)/sys.stderr.write(\1); sys.stderr.flush()/g" emcc.py
50
51 # disables cache in user home, use installation directory instead
52 sed -i '/^def/!s/root_is_writable()/True/' tools/config.py
53 sed -i "/^def check_sanity/a\\ return" tools/shared.py
54
55 # required for wasm2c
56 ln -s ${nodeModules}/node_modules .
57
58 echo "EMSCRIPTEN_ROOT = '$out/share/emscripten'" > .emscripten
59 echo "LLVM_ROOT = '${llvmEnv}/bin'" >> .emscripten
60 echo "NODE_JS = '${nodejs}/bin/node'" >> .emscripten
61 echo "JS_ENGINES = [NODE_JS]" >> .emscripten
62 echo "CLOSURE_COMPILER = ['${closurecompiler}/bin/closure-compiler']" >> .emscripten
63 echo "JAVA = '${jre}/bin/java'" >> .emscripten
64 # to make the test(s) below work
65 # echo "SPIDERMONKEY_ENGINE = []" >> .emscripten
66 echo "BINARYEN_ROOT = '${binaryen}'" >> .emscripten
67
68 # make emconfigure/emcmake use the correct (wrapped) binaries
69 sed -i "s|^EMCC =.*|EMCC='$out/bin/emcc'|" tools/shared.py
70 sed -i "s|^EMXX =.*|EMXX='$out/bin/em++'|" tools/shared.py
71 sed -i "s|^EMAR =.*|EMAR='$out/bin/emar'|" tools/shared.py
72 sed -i "s|^EMRANLIB =.*|EMRANLIB='$out/bin/emranlib'|" tools/shared.py
73
74 runHook postBuild
75 '';
76
77 installPhase = ''
78 runHook preInstall
79
80 appdir=$out/share/emscripten
81 mkdir -p $appdir
82 cp -r . $appdir
83 chmod -R +w $appdir
84
85 mkdir -p $out/bin
86 for b in em++ em-config emar embuilder.py emcc emcmake emconfigure emmake emranlib emrun emscons emsize; do
87 makeWrapper $appdir/$b $out/bin/$b \
88 --set NODE_PATH ${nodeModules}/node_modules \
89 --set EM_EXCLUSIVE_CACHE_ACCESS 1 \
90 --set PYTHON ${python3}/bin/python
91 done
92
93 # precompile libc (etc.) in all variants:
94 pushd $TMPDIR
95 echo 'int main() { return 42; }' >test.c
96 for LTO in -flto ""; do
97 # wasm2c doesn't work with PIC
98 $out/bin/emcc -s WASM2C -s STANDALONE_WASM $LTO test.c
99
100 for BIND in "" "--bind"; do
101 for MT in "" "-s USE_PTHREADS"; do
102 for RELOCATABLE in "" "-s RELOCATABLE"; do
103 $out/bin/emcc $RELOCATABLE $BIND $MT $LTO test.c
104 done
105 done
106 done
107 done
108 popd
109
110 export PYTHON=${python3}/bin/python
111 export NODE_PATH=${nodeModules}/node_modules
112 pushd $appdir
113 python tests/runner.py test_hello_world
114 popd
115
116 runHook postInstall
117 '';
118
119 meta = with lib; {
120 homepage = "https://github.com/emscripten-core/emscripten";
121 description = "An LLVM-to-JavaScript Compiler";
122 platforms = platforms.all;
123 maintainers = with maintainers; [ qknight matthewbauer ];
124 license = licenses.ncsa;
125 };
126}