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

bug: Emscripten doesn't generate PIC libc #16680

Closed
hoodmane opened this issue Apr 8, 2022 · 20 comments
Closed

bug: Emscripten doesn't generate PIC libc #16680

hoodmane opened this issue Apr 8, 2022 · 20 comments

Comments

@hoodmane
Copy link
Contributor

hoodmane commented Apr 8, 2022

Tested

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.9-git (7e4a0ae4bdd99abbbf299c025aa2ce7b339c8521)
clang version 15.0.0 (https://github.com/llvm/llvm-project b2a7f1c3904ede781565c6ed772f155167aa8325)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/hood/Documents/programming/emsdk/upstream/bin

Example:
test.c:

int f(x){
	return x+4;
}
emcc -c test.c -o test.o -fPIC
emcc test.o -o test.so -sSIDE_MODULE=1 -lc

fails with:

wasm-ld: error: unable to find library -lc
emcc: error: '/src/emsdk/emsdk/upstream/bin/wasm-ld -o tst.so --whole-archive tst.o -lc -L/src/emsdk/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/pic --no-whole-archive -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --import-undefined --import-memory --strip-debug --export-all --no-gc-sections --experimental-pic -shared' failed (returned 1)
@hoodmane
Copy link
Contributor Author

hoodmane commented Apr 8, 2022

Or probably it makes no sense to link -lc against a side module and we should be filtering out?

@kripken
Copy link
Member

kripken commented Apr 11, 2022

Does replacing -fPIC with -sMAIN_MODULE fix this perhaps? (we don't have full dynamic linking support, just the limited model of main and side modules)

@hoodmane
Copy link
Contributor Author

Well what works for me is just filtering out -lc. I'm building a Rust package (the Python cryptography package) and cargo generates a linker invocation with -lc. Everything works fine if I just drop -lc in my linker wrapper before handing the invocation to emcc.

@hoodmane
Copy link
Contributor Author

So perhaps I should close this as resolved?

@kripken
Copy link
Member

kripken commented Apr 12, 2022

Oh, ignore my comment on main module, I misread those commands...

I'm not sure where we landed on automatically ignoring redundant link libraries like -lc. @sbc100 ?

@sbc100
Copy link
Collaborator

sbc100 commented Apr 12, 2022

When building a side module we don't add -lc automatically like we do normally. However, if you explicitly ask for it we don't ignore it.

I think its probably bug that we don't auto-build wasm32-emscripten/pic/libc.a here.

@sbc100
Copy link
Collaborator

sbc100 commented Apr 12, 2022

On the other hand you almost certainly don't want to be including libc in your side module... I'm not sure if its best to just ignore it or to give a warning in this case?

@hoodmane
Copy link
Contributor Author

Yeah we are filtering it out. Maybe dropping it and printing a warning would be best?

@kleisauke
Copy link
Collaborator

I think PR #19405 might be an alternative solution for this.

@kleisauke
Copy link
Collaborator

Or, if possible(?), perhaps we could avoid that rust passes -lc to the linker.

$ rustc --target=wasm32-unknown-emscripten --crate-type staticlib --print native-static-libs - < /dev/null
note: Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.

note: native-static-libs: -lc

@hoodmane
Copy link
Contributor Author

Well the rust people rejected my suggestions to adjust rust since in their opinion passing -shared -lc is totally reasonable. I think it is reasonable:

gcc -shared -lc side.c -o side.so

works fine and same with clang. So Emscripten is really doing the wrong thing here by failing. We currently pass -Z link-native-libraries=no but this requires using nightly rust.

I also don't think #19405 is the right solution for this particular problem because we don't really want or need to actually link anything extra into the .so file. The native compilers produce exactly the same output whether -lc is passed or not and Emscripten should too IMO.

@hoodmane
Copy link
Contributor Author

@katietz ran into this problem today trying to build libpng.so. It comes up in other contexts too, not just when building rust.

@hoodmane
Copy link
Contributor Author

But #19405 does look independently helpful. I guess we should check if the #19405 solution has the same code size in the output as this solution. If they are the same code size, then that solution is indeed strictly better.

@sbc100
Copy link
Collaborator

sbc100 commented May 22, 2023

I think #19405 probably won't fix your issue, since you really don't want to link libc.a into both your main module and your side module. That could lead to all kind of problems I think.

@hoodmane
Copy link
Contributor Author

Out of curiousity does passing -lc when linking a main module (or with no dylink) change the behavior in any way? What does -lc actually do?

@sbc100
Copy link
Collaborator

sbc100 commented May 22, 2023

-lc resolves of libc.a that contains our modified version of musl libc. It defines everything from printf to global such as stdout

@sbc100
Copy link
Collaborator

sbc100 commented May 22, 2023

In emscripten we don't build libc as a side module (shared library) but always link it statically into the main module.

@hoodmane
Copy link
Contributor Author

always link it statically into the main module

"always" as in independently of whether -lc is passed or not?

@hoodmane
Copy link
Contributor Author

Ah I see from #19414 that -lc does something when -nostdlib or -nodefaultlibs is passed. That answers my question.

@hoodmane
Copy link
Contributor Author

This doesn't seem to reproduce anymore, so I'll close it as fixed.

hoodmane added a commit to hoodmane/pyodide-build that referenced this issue Oct 16, 2024
The upstream bug that made this necessary seems to have been resolved:
emscripten-core/emscripten#16680
hoodmane added a commit to hoodmane/emscripten that referenced this issue Oct 18, 2024
There have been a lot of bugs when the caller passes `-lc` over the years. For
example it crashes if we do:
```
emcc -lc -sDISABLE_EXCEPTION_CATCHING=0 -sMIN_SAFARI_VERSION=150000
```

Rust likes to pass `-lc`. Let's drop it and stop causing trouble for Rust.

Resolves emscripten-core#22758, emscripten-core#22742 and would have resolved emscripten-core#16680 if it hadn't disappeared
first.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants