golang/go

x/mobile/cmd/gomobile: gomobile build on simple program returns "ld: error: duplicate symbol: x_cgo_inittls"

nicklasaven opened this issue ยท 16 comments

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

$ go version
go version go1.15.5 linux/amd64

Does this issue reproduce with the latest release?

Yes, latest release is 1.15.5

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/nicklas/.cache/go-build"
GOENV="/home/nicklas/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/nicklas/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/nicklas/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build465769179=/tmp/go-build -gno-record-gcc-switches"

What did you do?

run
gomobile build
on a simple script like:

package main

/*
double Square(double a)
{
    return a * a;
}
*/
import "C"
import "fmt"

func main() {
    a := C.double(10)
    b := C.Square(a)
    fmt.Println(b)
}

What did you expect to see?

That the process succeeded

What did you see instead?

ld: error: duplicate symbol: x_cgo_inittls
>>> defined at gcc_android.c:90
>>>            $WORK/b059/_x003.o:(x_cgo_inittls)
>>> defined at gcc_linux_arm.c:13
>>>            $WORK/b059/_x006.o:(.bss+0x4)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I think this comes from latest NDK upgrade

I have had a quite hard time to prove that the ndk is at least part of the issue since ndk-bundle precedence is hard coded in env.go
https://github.com/golang/mobile/blob/973feb4309de5c3aad0553fc987d76abf1fa58f7/cmd/gomobile/env.go#L181

So I renamed ndk-bundle folder temporary so I could change ndk with ANDROID_NDK_HOME

Then:

export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/22.0.6917172
gomobile build -x -v

fails with the error in this issue

but this works without issue:

export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/21.3.6528147
gomobile build -x -v

and

export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/20.0.5594570
gomobile build -x -v

By using the -x flag I could confirm that the older NDK then was used instead of ndk-bundle.

This issue was also mentioned in #42647 (comment)

Exporting ANDROID_NDK_HOME may also fail.

ndkRoot := filepath.Join(androidHome, "ndk-bundle")

https://github.com/golang/mobile/blob/973feb4309de5c3aad0553fc987d76abf1fa58f7/cmd/gomobile/env.go#L181-L204

Yes, exactly, that is why I renamed ndk-bundle so it couldn't find it as I wrote in the issue.

I would have preferred if ANDROID_NDK_HOME tok precedence over the presence of ndk-bundle, but that is another issue I guess :-)

Any idea what the root problem is? I can confirm that compiling a simple go program (anything that uses net) fails for me on NDK version 22, but works for NDK 21. I'm not using gomobile, but invoking the compiler directly like this:

GOOS=android GOARCH=arm64 CGO_ENABLED=1 CC=$NDK_ROOT/21.3.6528147/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang go build

See my issue (resolved for now by downgrading NDK version) here: #42725

I think "extern" keyword is needed before
void (*x_cgo_inittls)(void **tlsg, void **tlsbase);
in each of src/runtime/cgo/gcc_linux_*.c, when used with Android NDK r22-beta1.

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

$ go version
go version go1.15.5 linux/amd64

Does this issue reproduce with the latest release?

Yes, latest release is 1.15.5

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

go env Output

What did you do?

run
gomobile build
on a simple script like:

package main

/*
double Square(double a)
{
    return a * a;
}
*/
import "C"
import "fmt"

func main() {
    a := C.double(10)
    b := C.Square(a)
    fmt.Println(b)
}

What did you expect to see?

That the process succeeded

What did you see instead?

ld: error: duplicate symbol: x_cgo_inittls
>>> defined at gcc_android.c:90
>>>            $WORK/b059/_x003.o:(x_cgo_inittls)
>>> defined at gcc_linux_arm.c:13
>>>            $WORK/b059/_x006.o:(.bss+0x4)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I think this comes from latest NDK upgrade

I have had a quite hard time to prove that the ndk is at least part of the issue since ndk-bundle precedence is hard coded in env.go
https://github.com/golang/mobile/blob/973feb4309de5c3aad0553fc987d76abf1fa58f7/cmd/gomobile/env.go#L181

So I renamed ndk-bundle folder temporary so I could change ndk with ANDROID_NDK_HOME

Then:

export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/22.0.6917172
gomobile build -x -v

fails with the error in this issue

but this works without issue:

export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/21.3.6528147
gomobile build -x -v

and

export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/20.0.5594570
gomobile build -x -v

By using the -x flag I could confirm that the older NDK then was used instead of ndk-bundle.

This issue was also mentioned in #42647 (comment)

Solved by downloading older version of NDK 21.3.6528147
https://developer.android.com/ndk/downloads

tmm1 commented

Adding extern to the gcc_linux_* files makes the android build work, but then building for linux fails:

[linux-x86_64] Building packages and commands for linux/amd64.
[linux-x86_64] # runtime/cgo
[linux-x86_64] /tmp/go-build668149361/b038/_x006.o: In function `x_cgo_init':
[linux-x86_64] src/runtime/cgo/gcc_linux_amd64.c:51: undefined reference to `x_cgo_inittls'
[linux-x86_64] collect2: error: ld returned 1 exit status

Adding extern to the android file doesn't work:

# runtime/cgo
gcc_android.c:90:15: error: 'extern' variable has an initializer [-Werror,-Wextern-initializer]

cc @ianlancetaylor @eliasnaur

Change https://golang.org/cl/280312 mentions this issue: runtime/cgo: fix Android build with NDK 22

@gopherbot Please open backport issues

Although this was filed against x/mobile, the fix is to runtime/cgo in the standard library. This is caused by a change in the default behavior of the C compiler. Anybody using an older release of Go with a new C compiler will run into this problem. Since the fix is small and safe, we should backport it.

Backport issue(s) opened: #43405 (for 1.14), #43406 (for 1.15).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.

manen commented

Screenshot

Same thing happens to me :/

NDK 22.0.7026061 same problem, 21.3.6528147 works.

gomobile version +e6ae53a Thu Dec 17 15:07:44 2020 +0000 (android); androidSDK=/home/m/app/android-sdk/platforms/android-30

@eliasnaur would you mind creating the backport CL's for 1.14 and 1.15?

Done.

Hello guys! Sorry, the issue seems to be fixed but how can I get the fix?

I believe Go 1.16 RC1 contains the fix. The Go 1.15 backport is slated to be included in Go 1.15.8.

Thank you @eliasnaur