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