如何在不中断基于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,nl_langinfo_l(CODESET,loc));
    }
//#endif 
}

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

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

我发现一个thread建议使用_GNU_SOURCE和_XOPEN_SOURCE,但是结果是上面的代码也被禁用了。似乎我需要在使用_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宏来检测该选项是否可用。这种解决方案稳定,易于移植,并且可以对环境变化做出动态反应。