Golang中从Go1.10版本起使用Android NDK时出现的Cgo构建失败问题
Golang中从Go1.10版本起使用Android NDK时出现的Cgo构建失败问题 对于Syncthing来说,一个原生Go应用程序需要为Android使用cgo进行交叉编译。目前这些构建仍在go1.9上进行。我们原以为以下问题在go1.11中已经修复,但使用beta 3进行测试显示问题仍然存在。我首先在论坛上提问,以确认这是用户问题、NDK问题还是Golang问题。
构建过程是从15b生成独立NDK,具体操作如下(环境变量的值在下方给出):
$NDK_HOME/build/tools/make_standalone_toolchain.py --arch $ARCH --api $MIN_SDK --install-dir $STANDALONE_NDK_DIR -v
然后安装标准工具:
CGO_ENABLED=1 CC=STANDALONE_NDK_DIR/android-$MIN_SDK-$GOARCH/bin/$CCBIN GOOS=android GOARCH=$GOARCH go install -v std
接着我们使用自定义构建脚本构建应用程序,该脚本只是在调用go build之前进行一些准备工作:
CC=$STANDALONE_NDK_DIR/bin/$CCBIN go run build.go -goos android -goarch $GOARCH -no-upgrade build
这针对不同的架构使用以下值执行:
{
'arch': 'arm',
'goarch': 'arm',
'ccbin': 'arm-linux-androideabi-clang',
'min_sdk': 21,
},
{
'arch': 'arm64',
'goarch': 'arm64',
'ccbin': 'aarch64-linux-android-clang',
'min_sdk': 21,
},
{
'arch': 'x86',
'goarch': '386',
'ccbin': 'i686-linux-android-clang',
'min_sdk': 16,
}
为了确保与NDK版本无关,我还尝试了最新的17b版本。 在最后阶段出现以下错误: arm:
# runtime/cgo
In file included from gcc_libinit.c:8:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/pthread.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/time.h:33:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/time.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/select.h:36:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/signal.h:37:
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:79:20: error: expected ';' at end of declaration list
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:73:18: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:85:22: note: expanded from macro 'sa_handler'
In file included from gcc_libinit.c:8:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/pthread.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/time.h:33:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/time.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/select.h:36:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/signal.h:37:
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:79:20: error: expected ')'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:74:12: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:86:24: note: expanded from macro 'sa_sigaction'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:79:20: note: to match this '('
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:74:10: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:79:20: error: duplicate member '_u'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:74:12: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:86:22: note: expanded from macro 'sa_sigaction'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:79:20: note: previous declaration is here
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:73:18: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:85:20: note: expanded from macro 'sa_handler'
In file included from gcc_libinit.c:8:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/pthread.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/time.h:33:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/time.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/select.h:36:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/signal.h:37:
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:80:22: error: expected ';' at end of declaration list
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:73:18: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:85:22: note: expanded from macro 'sa_handler'
In file included from gcc_libinit.c:8:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/pthread.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/time.h:33:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/time.h:37:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/sys/select.h:36:
In file included from /media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/signal.h:37:
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:80:22: error: expected ')'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:74:12: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:86:24: note: expanded from macro 'sa_sigaction'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:80:22: note: to match this '('
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:74:10: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:80:22: error: duplicate member '_u'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:74:12: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:86:22: note: expanded from macro 'sa_sigaction'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:80:22: note: previous declaration is here
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/bits/signal_types.h:73:18: note: expanded from macro '__SIGACTION_BODY'
/media/ext4_data/Coding/syncthing-android/syncthing/gobuild/standalone-ndk/android-16-arm/bin/../sysroot/usr/include/asm/signal.h:85:20: note: expanded from macro 'sa_handler'
目前暂时省略了386和arm64的错误信息。
然后我考虑如何在不涉及Syncthing的情况下获得可复现的示例,因此我尝试像这样交叉编译go1.11 beta 3(在$GOROOT/src中运行):
CC=$STANDALONE_NDK_DIR/bin/$CCBIN GOOS=android GOARCH=$GOARCH ./make.bash
结果出现了与上述完全相同的失败。
使用go 1.9时一切正常。大家有什么想法问题可能出在哪里吗?
另外,我是否需要添加arm64和386的结果?
更多关于Golang中从Go1.10版本起使用Android NDK时出现的Cgo构建失败问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang中从Go1.10版本起使用Android NDK时出现的Cgo构建失败问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个已知的Go语言与Android NDK兼容性问题。从Go 1.10开始,Go工具链对Cgo的处理发生了变化,导致与某些Android NDK版本的头文件存在冲突。错误信息显示在signal_types.h头文件中存在重复成员定义和语法错误。
问题出现在__SIGACTION_BODY宏的定义上,这是Android NDK头文件与Go的Cgo编译器的兼容性问题。在Go 1.9中,Cgo的处理方式不同,因此不会遇到这个问题。
以下是针对此问题的解决方案:
// 设置环境变量来绕过这个问题
export CGO_CFLAGS="-D__ANDROID_API__=$MIN_SDK"
// 对于arm架构的构建示例
export GOOS=android
export GOARCH=arm
export CC=$STANDALONE_NDK_DIR/bin/arm-linux-androideabi-clang
export CGO_CFLAGS="-D__ANDROID_API__=21"
go build -v your_package
或者,可以在构建时直接指定C标志:
CGO_CFLAGS="-D__ANDROID_API__=21" CC=$STANDALONE_NDK_DIR/bin/arm-linux-androideabi-clang GOOS=android GOARCH=arm go build -v .
对于不同的架构,需要相应地调整CGO_CFLAGS:
// arm64
CGO_CFLAGS="-D__ANDROID_API__=21" CC=$STANDALONE_NDK_DIR/bin/aarch64-linux-android-clang GOOS=android GOARCH=arm64 go build -v .
// x86 (386)
CGO_CFLAGS="-D__ANDROID_API__=16" CC=$STANDALONE_NDK_DIR/bin/i686-linux-android-clang GOOS=android GOARCH=386 go build -v .
在构建标准库时也需要应用相同的修复:
CGO_CFLAGS="-D__ANDROID_API__=$MIN_SDK" CC=$STANDALONE_NDK_DIR/bin/$CCBIN GOOS=android GOARCH=$GOARCH go install -v std
这个问题的根本原因是Go 1.10+的Cgo现在更严格地处理C头文件,而Android NDK中的某些头文件定义在特定API级别下存在兼容性问题。通过显式定义__ANDROID_API__宏,可以确保头文件使用正确的定义路径。
对于你的构建脚本,修改如下:
CGO_CFLAGS="-D__ANDROID_API__=$MIN_SDK" CC=$STANDALONE_NDK_DIR/bin/$CCBIN go run build.go -goos android -goarch $GOARCH -no-upgrade build
是的,建议也提供arm64和386架构的错误信息,因为它们可能遇到类似但略有不同的问题,有助于更全面地诊断问题。

