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

Static version of tdjson? #8

Closed
savely-krasovsky opened this issue Jan 16, 2018 · 7 comments
Closed

Static version of tdjson? #8

savely-krasovsky opened this issue Jan 16, 2018 · 7 comments

Comments

@savely-krasovsky
Copy link

savely-krasovsky commented Jan 16, 2018

I am using Golang with C-bindings to use this lib, but I also want to compile static binary. There is shared version /usr/local/lib/libtdjson.so, but there is no static one. I tried to use libtdjson_static.a, but seems like this is works for C++ only.

@levlam
Copy link
Contributor

levlam commented Jan 20, 2018

We haven't tested static linking of the libtdjson_static library to Golang code, but it looks like Golang (using cgo) supports static linking of С libraries and everything should work fine. You will also need to statically link all TDLib dependencies, namely ilibtdactor, libtddb, libtdnet, libtdsqlite, libtdutils, libcrypto, libssl, libz and standard C++ library (libc++/libstdc++). What errors do you get?

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Jan 20, 2018

@levlam seems like the libs order is the key. After researching CMakeLists.txt I recover the right order:

/*
#cgo LDFLAGS: -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdactor -ltddb -ltdsqlite -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
#include <stdlib.h>
#include <td/telegram/td_json_client.h>
#include <td/telegram/td_log.h>
*/
import "C"

After this I compiled the binary, but with few warnings:

//usr/local/lib/libtdsqlite.a(sqlite3.c.o): In function `unixDlOpen':
sqlite3.c:(.text+0x15b17): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
//usr/local/lib/libtdutils.a(IPAddress.cpp.o): In function `td::IPAddress::init_host_port(td::CSlice, td::CSlice)':
IPAddress.cpp:(.text._ZN2td9IPAddress14init_host_portENS_6CSliceES1_+0x244): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

Because of it seems like Go static builds linked with glibc are not working:

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x0]

runtime stack:
runtime.throw(0x1b4c034, 0x2a)
        /usr/lib/go-1.9/src/runtime/panic.go:605 +0x95
runtime.sigpanic()
        /usr/lib/go-1.9/src/runtime/signal_unix.go:351 +0x2b8

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4cb380, 0xc42005bde0, 0xc42005be01)
        /usr/lib/go-1.9/src/runtime/cgocall.go:132 +0xe4 fp=0xc42005bdb0 sp=0xc42005bd70 pc=0x4027b4
github.com/L11R/go-tdjson._Cfunc_td_json_client_create(0x0)
        github.com/L11R/go-tdjson/_obj/_cgo_gotypes.go:92 +0x4a fp=0xc42005bde0 sp=0xc42005bdb0 pc=0x4c7cea
github.com/L11R/go-tdjson.NewClient(0x1b45955)
        /home/savely/go/src/github.com/L11R/go-tdjson/tdjson.go:37 +0x40 fp=0xc42005be48 sp=0xc42005bde0 pc=0x4c8050
main.main()
        /home/savely/go/src/Aggregator/main.go:29 +0xb6 fp=0xc42005bf80 sp=0xc42005be48 pc=0x4cab66
runtime.main()
        /usr/lib/go-1.9/src/runtime/proc.go:195 +0x226 fp=0xc42005bfe0 sp=0xc42005bf80 pc=0x42afb6
runtime.goexit()
        /usr/lib/go-1.9/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42005bfe8 sp=0xc42005bfe0 pc=0x456cd1

goroutine 5 [syscall]:
os/signal.signal_recv(0x0)
        /usr/lib/go-1.9/src/runtime/sigqueue.go:131 +0xa6
os/signal.loop()
        /usr/lib/go-1.9/src/os/signal/signal_unix.go:22 +0x22
created by os/signal.init.0
        /usr/lib/go-1.9/src/os/signal/signal_unix.go:28 +0x41

Article with very similar problem:
https://tschottdorf.github.io/golang-static-linking-bug

To finalize:
go build -a -ldflags '-linkmode external -extldflags -static' -- not working, so we can't build TOTALLY static build.
go build -- working. We can launch it on the machines without TDlib, but have to install libs like libz, etc. It is quite acceptable.

@levlam
Copy link
Contributor

levlam commented Jan 21, 2018

I have a few suggestions for you:

  1. You can try to manually remove calls to some glibc functions that can't be linked statically.
    In order to remove call to dlopen in sqlite, just add to sqlite/CMakeFiles.txt
    target_compile_definitions(tdsqlite PRIVATE -DSQLITE_OMIT_LOAD_EXTENSION)
    In order to remove call to getaddrinfo, replace function in tdutils/td/utils/port/IPAddress.cpp with
    Status IPAddress::init_host_port(CSlice host, CSlice port) {
    return Status::Error("Unsupported");
    }
    There is no critical functionality in TDLib which depends on that function, it should work fine.
  2. As noted in the linked by you article, you can try to use another libc, for example, musl.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Jan 21, 2018

@levlam thanks for suggestions!

  1. I tried first one, two warnings were disappear, but appeared another one 😢
/usr/lib/x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
(.text+0x11): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
  1. If I understood correctly, I should compile TDLib with musl, but I got many errors, like:
    /home/savely/td/sqlite/sqlite/sqlite3.c:20258:26: fatal error: openssl/rand.h: No such file
    I tried to add -I/usr/include at sqlite/CMakeLists.txt, but then got another errors, tried to solve them, but they appearing "avalanche-like".

@levlam
Copy link
Contributor

levlam commented Jan 21, 2018

  1. This comes from OpenSSL now. You could try to build OpenSSL from sources with no-dso configure option, which should remove calls to dlopen.
  2. You probably also need to recompile OpenSSL and zlib with musl and specify musl-compiled libraries as dependencies when building TDLib, It doesn't sounds like an easy way.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Jan 25, 2018

@levlam thanks for advices. For me easier to link statically against TDLib only. Other libs like OpenSSL, ZLib and others is simpler to install on target system from package manager.

For readers:
Set right flags for CGO:

/*
#cgo LDFLAGS: -ltdjson_static -ltdjson_private -ltdclient -ltdcore -ltdactor -ltddb -ltdsqlite -ltdnet -ltdutils -lstdc++ -lssl -lcrypto -ldl -lz -lm
#include <stdlib.h>
#include <td/telegram/td_json_client.h>
#include <td/telegram/td_log.h>
*/
import "C"

Compile dynamic binary with default command:

go build

Now your binary will depends only from libs like OpenSSL and zLib.

@Arman92
Copy link

Arman92 commented Apr 5, 2018

I have a full tdlib-tdjson binding package here (Autogenerated all types/methods from tdlib.tl) : https://github.com/Arman92/go-tdlib

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

3 participants