Ubuntu离线安装特定版本的gcc
Ubuntu离线安装特定版本的gcc
参考文章1,文章2
- 下载gcc源码
在网站下载所需的gcc源码到本地 - 进入原名包所在目录,解压源码包,命令为
tar -zxvf gcc-xxx.tar.gz
- 进入目录
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/”文件夹下下载依赖包:注意后面的需要改成相应的版本
再次./contrib/download_prerequisites,发现所有依赖包装完全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
- 编译并安装
首先利用configure
设置一些参数,比如安装路径,最终生成Makefile。
方法一:
用下面的命令生成makefile。注意mkdir build cd build
--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
若成功应该生成Makefile./configure --enable-languages=c,c++ --disable-multilib --with-system-zlib --prefix=/home/yueshanning/software/gcc/7.5.0
然后编译并安装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 negativetypedef 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_ANDROIDunsigned 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 #endifunsigned 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