-
Notifications
You must be signed in to change notification settings - Fork 70
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
Adjust dependencies to make it possible to statically link dqlite. #241
base: master
Are you sure you want to change the base?
Conversation
@@ -1,6 +1,6 @@ | |||
package bindings | |||
|
|||
/* | |||
#cgo linux LDFLAGS: -lraft -ldqlite -Wl,-z,now | |||
#cgo linux LDFLAGS: -ldqlite -lraft -llz4 -luv_a -lm -Wl,-z,now |
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.
I guess -luv_a
forces cc to link against libuv.a instead of libuv.so? I appreciate the virtues of static linking and I'd be happy to support it better in go-dqlite, but I'm very wary of modifying the cgo setup in a way that affects all users of go-dqlite like this. People may be depending on libuv being linked dynamically.
If you're willing to wait a bit, I'm aiming to make the upcoming C client library for dqlite support static linking, and I have a setup for building a fully-static libdqlite that I can publish and point you to.
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.
Not really. It appears that my distribution (ubuntu 22.04) comes with the libuv_a.a
file instead of libuv.a, and I assumed that this could be the default naming convention for the static version of the libuv library.
However, the switch for static linking comes with the -static ld flag, which forces ld to look for *.a files instead of *.so files. I initially thought that this wouldn't affect dynamic linking at all since the .a extension would be ignored during dynamic linking. At least it seems like that's what's happening on my system. But yeah, it looks a little dirty.
Didn't know that you already had plans to support fully-static builds. That will help a lot, thank you!
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.
Ah, yeah, this is tricky. I guess libuv doesn't ship libuv.a
at all (I thought it did, but on double-checking I have the same thing in /usr/lib/x86_64-linux-gnu as you do). That means you really have to use a different -l
flag depending on whether you want libuv to be statically or dynamically linked -- go-dqlite can't straightforwardly support both at once. I definitely don't want to silently switch the default behavior (and I don't know whether non-Ubuntu systems have libuv_a.a as well), but we should definitely figure out a way to produce static binaries with go-dqlite. Maybe we could use a build tag to select between two versions of build.go, one of which has -static -luv_a
and one of which has -luv
?
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 could be an option, but I'm unsure about including -static
in the #cgo linux LDFLAGS:
directive. This flag forces the static build for the entire application. But if we don't include this, then users would need to add it themselves. Or maybe we could do so just with the big red warning in the readme?:)
From the user experience perspective it just looks like the providing a static version of the dqlite library with all dependencies included might be the best choice. In this case, the build process will remain unchanged. However, it might not be very flexible for end-users who want to build with their own versions of the dependencies.
A lot of tradeoffs:)
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.
After some thought, I think it would be better to stick with the dqlitestatic
tag.
build_static.go
// +build dqlitestatic
package bindings
/*
#cgo linux LDFLAGS: -static -ldqlite -lraft -llz4 -luv_a -lm -Wl,-z,now
*/
import "C"
and readme warning about this. It just combines the possibility to replace dependencies if you want and a convenient build process where you just need to specify a new tag. What do you think?
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.
After some investigation, it looks like this filename has changed starting from ubuntu jammy. And the old releases contain normal libuv.a file. And this comes from the libuv itself. Starting from the v.1.40.0 they started shipping libuv_a libuv/libuv#2988
Considering this, maybe it would be better to provide several tags? Like dqlitestatic_libuva
and dqlitestatic_libuv
? I just ran out of ideas:)
Or maybe there could be some workarounds with pkg-config?
IIRC passing Just trying to understand your use case, so we have better information when deciding for the most appropriate solution. |
As far as I see, this tag just adds Regarding my use case, I just want to build a fully static go executable:) With all dependencies included. And with these changes, it actually works. Static example:
Dynamic example:
|
I might be confused or not remember correctly, but if don't pass |
I understand:) But as I see, it cannot happen. Just wanted to share my observations to make it easier to check: When I said "this tag just adds -lsqlite3 to the LDFLAGS" it's been a little roughly speaking. In fact, it also adds USE_LIBSQLITE3 define and then if we take a look at the sqlite3-binding.c we can see that at the very first line, there is a check And at line # #else // USE_LIBSQLITE3
// If users really want to link against the system sqlite3 we
// need to make this file a noop.
#endif So to summarize, if |
That was my understanding indeed. But I was assuming that if you pass |
I have successfully static link dqlite in golang. You can ref to https://github.com/openPanel/core/blob/master/Taskfile.yml Seems it works well without change the dqlite source. Of course, symbol like |
And as my personal curious, why |
It works! Thank you very much. I had previously tried passing everything through the CGO_LDFLAGS variable, but it seemed to concatenate the flags to the beginning of the ld flags. While
It appears to be a sqlite dependency in my system. Without it, I get the following errors
|
seems it because i didn't pass |
Hi. Currently, if you try to build a statically linked executable you'll see a lot of errors like:
To get rid of these errors we need to ensure that all of dqlite's dependencies are also linked to the executable. So we need to specify them in the correct order after the dqlite library itself.