Change:
I am trying to compile a project which (among other things) uses emscripten. I have created a custom file to create a development environment for the project. Executing the makefile fails when it gets to compiling the emscripten part of the project with the following error message: The project makes use of the open source project imgui. One of it's examples can be used to reproduce the error message. a file named with the following contents: The command succeeds resulting in a compiled executable of the example project. The execution of fails with the following error: During building of the example project make tries to execute the command: which fails with the error: system: host os: multi-user?: sandbox: version: channels(root): channels(mbust): nixpkgs:
Emscripten's compilation model clashes a bit with nix. For obvious reasons, emscripten requires wasm-compiled libc and libc++ libraries. Vanilla emscripten compiles these libraries on demand when they are first needed (this is called caching, and the compiled library is stored in the cache directory). In nix, this approach is very unsatisfactory because it means that emscripten would recompile libc again from scratch in every derivation that uses emscripten (because using an outside cache would of course make the derivation nonreproducible). Therefore we are creating a read-only cache during the emscripten build that contains "all possible" pre-compiled versions of libc and libc++ (there are different builds depending on whether you exceptions enabled or not, etc.). Sometimes we are missing one such combination, maybe this is the case here.
Thanks to for providing me with a quick-fix for this: I see how this approach is necessary to provide an experience that is satisfactory for nixos. However, doesn't emscripten also cache all libraries that the compiled sources link against? And if that is the case, doesn't that mean that a mutable cache location is still needed, although most common libraries are already provided by the readonly cache? Whatever the case, I am personally not trying to create a nixos package, but instead want to use emscripten on the command line. The above commands provide a way to make emscripten work on the command line by changing the cache to a mutable location. Could this behavior perhaps be implemented into the package so that using emscripten in private projects does not fail with cryptic error messages?
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
To the best of my knowledge, no, it doesn't. It only caches libc and libc++. You are responsible to provide other libraries (like you would with for a native target). This is an interesting idea. Maybe we should just add a line to check if there is a precompiled file available. (That is, first try the emscripten package and then fall back to the emscripten cache in the home directory.)
Good suggestion. I must admit that I am looking at this from a pure user perspective. I just expect the commands to work as the would on any other distribution. I know almost nothing about what's going on behind the scenes. But from what you are saying it sounds like the problem isn't with nixos but with emscripten itself. Almost all other Unix tools that have config or cache files somewhere usually have a system wide and a user specific config, so why shouldn't emscripten.
I marked this as stale due to inactivity. &rarr;
Note that attempts to resolve this by just creating a local dot directory for each package. I'm not sure how else this could be addressed with a more global system-wide cache given the restrictions on previous derivations being writable.
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
This worked for me:
This issue has been mentioned on NixOS Discourse. There might be relevant details there:

Discussion:
<del> { pkgs, lib, emscripten, python2 }: </del> <ins> { pkgs, lib, emscripten, python3 }: </ins> { buildInputs ? [], nativeBuildInputs ? []

pname = "emscripten-${lib.getName args}"; version = lib.getVersion args; <del> buildInputs = [ emscripten python2 ] ++ buildInputs; nativeBuildInputs = [ emscripten python2 ] ++ nativeBuildInputs; </del> <ins> buildInputs = [ emscripten python3 ] ++ buildInputs; nativeBuildInputs = [ emscripten python3 ] ++ nativeBuildInputs; </ins> # fake conftest results with emscripten's python magic EMCONFIGURE_JS=2;

emconfigure ./configure --prefix=$out <ins> mkdir -p .emscriptencache export EM_CACHE=$(pwd)/.emscriptencache </ins> runHook postConfigure '';

runHook preBuild HOME=$TMPDIR emmake make runHook postBuild

propagatedBuildInputs = [ zlib ]; configurePhase = '' HOME=$TMPDIR <ins> mkdir -p .emscriptencache export EM_CACHE=$(pwd)/.emscriptencache </ins> emcmake cmake . $cmakeFlags -DCMAKE_INSTALL_PREFIX=$out -DCMAKE_INSTALL_INCLUDEDIR=$dev/include ''; checkPhase = ''

autoreconfPhase = "echo autoreconfPhase not used..."; configurePhase = '' HOME=$TMPDIR <ins> mkdir -p .emscriptencache export EM_CACHE=$(pwd)/.emscriptencache </ins> emconfigure ./configure --prefix=$out --without-python ''; checkPhase = ''

sed -e "s/$(JSONC_LDFLAGS) $(ZLIB_LDFLAGS) $(LIBXML20_LDFLAGS)/$(JSONC_LDFLAGS) $(LIBXML20_LDFLAGS) $(ZLIB_LDFLAGS) /g" -i Makefile.emEnv # https://gitlab.com/odfplugfest/xmlmirror/issues/11 sed -e "s/-o fastXmlLint.js/-s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' -o fastXmlLint.js/g" -i Makefile.emEnv <ins> mkdir -p .emscriptencache export EM_CACHE=$(pwd)/.emscriptencache </ins> ''; buildPhase = ''

buildInputs = old.buildInputs ++ [ pkg-config ]; # we need to reset this setting! NIX_CFLAGS_COMPILE=""; <del> configurePhase = '' # FIXME: Some tests require writing at $HOME HOME=$TMPDIR runHook preConfigure #export EMCC_DEBUG=2 emconfigure ./configure --prefix=$out --shared runHook postConfigure ''; </del> dontStrip = true; outputs = [ "out" ]; buildPhase = ''

echo "Compiling a custom test" set -x emcc -O2 -s EMULATE_FUNCTION_POINTER_CASTS=1 test/example.c -DZ_SOLO  <del> -L. libz.so.${old.version} -I . -o example.js </del> <ins> -L. libz.a -I . -o example.js </ins> echo "Using node to execute the test" ${pkgs.nodejs}/bin/node ./example.js