如何在基于FreeBSD的系统中使用glibc中的langinfo.h功能而不中断编译



我正在努力使以下代码在基于Linux和FreeBSD的系统上都能工作,这是对宏__GLIBC____USE_XOPEN2K8的有效使用吗?

#include <stdio.h>
#include <langinfo.h>
#include <locale.h>
#include <xlocale.h>
int main(void) {
//#if defined(__GLIBC__) && defined (__USE_XOPEN2K8)
locale_t    loc;
char *locale_messages = "en-US.utf-8";
loc = newlocale(LC_ALL_MASK, locale_messages, (locale_t)0);
if (loc != NULL)
{
char    result[256]; 
sprintf(result, "%s_%s.%s",
nl_langinfo_l(_NL_IDENTIFICATION_LANGUAGE, loc),
nl_langinfo_l(_NL_IDENTIFICATION_TERRITORY, loc),
nl_langinfo_l(CODESET, loc));
}
//#endif 
}

如果我不使用这些指令,我会在macOS上得到以下错误。我想禁用该代码以避免出现以下错误。

error: use of undeclared identifier '_NL_IDENTIFICATION_LANGUAGE'
nl_langinfo_l(_NL_IDENTIFICATION_LANGUAGE, loc),
^
error: use of undeclared identifier '_NL_IDENTIFICATION_TERRITORY'
nl_langinfo_l(_NL_IDENTIFICATION_TERRITORY, loc),

我发现一个线程建议使用_GNU_SOURCE和_XOPEN_SOURCE,但结果上面的代码在我的linux系统上也被禁用了。在使用它之前,我似乎需要定义_GNU_SOURCE,但在继续使用这个想法之前,我们可以使用__GLIBC____USE_XOPEN2K8吗。

您可以使用

#indef __FreeBSD__
#endif

预处理器指令来忽略不应该在FreeBSD上构建的代码。然而,FreeBSD上的man nl_langinfo_l说,这个函数在FreeBSD中存在,所以你应该不会有任何问题

最好的方法是使用构建系统来检测该选项是否可用,然后根据检测结果有条件地启用该部分代码。autotools项目就是这样产生的——检测操作系统之间的差异。

在cmake中,您可以:

include(CheckCSourceCompiles)
check_c_source_compiles("
#define _GNU_SOURCE
#define _SOMETHING_READ_FEATURE_TEST_MACROS
#include <something something that is needed.h>
int main() { return _NL_IDENTIFICATION_TERRITORY; }
" WE_HAVE_NL_IDENTIFICATION_TERRITORY)
if(WE_HAVE_NL_IDENTIFICATION_TERRITORY)
target_add_definitions(your_target PUBLIC LIB_HAS_NL_IDENTIFICATION_TERRITORY)
endif()

然后使用您自己的LIB_HAS_NL_IDENTIFICATION_TERRITORY宏来检测该选项是否可用。这样的解决方案稳定、易于移植,并对环境变化做出动态反应。

最新更新