我正在尝试交叉编译PuTTY实用程序以在Termux下运行,尽管使用了API 28级,但它表示函数"futimes"不存在。
以下是它被卡住的地方:
/home/xb/Desktop/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang -DHAVE_CONFIG_H -I. -I././ -I./charset/ -I./windows/ -I./unix/ -Wall -Werror -Wpointer-arith -Wvla -g -O2 -MT unix/uxsftpserver.o -MD -MP -MF $depbase.Tpo -c -o unix/uxsftpserver.o unix/uxsftpserver.c &&
mv -f $depbase.Tpo $depbase.Po
unix/uxsftpserver.c:472:18: error: implicit declaration of function 'futimes' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
SETSTAT_GUTS(FD_PREFIX, fd, attrs, success);
^
您可以通过下载PuTTY源代码版本0.74来浏览有问题的源文件。
本页显示了在API版本26中添加的futimes。
我知道Termux的回购中有PuTTY的二进制包,我只想学习如何交叉编译。
问题是,虽然我们的SDK最低版本可能为26,但我们没有定义__USE_BSD
宏,也没有添加定义。
#if defined(__USE_BSD)
#if __ANDROID_API__ >= 26
int futimes(int __fd, const struct timeval __times[2]) __INTRODUCED_IN(26);
int lutimes(const char* __path, const struct timeval __times[2]) __INTRODUCED_IN(26);
#endif /* __ANDROID_API__ >= 26 */
#endif
sys/time.h source (same as above)
深入研究宏的定义,我们可以看到这个定义:
/*
* With bionic, you always get all C and POSIX API.
*
* If you want BSD and/or GNU extensions, _BSD_SOURCE and/or _GNU_SOURCE are
* expected to be defined by callers before *any* standard header file is
* included.
*
* In our header files we test against __USE_BSD and __USE_GNU.
*/
#if defined(_GNU_SOURCE)
# define __USE_BSD 1
# define __USE_GNU 1
#endif
#if defined(_BSD_SOURCE)
# define __USE_BSD 1
#endif
sys/cdefs.h source (same as above)
因此,我们必须添加_GNU_SOURCE
或_BSD_SOURCE
作为编译器cFlag,它在gradle中看起来是这样的:
android {
compileSdkVersion 30
...
defaultConfig {
minSdkVersion 26
targetSdkVersion 30
...
externalNativeBuild {
cmake {
cFlags "-D_BSD_SOURCE" // or cFlags "-D_GNU_SOURCE"
...
}
}
}
事实证明,NDK在任何地方都不一定会使用这些标志,如sys/cdefs.h
中的注释所示。相反,我们必须自己提供预处理器宏定义。