go icon indicating copy to clipboard operation
go copied to clipboard

cmd/cgo: building fully statically linked executable for Android fails when cgo is enabled

Open leleliu008 opened this issue 2 years ago • 6 comments

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; 
}

leleliu008 avatar May 03 '23 06:05 leleliu008

(CC @golang/android)

bcmills avatar May 04 '23 12:05 bcmills

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.

mknyszek avatar May 10 '23 19:05 mknyszek

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.

leleliu008 avatar May 11 '23 02:05 leleliu008

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.

leleliu008 avatar May 11 '23 02:05 leleliu008

workaround https://github.com/termux/termux-packages/pull/21667/commits/10e3b958b614e42272eded008745a40bfe589358

tomaszduda23 avatar Oct 04 '24 17:10 tomaszduda23

@eliasnaur would you mind take a look on this? Current implementation on Android use dlopen which causes two problems:

  1. impossible to build static executable
  2. runc deadlock on dlopen for some reason https://github.com/termux/termux-packages/pull/21667

tomaszduda23 avatar Oct 19 '24 15:10 tomaszduda23