交叉编译时选择的API版本28不存在futimes函数



我正在尝试交叉编译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中的注释所示。相反,我们必须自己提供预处理器宏定义。

最新更新