我一直在尝试让 Go 应用程序在 Android 10 上运行并遇到了障碍。我很确定我现在知道为什么我会遇到这个障碍,但不知道如何解决它。首先,简单的事情适用于交叉编译。例如,
package main
import "fmt"
func main() {
fmt.Println("Hello, Android!")
}
用 GOARM=arm64 GOOS=linux go build
编译会运行得很好但是现在如果我添加一些网络代码:
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
fmt.Println("Hello, Android!")
client := &http.Client{}
resp, err := client.Get("https://www.google.com")
if err != nil {
fmt.Println(err)
return
}
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s", bodyBytes)
}
并以与运行相同的方式编译,但我会收到如下错误:Get "https://www.google.com": dial tcp: lookup www.google.com on [::1]:53: read udp [::1]:47618->[::1]:53: read: connection refused
最初我认为这是我的 Android 设备上的一些网络配置,但经过大量的困惑之后,我很确定这与 Android 网络“不同”的事实有关。也许这是仿生 vs libc 的事情(?)但至少有其他人似乎已经击中了 same snag并通过使用 NDK 附带的工具链进行构建来解决。有谁知道如何真正让它发挥作用?
最初我希望它像
GOOS=android GOARCH=arm64 go build
一样简单但这失败了:# command-line-arguments
/usr/lib/golang/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-384615804/go.o: Relocations in generic ELF (EM: 183)
<bunch of these>
/usr/bin/ld: /tmp/go-link-384615804/go.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
一些谷歌搜索出现 https://github.com/golang/go/issues/30216 - 这表示您需要明确启用 CGO。但是GOARCH=arm64 GOOS=android CGO_ENABLED=1 go build
仍然失败,这次是:# runtime/cgo
gcc_android.c:6:10: fatal error: android/log.h: No such file or directory
6 | #include <android/log.h>
| ^~~~~~~~~~~~~~~
compilation terminated.
我弄乱了很多其他组合,最接近的是在我的 NDK 安装中指向编译器。基本上类似于 GOARCH=arm64 GOOS=android CC=$NDKROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc CGO_ENABLED=1 CGO_CFLAGS="--sysroot $NDKROOT/sysroot -I$NDKROOT/sysroot/usr/include/arm-linux-androideabi/" go build
.但这失败了:# runtime/cgo
In file included from _cgo_export.c:4:0:
cgo-gcc-export-header-prolog:25:14: error: size of array '_check_for_64_bit_pointer_matching_GoInt' is negative
我指向编译器的方式有问题 - 例如,如果不指定 sysroot,我将找不到任何头文件 (stdlib.h),即使那样它也找不到特定于体系结构的包含 (asm/types.h)。 h) 没有指定额外的包含路径。所以错误可能是架构和编译器之间的不匹配,我只是不确定在哪里或如何修复它。如果您已阅读所有这些内容,谢谢!一些额外的信息:
我也看过类似 gomobile 的东西但这似乎更适合构建 Android 应用程序(如 apks),尽管我可能在这里遗漏了一些东西。
最佳答案
弄清楚了!好吧,让我的具体示例工作,但我不确定为什么会这样。答案基本上来自https://github.com/golang/go/issues/20755你必须:
所以对于我的例子:
$ $(NDKROOT)/build/tools/make_standalone_toolchain.py --arch arm64 --api 24 --install-dir $(HOME)/ndk_standalone
$ CC=$(HOME)/ndk_standalone/bin/clang CXX=$(HOME)/ndk_standalone/bin/clang GOOS=android GOARCH=arm64 go install std
$ CC=$(HOME)/ndk_standalone/bin/clang CXX=$(HOME)/ndk_standalone/bin/clang GOOS=android GOARCH=arm64 CGO_ENABLED=1 go build
和网络工作!我不太确定为什么(或如果)clang 与直接调用编译器不同。也许我会更多地玩这个。此外,在编译我的应用程序时(但不是为 go std 库),我仍然必须显式启用 CGO,否则链接失败。
关于android - 在 Android 上使用网络,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65366107/