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

Options to use an alternate compiler #12218

Closed
j-jorge opened this issue Sep 15, 2020 · 7 comments
Closed

Options to use an alternate compiler #12218

j-jorge opened this issue Sep 15, 2020 · 7 comments

Comments

@j-jorge
Copy link
Contributor

j-jorge commented Sep 15, 2020

This is more of a discussion than an issue.

At the time of this writing there are two main solutions to set the path to the clang compiler used by emcc:

  • set the LLVM_ROOT config variable (or EM_LLVM_ROOT environment variable) to point to the root of the LLVM installation,
  • or set the EMMAKEN_COMPILER environment variable to point to the compiler to use (i.e. the deprecated method).

I've found the first option to be very restrictive about the supported versions of Clang, mostly because -fignore-exceptions is passed by default to the compiler. This compilation flag is not available in old versions of Clang and the build will fail.

As I use Emscripten with a custom clang-based compiler a few versions behind upstream, I would like Emscripten to keep some flexibility on the backend compiler features.

For example, here's what I got trying to use the Clang compiler provided in Ubuntu. With the EMMAKEN_COMPILER way:

(1) First run to compile the system libraries with the default compiler.

# echo '' | EMMAKEN_COMPILER=/usr/bin/clang ./upstream/emscripten/em++ -x c++ - -o delme
shared:INFO: (Emscripten: config changed, clearing cache)
shared:INFO: (Emscripten: Running sanity checks)
clang: error: unknown argument: '-fignore-exceptions'
em++: error: '/usr/bin/clang -target wasm32-unknown-emscripten -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=2 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -nostdsysteminc -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include/libcxx -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/lib/libcxxabi/include -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include/compat -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include/libc -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/lib/libc/musl/arch/emscripten -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/local/include -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include/SSE -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include/neon -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/lib/compiler-rt/include -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/lib/libunwind/include -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/include -DEMSCRIPTEN -fignore-exceptions -x c++ -o delme - -Xclang -isystem/home/julien/emscripten/emsdk/upstream/emscripten/system/include/SDL -c -o /tmp/emscripten_temp_fmm0ti8t/-_0.o -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (1)

(2) Ok, it failed because Clang 10 does not know about -fignore-exceptions. Let's force -fexceptions:

$ echo '' | EMCC_CFLAGS=-fexceptions EMMAKEN_COMPILER=/usr/bin/clang ./upstream/emscripten/em++ -x c++ - -o delme
cache:INFO: generating system library: libc.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libcompiler_rt.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libcompiler_rt.a" for subsequent builds)
clang: warning: argument unused during compilation: '-fexceptions' [-Wunused-command-line-argument]
clang -cc1as: fatal error: error in backend: don't yet support defined globals
emcc: error: '/usr/bin/clang -target wasm32-unknown-emscripten -c -o /tmp/emscripten_temp_zvlm3csy/stack_ops.o -fexceptions /home/julien/emscripten/emsdk/upstream/emscripten/system/lib/compiler-rt/stack_ops.s -c -o /tmp/emscripten_temp_zvlm3csy/stack_ops.o -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-cxx-exceptions -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (1)

(3) No luck here. Use the default compiler to compile the system libraries.

$ echo '' | ./upstream/emscripten/em++ -x c++ - -o delme

cache:INFO: generating system library: libc.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libcompiler_rt.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libcompiler_rt.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc++-noexcept.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc++-noexcept.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc++abi-noexcept.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc++abi-noexcept.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libdlmalloc.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libdlmalloc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libpthread_stub.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libpthread_stub.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc_rt_wasm.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc_rt_wasm.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libsockets.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libsockets.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system asset: generated_struct_info.json... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/generated_struct_info.json" for subsequent builds)
cache:INFO:  - ok

(4) And then use the custom compiler to compile the actual program:

$ EMCC_CORES=1 EMMAKEN_COMPILER=/usr/bin/clang++ ./upstream/emscripten/em++ hello.cpp -fexceptions
cache:INFO: generating system library: libc++.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc++.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc++abi.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc++abi.a" for subsequent builds)
cache:INFO:  - ok

Sucess! I managed to compile my program with a custom compiler.

(5) Now see if we can do the same with LLVM_ROOT.

$ echo '' | EM_LLVM_ROOT=/usr/bin ./upstream/emscripten/em++ -x c++ - -o delme
em++: warning: LLVM version appears incorrect (seeing "10.0", expected "12.0") [-Wversion-check]
shared:INFO: (Emscripten: config changed, clearing cache)
shared:INFO: (Emscripten: Running sanity checks)
cache:INFO: generating system library: libc.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libcompiler_rt.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libcompiler_rt.a" for subsequent builds)
clang -cc1as: fatal error: error in backend: don't yet support defined globals
emcc: error: '/usr/bin/clang++ -target wasm32-unknown-emscripten -c -o /tmp/emscripten_temp_izgpfzci/stack_ops.o /home/julien/emscripten/emsdk/upstream/emscripten/system/lib/compiler-rt/stack_ops.s -c -o /tmp/emscripten_temp_izgpfzci/stack_ops.o -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (1)

The error is clear: error in backend: don't yet support defined globals, so I reuse the solution in (3); I use the default compiler to compile the system libraries.

(6) Then I try to compile my program:

$ EM_LLVM_ROOT=/usr/bin ./upstream/emscripten/em++ hello.cpp -fexceptions
em++: warning: LLVM version appears incorrect (seeing "10.0", expected "12.0") [-Wversion-check]
shared:INFO: (Emscripten: config changed, clearing cache)
shared:INFO: (Emscripten: Running sanity checks)
cache:INFO: generating system library: libc.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libcompiler_rt.a... (this will be cached in "/home/julien/emscripten/emsdk/upstream/emscripten/cache/wasm/libcompiler_rt.a" for subsequent builds)
clang -cc1as: fatal error: error in backend: don't yet support defined globals
emcc: error: '/usr/bin/clang++ -target wasm32-unknown-emscripten -c -o /tmp/emscripten_temp_1j_x9v50/stack_ops.o /home/julien/emscripten/emsdk/upstream/emscripten/system/lib/compiler-rt/stack_ops.s -c -o /tmp/emscripten_temp_1j_x9v50/stack_ops.o -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (1)

As you can see it recompiles the system libraries and we are back to the problem of the defined globals. I have no other solution to use another compiler.

What can I do to use a custom older compiler with LLVM_ROOT and a recent version of Emscripten?

@sbc100
Copy link
Collaborator

sbc100 commented Sep 15, 2020

The fundamental problem here is that emscripten only supports a single LLVM version at any given time.

You cannot expect to be able to use it with your system version of LLVM or with any version other than the one it is expecting.

I have an open issue to try to move towards supporting LLVM stable so that we can one day support your use case:
#11362

However as you can see libcompiler_rt uses a feature that clang 10 simply doesn't support. Your solution of trying to work around this by using your system compiler only for your user code could work but seems... dangerous. If you are using your own custom clang version for some reason presumably you also want to use it for the system libraries? The reason the this hack didn't work when you set EM_LLVM_ROOT is that emscripten detected this (correctly) as a change in your configuration and forced you to rebuild all your system libraries " (Emscripten: config changed, clearing cache)". The fact that changing EMMAKEN_COMPILER was not detected as a change in configuration as arguably a bug.

I'm am keen to help you find a solution. Perhaps we can work on #11362
? But I'm curious what you goal is? Is your goal just to use the system compiler and llvm 10? Or do you have a customized version of llvm you want to use that is non-standard?

@sbc100
Copy link
Collaborator

sbc100 commented Sep 15, 2020

One possible solution is to provide a way to override the (Emscripten: config changed, clearing cache) behaviour such that emscripten keeps that cache even though the config has changed..

@j-jorge
Copy link
Contributor Author

j-jorge commented Sep 15, 2020

But I'm curious what you goal is? Is your goal just to use the system compiler and llvm 10? Or do you have a customized version of llvm you want to use that is non-standard?

I have indeed an internal customized version of llvm with extra features that I want to be able to apply to my program :)

@sbc100
Copy link
Collaborator

sbc100 commented Sep 15, 2020

But I'm curious what you goal is? Is your goal just to use the system compiler and llvm 10? Or do you have a customized version of llvm you want to use that is non-standard?

I have indeed an internal customized version of llvm with extra features that I want to be able to apply to my program :)

Do you not also want those extra features when you compile the emscripten system libraries?

Would it be possible to rebase on top of LLVM latest? (I know that isn't always easy :)

@sbc100
Copy link
Collaborator

sbc100 commented Sep 15, 2020

I'm afraid the short answer is that we don't support this setup today. Its not unusual for emscripten to depend unconditionally on features in llvm tip-of-tree.

@j-jorge
Copy link
Contributor Author

j-jorge commented Sep 16, 2020

I'm closing this issue because the problem is already discussed in #11362, where this issue is already linked. No need to have two threads about it :)

@j-jorge j-jorge closed this as completed Sep 16, 2020
@j-jorge
Copy link
Contributor Author

j-jorge commented Sep 16, 2020

Do you not also want those extra features when you compile the emscripten system libraries?

No, these features have no impact on the system libraries, only for client code.

Would it be possible to rebase on top of LLVM latest? (I know that isn't always easy :)

Unfortunately it's impossible for me to rebase to latest :(

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

No branches or pull requests

2 participants