• __USE_KERNEL_IPV6_DEFS 定义问题排查


    背景:

    想编译一下阿里云iot的 sdk4.0(主要是学习目的),下载后,直接执行make命令,报错信息如下:

    : Compiling portfiles/aiot_port/posix_port.c ...
    In file included from portfiles/aiot_port/posix_port.c:13:
    ./components/das/src/service/compat/netinet/in.h:506:48: error: ‘struct sockaddr_in6’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
      506 | extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in)
          |                                                ^~~~~~~~~~~~
    cc1: all warnings being treated as errors
    make: *** [Makefile:42: output/./portfiles/aiot_port/posix_port.o] Error 1

    环境:

    Ubuntu 20.04 LTS

    gcc --version

    gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
    Copyright (C) 2019 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    原因:

    sdk将部分GNU C Library的源码放在了源文件路径下,但其实又没放全。导致自带的文件和系统的文件不兼容。看下头文件的声明日期。

    sdk内的 netinet/in.h:

    /* Copyright (C) 1991-2016 Free Software Foundation, Inc.
       This file is part of the GNU C Library.
    
       The GNU C Library is free software; you can redistribute it and/or
       modify it under the terms of the GNU Lesser General Public
       License as published by the Free Software Foundation; either
       version 2.1 of the License, or (at your option) any later version.
    
       The GNU C Library is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       Lesser General Public License for more details.
    
       You should have received a copy of the GNU Lesser General Public
       License along with the GNU C Library; if not, see
       <http://www.gnu.org/licenses/>.  */

    系统目录下的 /usr/include/netinet/in.h

    /* Copyright (C) 1991-2020 Free Software Foundation, Inc.
       This file is part of the GNU C Library.
    
       The GNU C Library is free software; you can redistribute it and/or
       modify it under the terms of the GNU Lesser General Public
       License as published by the Free Software Foundation; either
       version 2.1 of the License, or (at your option) any later version.
    
       The GNU C Library is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       Lesser General Public License for more details.
    
       You should have received a copy of the GNU Lesser General Public
       License along with the GNU C Library; if not, see
       <https://www.gnu.org/licenses/>.  */

    两者其实都包含了文件    #include <bits/in.h>

    主要问题在使用宏定义的判断方式差别。

    sdk中:

    #ifndef __USE_KERNEL_IPV6_DEFS
    .....
    #endif /* !__USE_KERNEL_IPV6_DEFS */

    系统文件中:

    #if !__USE_KERNEL_IPV6_DEFS
    ......#endif /* !__USE_KERNEL_IPV6_DEFS */

    而在bits/in.h文件中,其实是不管怎样都定义了该变量的

    /* If the application has already included linux/in6.h from a linux-based
       kernel then we will not define the IPv6 IPPROTO_* defines, in6_addr (nor the
       defines), sockaddr_in6, or ipv6_mreq. Same for in6_ptkinfo or ip6_mtuinfo
       in linux/ipv6.h. The ABI used by the linux-kernel and glibc match exactly.
       Neither the linux kernel nor glibc should break this ABI without coordination.
       In upstream kernel 56c176c9 the _UAPI prefix was stripped so we need to check
       for _LINUX_IN6_H and _IPV6_H now, and keep checking the old versions for
       maximum backwards compatibility.  */
    #if defined _UAPI_LINUX_IN6_H 
        || defined _UAPI_IPV6_H 
        || defined _LINUX_IN6_H 
        || defined _IPV6_H
    /* This is not quite the same API since the kernel always defines s6_addr16 and
       s6_addr32. This is not a violation of POSIX since POSIX says "at least the
       following member" and that holds true.  */
    # define __USE_KERNEL_IPV6_DEFS 1
    #else
    # define __USE_KERNEL_IPV6_DEFS 0
    #endif

    这样会导致sdk中的判断永远为否。

    这里面涉及到了,#ifndef 和 #if 的差别,简单讲,#ifndef  只管是否有这个定义,而不管这个值是真是假。而#if就不同了。

    总结:

    部分系统文件(特别是与其他系统文件相关的)还是不要放在源代码中好,指明最低编译器的版本即可。因为绝大部分编译器都是向后兼容的。除非特别老的代码。

  • 相关阅读:
    利用Oracle分析函数row_number和sys_connect_by_path实现多行数据合并为一行
    public string err属性
    table冻结表头和列[转]
    转:Js日期操作
    ASP.NET中JSON的序列化和反序列化
    javascript Date format(js日期格式化) [转]
    刚开通的博客
    调用图片
    散记兼容,需要整理
    ie6、div高度低于字体大小、则继承fontsize
  • 原文地址:https://www.cnblogs.com/huoqs/p/14277675.html
Copyright © 2020-2023  润新知