Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emscripten toolchain #16208

Merged
merged 1 commit into from
Jul 4, 2016
Merged

emscripten toolchain #16208

merged 1 commit into from
Jul 4, 2016

Conversation

qknight
Copy link
Member

@qknight qknight commented Jun 13, 2016

status

THIS MAJORED NOW INTO A PULL REQUEST

what is this?

this branch contains a emscripten based toolchain for nix.

nix-env -I nixpkgs=. -f default.nix -iA emscriptenPackages.libz && nix-env -I nixpkgs=. -f default.nix -iA emscriptenPackages.json_c && nix-env -I nixpkgs=. -f default.nix -iA emscriptenPackages.libxml2 && nix-env -I nixpkgs=. -f default.nix -iA emscriptenPackages.xmlmirror


meta = {
# Add default meta information
platforms = lib.platforms.all;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also set hydraPlatforms = []; to stop hydra from spawning 3x jobs for each emscripten package.

Copy link
Member Author

@qknight qknight Jun 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add that
added

@qknight
Copy link
Member Author

qknight commented Jun 26, 2016

@Profpatsch, @matthewbauer
some updates on the toolchain. libz, json_c and libxml2 now compile to javascript using this toolchain!

@qknight
Copy link
Member Author

qknight commented Jun 27, 2016

TODOs left until merge request:

  • we need a patch on emscripten to get rid of this requirement:

    HOME=$TMPDIR

  • xmlmirror must be compiling, but not packaged yet and ATM it does not compile anymore, see https://gitlab.com/odfplugfest/xmlmirror

  • consider profpatsch's ideas regarding toolchain design:

    • current implementation is analogous to the now obsoleted goPackages
    • profpatsch's idea is to define a new system = "emscripten"; which is probably simpler in design yet providing the same features needed

compiling xmlmirror

xmlmirror's nix-shell build environment fails currently, no idea what causes this:

nix-shell -A emEnv

vs

nix-shell -A emEnv -I nixpkgs=/home/joachim/Desktop/projects/nixos/nixpkgs

emcc 1.35.4

emcc -O3 -Wall -pedantic -Wextra `pkg-config json-c --cflags` `pkg-config zlib --cflags` `pkg-config libxml-2.0 --cflags` \                                                                                 

fastXmlLint.c:275:15: warning: unused parameter 'argc' [-Wunused-parameter]                           
int main (int argc, const char * argv[]) {                                                            
              ^                                                                                       
fastXmlLint.c:275:34: warning: unused parameter 'argv' [-Wunused-parameter]                           
int main (int argc, const char * argv[]) {                                                            
                                 ^                                                                    
2 warnings generated.                                                                                 
# https://github.com/kripken/emscripten/issues/2872
# so -s EMULATE_FUNCTION_POINTER_CASTS=1
emcc -O3 -Wall -pedantic -Wextra -std=gnu1x fastXmlLint.o  `pkg-config json-c --libs` `pkg-config zlib --libs` `pkg-config libxml-2.0 --libs`\                                                              
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)                                                                    
error: Unknown attribute kind (48)
error: Unknown attribute kind (48)
error: Unknown attribute kind (48)
error: Unknown attribute kind (48)
error: Unknown attribute kind (48)
warning: unresolved symbol: xmlParseMemory
warning: unresolved symbol: xmlRelaxNGNewParserCtxt
warning: unresolved symbol: xmlSchemaParse
warning: unresolved symbol: xmlLineNumbersDefault
warning: unresolved symbol: xmlRelaxNGNewValidCtxt
warning: unresolved symbol: xmlSchemaNewParserCtxt
warning: unresolved symbol: xmlFreeDoc
warning: unresolved symbol: xmlSchemaNewValidCtxt
warning: unresolved symbol: xmlSchemaValidateDoc
warning: unresolved symbol: xmlRelaxNGValidateDoc
warning: unresolved symbol: xmlSchemaNewMemParserCtxt
warning: unresolved symbol: xmlSetStructuredErrorFunc
warning: unresolved symbol: xmlRelaxNGParse
warning: unresolved symbol: xmlRelaxNGNewMemParserCtxt
warning: unresolved symbol: xmlSchemaFreeValidCtxt
wrote symbol map file to fastXmlLint.js.symbols
Traceback (most recent call last):
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/bin/emcc", line 1579, in <module>
    flush_js_optimizer_queue()
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/bin/emcc", line 1482, in flush_js_optimizer_queue
    run_passes(chunks[0], title, just_split=False, just_concat=False)
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/bin/emcc", line 1455, in run_passes
    final = shared.Building.js_optimizer(final, passes, debug_level >= 4, js_optimizer_extra_info, just_split=just_split, just_concat=just_concat)
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/share/emscripten/tools/shared.py", line 1651, in js_optimizer
    ret = js_optimizer.run(filename, passes, NODE_JS, debug, extra_info, just_split, just_concat)
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/share/emscripten/tools/js_optimizer.py", line 538, in run
    return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, source_map, extra_info, just_split, just_concat))
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/share/emscripten/tools/tempfiles.py", line 64, in run_and_clean
    return func()
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/share/emscripten/tools/js_optimizer.py", line 538, in <lambda>
    return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, source_map, extra_info, just_split, just_concat))
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/share/emscripten/tools/js_optimizer.py", line 448, in run_on_js
    filenames = [run_on_chunk(command) for command in commands]
  File "/nix/store/65d0l615r23k5n3g6pyd3chm1pj4620b-emscripten-1.35.4/share/emscripten/tools/js_optimizer.py", line 276, in run_on_chunk
    proc = subprocess.Popen(command, stdout=subprocess.PIPE)
  File "/nix/store/34sscviv2lpz6vr308gg99rdc2hbhlis-python-2.7.11/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/nix/store/34sscviv2lpz6vr308gg99rdc2hbhlis-python-2.7.11/lib/python2.7/subprocess.py", line 1335, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
Makefile.emEnv:16: die Regel für Ziel „fastXmlLint“ scheiterte
make: *** [fastXmlLint] Fehler 1

emcc 1.36.4

emcc -O3 -Wall -pedantic -Wextra `pkg-config json-c --cflags` `pkg-config zlib --cflags` `pkg-config libxml-2.0 --cflags` \
        -c fastXmlLint.c\
        -s AGGRESSIVE_VARIABLE_ELIMINATION=1 \
        --llvm-lto 3 \
        -o fastXmlLint.o 
fastXmlLint.c:275:15: warning: unused parameter 'argc' [-Wunused-parameter]
int main (int argc, const char * argv[]) {
              ^
fastXmlLint.c:275:34: warning: unused parameter 'argv' [-Wunused-parameter]
int main (int argc, const char * argv[]) {
                                 ^
2 warnings generated.
# https://github.com/kripken/emscripten/issues/2872
# so -s EMULATE_FUNCTION_POINTER_CASTS=1
emcc -O3 -Wall -pedantic -Wextra -std=gnu1x fastXmlLint.o  `pkg-config json-c --libs` `pkg-config zlib --libs` `pkg-config libxml-2.0 --libs`\
        -s EXPORTED_FUNCTIONS="['_validate', '_set_schema', '_my_echo', '_set_schema_file', \
                '_set_relaxNG_schema', '_set_relaxNG_schema_file', '_validate_NG']" \
        -s ASSERTIONS=2 --emit-symbol-map  \
        -s EMULATE_FUNCTION_POINTER_CASTS=1 \
        --memory-init-file 0 \
        --pre-js pre.js \
        --memory-init-file 1 \
        -s TOTAL_MEMORY=234217728 \
        --llvm-lto 3 \
        --closure 0 \
        -o fastXmlLint.js
wrote symbol map file to fastXmlLint.js.symbols
Traceback (most recent call last):
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/bin/emcc", line 13, in <module>
    emcc.run()
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/emcc.py", line 1772, in run
    JSOptimizer.flush()
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/emcc.py", line 1669, in flush
    run_passes(chunks[0], title, just_split=False, just_concat=False)
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/emcc.py", line 1642, in run_passes
    final = shared.Building.js_optimizer(final, passes, debug_level >= 4, JSOptimizer.extra_info, just_split=just_split, just_concat=just_concat)
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/tools/shared.py", line 1744, in js_optimizer
    ret = js_optimizer.run(filename, passes, NODE_JS, debug, extra_info, just_split, just_concat)
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/tools/js_optimizer.py", line 544, in run
    return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, source_map, extra_info, just_split, just_concat))
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/tools/tempfiles.py", line 64, in run_and_clean
    return func()
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/tools/js_optimizer.py", line 544, in <lambda>
    return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, source_map, extra_info, just_split, just_concat))
  File "/nix/store/l74gmdpfq3r9y2rqak54706lcy18yjzl-emscripten-1.36.4/share/emscripten/tools/js_optimizer.py", line 446, in run_on_js
    filenames = pool.map(run_on_chunk, commands, chunksize=1)
  File "/nix/store/rqca003m6hmbfq352mvy0jadwyw51j81-python-2.7.11/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/nix/store/rqca003m6hmbfq352mvy0jadwyw51j81-python-2.7.11/lib/python2.7/multiprocessing/pool.py", line 567, in get
    raise self._value
OSError: [Errno 2] No such file or directory
Makefile.emEnv:16: die Regel für Ziel „fastXmlLint“ scheiterte
make: *** [fastXmlLint] Fehler 1

@qknight
Copy link
Member Author

qknight commented Jun 27, 2016

@Profpatsch

why can't i move the autoreconfHook dependency from em-modules/generic/default.nix into emscripten-packages.nix like below:

em-modules/generic/default.nix

nativeBuildInputs = [ emscripten ] ++ nativeBuildInputs ++ [ autoreconfHook ];

into

emscripten-packages.nix

  # works
  libxml2 = (pkgs.libxml2.override {
    stdenv = emscriptenStdenv;
    supportPython = false;
  }).overrideDerivation
          (old: { 
                buildInputs = old.buildInputs ++ [ libz pkgconfig ];
                nativeBuildInputs = old.nativeBuildInputs ++ [ autoreconfHook ];
                postPatch = "patch -R < " + fetchpatch {
                  name = "schemas-validity.patch";
                  url = "https://git.gnome.org/browse/libxml2/patch/?id=f6599c5164";
                  sha256 = "0i7a0nhxwkxx6dkm8917qn0bsfn1av6ghg2f4dxanxi4bn4b1jjn";
                };
          });   

error

➜  nixpkgs git:(emscripten_toolchain) ✗ nix-env -I nixpkgs=/home/joachim/Desktop/projects/nixos/nixpkgs -f default.nix -iA emscriptenPackages.libxml2 --show-trace            ~/Desktop/projects/nixos/nixpkgs

replacing old ‘emscripten-libxml2-2.9.4’
installing ‘emscripten-libxml2-2.9.4’
error: while evaluating the attribute ‘nativeBuildInputs’ of the derivation ‘emscripten-libxml2-2.9.4’ at /home/joachim/Desktop/projects/nixos/nixpkgs/pkgs/development/em-modules/generic/default.nix:22:3:
undefined variable ‘autoreconfHook’ at /home/joachim/Desktop/projects/nixos/nixpkgs/pkgs/top-level/emscripten-packages.nix:66:64

EDIT:

works with this:

  buildInputs = old.buildInputs ++ [ autoreconfHook pkgconfig zlib  ];
  nativeBuildInputs = old.nativeBuildInputs ++ [ zlib pkgconfig ];

@qknight
Copy link
Member Author

qknight commented Jun 28, 2016

@matthewbauer
@Profpatsch

after fixing some final issues and packaging xmlmirror we now can say: it works!

@qknight qknight changed the title backup of emscripten toolchain work emscripten toolchain Jul 1, 2016
@matthewbauer
Copy link
Member

@qknight
Copy link
Member Author

qknight commented Jul 2, 2016

@matthewbauer
could you please review this once more? it builds all 4 targets on my system successfully.

@matthewbauer
Copy link
Member

matthewbauer commented Jul 2, 2016

Here's the error I'm getting from nix-build -A emscriptenPackages.libz:

/usr/bin/libtool: file: inffast.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: inflate.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: inftrees.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: trees.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: zutil.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: compress.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: uncompr.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: gzclose.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: gzlib.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: gzread.o is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: gzwrite.o is not an object file (not allowed in a library)
Makefile:128: recipe for target 'libz.a' failed
make: *** [libz.a] Error 1

@qknight
Copy link
Member Author

qknight commented Jul 2, 2016

@matthewbauer
the error above is on darwin, so nixpkgs on mac os x, right?

@qknight qknight force-pushed the emscripten_toolchain branch 2 times, most recently from 549b0b5 to 2c6c655 Compare July 3, 2016 09:32
@qknight
Copy link
Member Author

qknight commented Jul 3, 2016

before final merge i would like to introduce:

@qknight qknight force-pushed the emscripten_toolchain branch 4 times, most recently from e54f913 to e3d8a59 Compare July 3, 2016 23:46
@qknight
Copy link
Member Author

qknight commented Jul 3, 2016

@matthewbauer
added unit test for libxml2

i think it is ready for merge. i really would like to have some feedback before doing so.

# fake conftest results with emscripten's python magic
EMCONFIGURE_JS=2;

configurePhase = args.configurePhase or ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those phases will of course be overwritten by existing phases.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are referring to:

  • configurePhase
  • buildPhase
  • checkPhase

not sure what you mean with that, but this is just a default implementation which should be overriden intentionally by emscriptionPackages.

@matthewbauer
Copy link
Member

Looks good to me now.

example usage:

- nix-env -I nixpkgs=../somewhere/nixpkgs -f default.nix -iA emscriptenPackages.libxml2
- nix-env -I nixpkgs=../somewhere/nixpkgs -f default.nix -iA emscriptenPackages.json_c
- nix-env -I nixpkgs=../somewhere/nixpkgs -f default.nix -iA emscriptenPackages.zlib
- nix-env -I nixpkgs=../somewhere/nixpkgs -f default.nix -iA emscriptenPackages.xmlmirror
@qknight qknight merged commit 4c4a63f into NixOS:master Jul 4, 2016
@CMCDragonkai
Copy link
Member

CMCDragonkai commented Sep 2, 2017

There should be some documentation on this emscripten packages and whether there are any package hooks to using emscripten to be concerned about. My experiments with this shows that when using something like emscriptenPackages.zlib, the results is that these directories gets produced:

nix/store/*-emscripten-zlib-*/
nix/store/*-emscripten-zlib-*-dev/
nix/store/*-emscripten-zlib-*-static/

As usual with emscripten, there are no shared objects, hence there is nothing in nix/store/*-emscripten-zlib-*/lib, even though this is added to the $NIX_LDFLAGS.

However there is a static library: nix/store/*-emscripten-zlib-*-static/lib/libz.a, furthermore this static archive is in fact llvm bitcode, and according to emscripten docs, this would be better nameed libz.bc not libz.a to avoid confusion.

The pkg-config supplied in nix/store/*-emscripten-zlib-*-dev/lib/pkgconfig/zlib.pc only shows this:

prefix=/nix/store/jv3ba7jvc43xdlgxl6120r8kny4c7p9q-emscripten-zlib-1.2.11
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
sharedlibdir=${libdir}
includedir=/nix/store/638qx68yv08zx7212d14wxm4myzlvwns-emscripten-zlib-1.2.11-dev/include

Name: zlib
Description: zlib compression library
Version: 1.2.11

Requires:
Libs: -L${libdir} -L${sharedlibdir} -lz
Cflags: -I${includedir}

Which doesn't mention the static directory at all, which I think means that uses of package config won't result in finding the necessary static library.

Overall I'm still not entirely sure how you're meant to build an emscripten package that relies on nixpkgs emscriptenPackages.zlib instead of using the zlib port (which does a remote download, which is bad). I suppose one could use the ${emscriptenPackages.zlib.static} to get the static directory, but shouldn't this be encoded into a package hook specific to emscripten builds? What if the package already has a configure script that looks for system provided zlib?

Further reading has led me to this: emscripten-core/emscripten#2486 Basically any generated package config files when using buildEmscriptenPackage/emscriptenStdenv should follow those standards.

@CMCDragonkai
Copy link
Member

CMCDragonkai commented Sep 2, 2017

This issue about the fact that shared objects and static archives being in separate directories is important: #12085

@mbodmer
Copy link

mbodmer commented Dec 20, 2018

Hi. I am not a nix expert, so please forgive if this question does seem too naive. I think it's great somebody started to bring packages for emscripten in. I do however wonder why it does not take the route other cross compiling takes in nixpkgs. Shouldn't "wasm" just be another targetPlatform as described here: https://nixos.org/nixpkgs/manual/#chap-cross ? What would be needed for this? Is this the right place to discuss this?

@qknight
Copy link
Member Author

qknight commented Dec 20, 2018

@mbodmer you can always start a better approach and create a PR. i'd in fact love that. i don't have the funding to look into a different approach ATM but also note that what we have already works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants