-
Notifications
You must be signed in to change notification settings - Fork 11
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
experiment: Static musl build #719
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #719 +/- ##
==========================================
- Coverage 85.35% 80.35% -5.01%
==========================================
Files 7 8 +1
Lines 3927 4164 +237
==========================================
- Hits 3352 3346 -6
- Misses 575 818 +243 ☔ View full report in Codecov by Sentry. |
21cef06
to
2e9ce83
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks great and would be awesome to finish this up
e72e576
to
5592774
Compare
So I updated the tests to build the static lib and put them in the right place like we were doing for the dynamic libs in the various SDKS (in Now we'll need to determine which languages can call into a static lib via FFI or some other mechanism. Go seems to work after I added one Current Status✅ Go (required adding ❌ Ruby (it seems the FFI gem only works for dynamic libs ffi/ffi#225) ❌ Java ( ❌ Dart (trying to load dynamic lib.. ❌ Python ( ❌ CSharp ( |
New ApproachGo back to building as a |
Ok.. so now with that approach here are the results:
In the tests we're compiling the .so on a linux-musl (alpine) host and then copying it to the test containers for each language which AFAIK are all debian based.. so this should prove that musl
|
just wow |
Ok.. so back to the drawing board it seems. In the previous commit(s) I was using Now when I fixed this and run the Go tests on different platforms like: I get this on the debian based hosts (which is to be expected I guess because we are still building a
|
Phew I went down some rabbit holes.. Here's a summary of the key changes made to fix the musl/glibc compatibility issues: In test/main.go:
In flipt-client-go/evaluation.go:
The key insight was that building with musl on Alpine allows the library to work on both musl and glibc systems, but we need to bundle the musl runtime libraries with our .so file. This approach avoids requiring users to install musl packages on their systems while maintaining compatibility across different libc implementations. So.. now we need to test with the other languages.. but Go works on the various distros:
I suppose its not a big deal to copy the required musl libs |
I don't know about other distros but on Debian 13 |
So I spent pretty much the whole day yesterday trying to get this to work and Im thinking its not possible to create a musl .so and run it on both musl and glibc hosts reliably. I think the ABIs are too different and we'll run into problems of it working on one distro but not another because of various differences in versions of glibc..etc. I think at this point we have three options:
|
Update! So it looks like option 1 does work at least on x86 & ARM Linux (via docker) in my initial testing. I likely broke Darwin and Windows support though because now we are creating only a static lib from Rust and not a dylib, and Darwin and Windows can work with dylibs just fine.. But if this passes CI for Go I'll try to get it working for the other languages 🤞🏻 on Linux and test on Debian and Alpine hosts for both x86_64 and arm64. Then if we can get the other languages to work again we can go back and fix the differences between Linux and Windows/Darwin |
The staticlib is used in Android. I have "borrowed" part of your PR (it will be a wild merge) and finally get Android CI running. |
@markphelps could we keep |
Ah yes. I can add that back. I think we'll also need dylib back as well for Darwin and Windows |
* chore: split up package-ffi workflows by OS Signed-off-by: Mark Phelps <[email protected]> * chore: add back notify android test job Signed-off-by: Mark Phelps <[email protected]> * chore: revert back to dynamic lib for now Signed-off-by: Mark Phelps <[email protected]> --------- Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
…-client-sdks into static-musl-build * 'static-musl-build' of https://github.com/flipt-io/flipt-client-sdks: build(deps): bump androidx.test.ext:junit (#710) build(deps): bump com.android.tools.build:gradle (#736) build(deps-dev): bump @types/node in /flipt-client-node (#735) build(deps-dev): bump rollup in /flipt-client-browser (#733) build(deps-dev): bump prettier from 3.4.2 to 3.5.1 in /flipt-client-node (#734) build(deps-dev): bump rollup in /flipt-client-react (#732) build(deps-dev): bump globals in /flipt-client-react (#731) build(deps-dev): bump @typescript-eslint/parser in /flipt-client-react (#728) build(deps-dev): bump @typescript-eslint/eslint-plugin (#730) build(deps-dev): bump @types/react in /flipt-client-react (#729) build(deps): bump flipt-io/setup-action from 0.2.0 to 0.3.1 (#727) chore: split up package-ffi workflows by OS (#724)
Ok so I'm consistently getting segfaults when trying to run the Go tests. All the other SDKs are passing except Go: https://github.com/flipt-io/flipt-client-sdks/actions/runs/13422162445 Im assuming because they are using FFI libs and Go is using Cgo which tries to do the linking itself (i think?) I spun up a Linux (Ubuntu) VM and went through the steps to build the # this builds the static lib (.a)
cargo build -p flipt-engine-ffi --release
# next we copy it to the flipt-engine-ffi dir where the build.sh script is which creates our .so using musl-gcc
cp target/release/libfliptengine.a flipt-engine-ffi
cd flipt-engine-ffi
./build.sh
# then we move the .so and .h files to the places that the Go SDK expects them (see the existing CGO directives)
cd ..
mkdir -p flipt-client-go/ext/linux_aarch64
cp flipt-engine-ffi/libfliptengine.so flipt-client-go/ext/linux_aarch64/
cp flipt-engine-ffi/include/flipt_engine.h flipt-client-go/ext/
# finally we build our test with debugging symbols added
go test -c -gcflags="all=-N -l"
# and run the compiled test with gdb
gdb ./flipt-client.test within gdb: (gdb) run -test.v
Starting program: /home/mark/workspace/flipt-client-sdks/flipt-client-go/flipt-client.test -test.v
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x0000fffff7d9b900 in getauxval () from /home/mark/workspace/flipt-client-sdks/flipt-client-go/ext/linux_aarch64/libfliptengine.so
(gdb) bt
#0 0x0000fffff7d9b900 in getauxval () from /home/mark/workspace/flipt-client-sdks/flipt-client-go/ext/linux_aarch64/libfliptengine.so
#1 0x0000fffff79efdec in init_have_lse_atomics () at ./lib/builtins/cpu_model/aarch64/lse_atomics/sysauxv.inc:4
#2 0x0000fffff7fc7624 in call_init (env=0xfffffffff080, argv=0xfffffffff068, argc=2, l=<optimized out>) at ./elf/dl-init.c:70
#3 call_init (l=<optimized out>, argc=2, argv=0xfffffffff068, env=0xfffffffff080) at ./elf/dl-init.c:26
#4 0x0000fffff7fc772c in _dl_init (main_map=0xfffff7fff370, argc=2, argv=0xfffffffff068, env=0xfffffffff080) at ./elf/dl-init.c:117
#5 0x0000fffff7fd9cc8 in _dl_start_user () from /lib/ld-linux-aarch64.so.1
Backtrace stopped: previous frame identical to this frame (corrupt stack?) so we can see the crash is coming from I found this Go issue from 2017: golang/go#13492 Currently reading through it to see if there's any solution.. but I wanted to post my steps to reproduce here incase anyone else had any idea / could reproduce cc @erka |
After doing some more digging I don't think it's gonna work for Go.. seems that segfault is a known issue after reading the above linked GitHub issue and won't be fixed any time soon. Also seems that cgo doesn't officially support any c std lib other than glibc.. Anyways I think we'll keep this as is for the other languages that use FFI as it seems to work quite well. I think next steps for go cross compatibility is to compile the evaluator to wasm and use something like wazero to call it from Go |
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
…-client-sdks into static-musl-build * 'static-musl-build' of https://github.com/flipt-io/flipt-client-sdks: feat(java): added error strategy option (#739) feat(ruby): added error strategy option (#740)
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
Signed-off-by: Mark Phelps <[email protected]>
try building a true static lib for musl as previously we were still dynamically linking
For musl targets, we need use
+crt-static
instead of-crt-static
to enable static linking-crt-static
means disabling static linking which Claude says is still required for AndroidThe idea is that if we use a static lib built with musl we can still use it in hosts that use glibc.. which would mean we could finally get away from the two different versions of libs for Go/Java/etc (glibc vs musl)
This also switches to use the rusttls crate and feature for
reqwest
which is a TLS lib implemented in Rust instead of depending on the system openssl which we cant link against for musl if we want static linksTODO:
.a
instead of.so
for linux