cmd/cgo: building fully statically linked executable for Android fails when cgo is enabled
What version of Go are you using (go version)?
go version go1.20.3 linux/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env)?
GO111MODULE="auto"
GOARCH="arm64"
GOBIN=""
GOCACHE="/home/leleliu008/.cache/go-build"
GOENV="/home/leleliu008/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/leleliu008/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="android"
GOPATH="/home/leleliu008/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/linuxbrew/.linuxbrew/Cellar/go/1.20.3/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/linuxbrew/.linuxbrew/Cellar/go/1.20.3/libexec/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.3"
GCCGO="gccgo"
AR="/home/leleliu008/.ndk-pkg/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
CC="/home/leleliu008/.ndk-pkg/core/bin/proxy-target-cc"
CXX="/home/leleliu008/.ndk-pkg/core/bin/proxy-target-c++"
CGO_ENABLED="1"
GOMOD="/home/leleliu008/.ndk-pkg/installing/android-31/arm64-v8a/yq/src/go.mod"
GOWORK=""
CGO_CFLAGS="--sysroot /home/leleliu008/.ndk-pkg/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Qunused-arguments -fPIC -fno-common -Os"
CGO_CPPFLAGS="-I/home/leleliu008/.ndk-pkg/installing/android-31/arm64-v8a/yq/include --sysroot /home/leleliu008/.ndk-pkg/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Qunused-arguments -include /home/leleliu008/.ndk-pkg/installing/android-31/arm64-v8a/yq/include/ndk-pkg-common.h -DNDEBUG"
CGO_CXXFLAGS="--sysroot /home/leleliu008/.ndk-pkg/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Qunused-arguments -fPIC -fno-common -Os"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-L/home/leleliu008/.ndk-pkg/installing/android-31/arm64-v8a/yq/lib --sysroot /home/leleliu008/.ndk-pkg/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Wl,--as-needed -Wl,-z,muldefs -Wl,--allow-multiple-definition -static --static -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--no-dynamic-linker -Wl,-S"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -pthread -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build155171888=/tmp/go-build -gno-record-gcc-switches"
What did you do?
go build -trimpath -v -ldflags ' -s -w -linkmode external "-extldflags=-static"' -tags release
What did you expect to see?
successfully built
What did you see instead?
/home/linuxbrew/.linuxbrew/Cellar/go/1.20.3/libexec/pkg/tool/linux_amd64/link: running /home/leleliu008/.ndk-pkg/core/bin/proxy-target-cc failed: exit status 1
ld: error: undefined symbol: __android_log_vprint
>>> referenced by gcc_android.c
>>> /tmp/go-link-1481358754/000008.o:(fatalf)
ld: error: undefined symbol: dlopen
>>> referenced by gcc_android.c
>>> /tmp/go-link-1481358754/000008.o:(inittls)
ld: error: undefined symbol: dlsym
>>> referenced by gcc_android.c
>>> /tmp/go-link-1481358754/000008.o:(inittls)
ld: error: undefined symbol: dlclose
>>> referenced by gcc_android.c
>>> /tmp/go-link-1481358754/000008.o:(inittls)
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
more
https://github.com/golang/go/blob/master/src/runtime/cgo/gcc_android.c
gcc_android.c rely on liblog.so and libdl.so
Note: Android NDK do not provides liblog.a
statically linked executable can not use functions in libdl.
to get runtime os SDK API Level, I usually use follwoing code:
char buff[PROP_VALUE_MAX];
int n = __system_property_get("ro.build.version.sdk", buff);
if (n > 0) {
return 0;
} else {
return -1;
}
(CC @golang/android)
In triage, we're not sure if building a fully static Android executable is supported. Assigned to the only person in @golang/android for more thoughts and details.
Android command-line app can be built as fully statically linked executable or position independent dynamically linked execuable.
Android apk only use dynamically linked library.
It would be cool if this feature could be implemented.
Rust don't support building as fully stattically linked executable for Android as well, but I can hack it. https://github.com/rust-lang/cargo/issues/10765
I din't find a way to do so for golang.
workaround https://github.com/termux/termux-packages/pull/21667/commits/10e3b958b614e42272eded008745a40bfe589358
@eliasnaur would you mind take a look on this? Current implementation on Android use dlopen which causes two problems:
- impossible to build static executable
- runc deadlock on dlopen for some reason https://github.com/termux/termux-packages/pull/21667