golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.74k stars 17.63k forks source link

cmd/compile, os: Go code in shared library under Android can't read env variables #59843

Open awsong opened 1 year ago

awsong commented 1 year ago

What version of Go are you using (go version)?

$ go version
go version go1.20.3 android/arm64

Does this issue reproduce with the latest release?

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/data/data/com.termux/files/home/.cache/go-build"
GOENV="/data/data/com.termux/files/home/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="android"
GOINSECURE=""
GOMODCACHE="/data/data/com.termux/files/home/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="android"
GOPATH="/data/data/com.termux/files/home/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/data/data/com.termux/files/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/data/data/com.termux/files/usr/lib/go/pkg/tool/android_arm64"
GOVCS=""
GOVERSION="go1.20.3"
GCCGO="gccgo"
AR="ar"
CC="aarch64-linux-android-clang"
CXX="aarch64-linux-android-clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -pthread -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/data/data/com.termux/files/usr/tmp/go-build3459929408=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I wrote a Go function named Foo(), whith calls os.UserConfigDir() and prints out the result or error. Function Foo() is exported to shared library through CGO, then is called in c program.

~/issue $ ls -R
.:
foo.c  test

./test:
go.mod  test.go
~/issue $ cat foo.c 
#include 
#include 
#include 
#include 

int main() {

    // Call the Foo() function and print the result
    char* result = Foo();
    printf("Result: %s\n", result);

    return 0;
}

~/issue $ cat test/test.go 
package main

import (
    "C"
    "os"
)

func main() {
}

//export Foo
func Foo() *C.char{
    dir, err := os.UserConfigDir()
    if err != nil {
        return C.CString(err.Error())
    }
    return C.CString(dir)
}
~/issue $ cat test/go.mod 
module mytest

go 1.20
~/issue $ cd test
~/issue/test $ go build -v -buildmode=c-shared -o libtest.so
runtime/cgo
mytest
~/issue/test $ cd ../
~/issue $ cc foo.c -I./test -L./test -ltest
~/issue $ LD_LIBRARY_PATH=./test ./a.out 
Result: neither $XDG_CONFIG_HOME nor $HOME are defined

What did you expect to see?

$ LD_LIBRARY_PATH=./test ./a.out
/data/data/com.termux/files/home/.config

What did you see instead?

$ LD_LIBRARY_PATH=./test ./a.out 
Result: neither $XDG_CONFIG_HOME nor $HOME are defined
dmitshur commented 1 year ago

CC @golang/android.

awsong commented 1 year ago

Same code works fine under linux and mac.

ianlancetaylor commented 1 year ago

A Go shared library built with -buildmode=c-shared relies on dynamic linker support to get command line arguments and environment variables. It's possible that the Android dynamic linker does not support that. This is probably essentially the same problem as #13492.

awsong commented 1 year ago

Not sure whether go build uses the same linker as c or not. But I did write a similar shared library in c which also read env vars in the library code that works fine under android.