Ubuntu离线安装特定版本的gcc

发布于:2025-06-25 ⋅ 阅读:(23) ⋅ 点赞:(0)

Ubuntu离线安装特定版本的gcc

参考文章1文章2

  1. 下载gcc源码
    网站下载所需的gcc源码到本地
  2. 进入原名包所在目录,解压源码包,命令为
    tar -zxvf gcc-xxx.tar.gz
    
  3. 进入目录contrib/download_prerequisites,查看所需的依赖包
    gmp='gmp-6.1.0.tar.bz2'
    mpfr='mpfr-3.1.4.tar.bz2'
    mpc='mpc-1.0.3.tar.gz'
    isl='isl-0.16.1.tar.bz2'
    
    base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
    
    注释掉检查代码,亲测不注释也可以。
    # for ar in $(echo_archives)
    # do
    #     if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi
    #     [ -e "${directory}/${ar}" ]                                               \
    #         || ${fetch} --no-verbose -O "${directory}/${ar}" "${base_url}${ar}"       \
    #         || die "Cannot download ${ar} from ${base_url}"
    # done
    # unset ar
    
    # if [ ${verify} -gt 0 ]
    # then
    #     chksumfile="contrib/prerequisites.${chksum_extension}"
    #     [ -r "${chksumfile}" ] || die "No checksums available"
    #     for ar in $(echo_archives)
    #     do
    #         grep "${ar}" "${chksumfile}"                                          \
    #             | ( cd "${directory}" && ${chksum} )                              \
    #             || die "Cannot verify integrity of possibly corrupted file ${ar}"
    #     done
    #     unset chksumfile
    # fi
    # unset ar
    
    使用命令./contrib/download_prerequisites,添加依赖包。
    如果执行上述命令报错,需要执行如下命令在“gcc-7…0/”文件夹下下载依赖包:注意后面的需要改成相应的版本
    wget http://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
    wget http://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
    wget http://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
    wget http://gcc.gnu.org/pub/gcc/infrastructure/isl-0.16.1.tar.bz2
    
    再次./contrib/download_prerequisites,发现所有依赖包装完全
    在这里插入图片描述
  4. 编译并安装
    首先利用configure设置一些参数,比如安装路径,最终生成Makefile。
    方法一:
    mkdir build
    cd build
    
    用下面的命令生成makefile。注意 --prefix=/home/yueshanning/software/gcc7.5.0 用于自定义安装路径,否则默认是/usr/bin
    ../configure --enable-languages=c,c++ --disable-multilib --with-system-zlib --prefix=/home/yueshanning/software/gcc/7.5.0 --enable-threads=posix -enable-checking=release -disable-multilib
    
    或者
    ../configure --prefix=/home/yueshanning/software/gcc/7.5.0 --enable-checking=release --enable-languages=c,c++ --disable-multilib CFLAGS="-g -O0"
    
    方法二:
    不用进入build
    ./configure --enable-languages=c,c++ --disable-multilib --with-system-zlib --prefix=/home/yueshanning/software/gcc/7.5.0
    
    若成功应该生成Makefile
    在这里插入图片描述
    然后编译并安装
    make -j15
    make install
    

记录一下在Ubuntu24.04.2下各版本gcc编译时出现的错误

  • gcc9.3.0是唯一顺利的一个版本

  • gcc7.5.0和gcc6.5.0
    libsanitizer出现断言错误,(下面的log是编译8.1.0版本出现的错误,这类错误是这三个版本的共性问题)

    In file included from ../../../../libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc:194:
    ../../../../libsanitizer/sanitizer_common/sanitizer_internal_defs.h:317:72: 错误: size of array ‘assertion_failed__1160’ is negative
         typedef char IMPL_PASTE(assertion_failed_##_, line)[2*(int)(pred)-1]
                                                                            ^
    ../../../../libsanitizer/sanitizer_common/sanitizer_internal_defs.h:311:30: 附注: in expansion of macro ‘IMPL_COMPILER_ASSERT’
     #define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__)
                                  ^~~~~~~~~~~~~~~~~~~~
    ../../../../libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h:1475:3: 附注: in expansion of macro ‘COMPILER_CHECK’
       COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
       ^~~~~~~~~~~~~~
    ../../../../libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc:1160:1: 附注: in expansion of macro ‘CHECK_SIZE_AND_OFFSET’
     CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
     ^~~~~~~~~~~~~~~~~~~~~
    

    上述错误所涉及到以下几个文件的内容:
    libsanitizer/sanitizer_common/sanitizer_internal_defs.h

    #define UNIMPLEMENTED() UNREACHABLE("unimplemented")
    
    #define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__)
    
    #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
    
    #define IMPL_PASTE(a, b) a##b
    #define IMPL_COMPILER_ASSERT(pred, line) \
        typedef char IMPL_PASTE(assertion_failed_##_, line)[2*(int)(pred)-1]
    

    libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h

     #define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER)                       \
       COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
                      sizeof(((CLASS *) NULL)->MEMBER));                \
       COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) ==          \
                      offsetof(CLASS, MEMBER))
    

    原因大概是由于机器中一些类型所占的空间大小与代码中设置的断言不一致,所以会出现这个错误。更高级的版本比如9.3.0对这部分进行分情况断言。
    通过查阅资料,找到一些方法,比如在编译或者config时添加关闭sanitizer的选项,尝试了一下,不可以。也有文章说要修改源码使其适配本地机器,本人比较菜,看不懂这部分代码,不敢轻易改动。最终选择一个最激进的方法,在文件libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h中直接注释掉了相关断言,确实可以编译、安装成功。但是目前还不知道有没有副作用。暂时猜测可能会对libanitizer有些影响。接下来会持续更新,这样粗暴的解决方式是否会带来问题。

    #define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER)                       \
      COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) ==          \
                     offsetof(CLASS, MEMBER))
    
    // #define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER)                       \
    //   COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
    //                  sizeof(((CLASS *) NULL)->MEMBER));                \
    //   COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) ==          \
    //                  offsetof(CLASS, MEMBER))
    
    // For sigaction, which is a function and struct at the same time,
    // and thus requires explicit "struct" in sizeof() expression.
    
  • gcc-8.1.0 在出现上面所提及的断言问题之前,出现了一个找不到sys/ustat.h的致命错误。原因是现在已经将这个头文件移除了。错误位置为libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc中的下面这个位置

     #if SANITIZER_LINUX && !SANITIZER_ANDROID
       unsigned struct_ustat_sz = sizeof(struct ustat);
       unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
       unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
     #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
    

    我将gcc9.3.0的相应部分的代码复制过来,可以编译通过。

    // modified reference by 9.3.0
    #if SANITIZER_LINUX && !SANITIZER_ANDROID
      // Use pre-computed size of struct ustat to avoid <sys/ustat.h> which
      // has been removed from glibc 2.28.
    #if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \
      || defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \
      || defined(__x86_64__)
    #define SIZEOF_STRUCT_USTAT 32
    #elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
      || defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
    #define SIZEOF_STRUCT_USTAT 20
    #else
    #error Unknown size of struct ustat
    #endif
      unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
      unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
      unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
    #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
    
  • 上述出现的问题都出现在libsanitizer 文件中,今天下午尝试着把9.3.0版本的libsanitizer文件整个复制过来,重新编译通过了。目前来看这种办法比注释断言效果要好。


网站公告

今日签到

点亮在社区的每一天
去签到