背景:
为了学习嵌入式,最近除了下载了 arm-linux-gcc,还需要编译 gdbserver,但是机子上的 gcc 无法编译,于是只好按 mooc 里的使用旧版本的 gcc 进行编译。
设备及软件信息:
VMware Workstation 15 Pro
Ubuntu 18.04
gcc-7.5.0
目的:
编译安装 gcc-4.7.4
详细过程:
1. 下载需要的源码包到当前目录
gcc-4.7.4.tar.gz mpfr-2.4.2.tar.bz2 gmp-4.3.2.tar.bz2 mpc-0.8.1.tar.gz
这一部分比较简单,不再赘述。需要注意的是当前版本 gcc 依赖软件的版本在 ./gcc-4.7.4/contrib/download_prerequisites 可以查阅,虽然官方推荐的是用这个脚本下载,但实际上似乎下载不了,故手动下载。
2. 创建需要的目录
需要创建 ./gcc-4.7.4/ ./gcc_build/
3. 下载一部分补丁到当前目录(行号对不上时可自行手动修改)
cfns.h.patch:用来修补 ./gcc-4.7.4/gcc/cp/cfns.h
@@ -53,6 +53,9 @@ __inline
static unsigned int hash (const char *, unsigned int);
#ifdef __GNUC__
__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
#endif
const char * libc_name_p (const char *, unsigned int);
/* maximum key range = 391, duplicates = 0 */
cfns.gperf.patch:用来修补 ./gcc-4.7.4/gcc/cp/cfns.gperf
@@ -22,6 +22,9 @@ __inline
static unsigned int hash (const char *, unsigned int);
#ifdef __GNUC__
__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
#endif
const char * libc_name_p (const char *, unsigned int);
%}
patch-gcc46-texi.diff:用来修补 ./gcc-4.7.4/gcc/doc/gcc.texi
--- ./gcc/doc/gcc.texi.orig 2017-03-01 16:56:48.000000000 -0800
+++ ./gcc/doc/gcc.texi 2017-03-01 17:03:38.000000000 -0800
@@ -86,9 +86,15 @@
@item GNU Press
@tab Website: www.gnupress.org
@item a division of the
-@tab General: @tex press@@gnu.org @end tex
+@tab General:
+@tex
+press@@gnu.org
+@end tex
@item Free Software Foundation
-@tab Orders: @tex sales@@gnu.org @end tex
+@tab Orders:
+@tex
+sales@@gnu.org
+@end tex
@item 51 Franklin Street, Fifth Floor
@tab Tel 617-542-5942
@item Boston, MA 02110-1301 USA
@@ -108,6 +114,7 @@
@sp 1
@insertcopying
4. 进行预处理
因为前前后后编译失败了很多次,所以每次把所有操作再做一遍很费事,因此在当前目录下写了个脚本 aaa.sh。
下面我会对脚本进行一定讲解,具体安装时可能每个人都要做一定的调整。
aaa.sh:
sudo rm -rf ./gcc-4.7.4/*
sudo rm -rf ./gcc_build/*
sudo tar zxf gcc-4.7.4.tar.gz
sudo cp mpfr-2.4.2.tar.bz2 ./gcc-4.7.4/
sudo cp gmp-4.3.2.tar.bz2 ./gcc-4.7.4/
sudo cp mpc-0.8.1.tar.gz ./gcc-4.7.4/
sudo patch -p0 ./gcc-4.7.4/gcc/cp/cfns.h cfns.h.patch
sudo patch -p0 ./gcc-4.7.4/gcc/cp/cfns.gperf cfns.gperf.patch
sudo patch -p0 ./gcc-4.7.4/gcc/doc/gcc.texi patch-gcc46-texi.diff
echo
find ./gcc-4.7.4/lib* -type f -name *.h | xargs grep -n " ucontext_ "
find ./gcc-4.7.4/lib* -type f -name *.h | xargs sudo sed -i "s/ ucontext_ / ucontext_t /g"
echo
find ./gcc-4.7.4/lib* -type f -name *.h | xargs grep -n " ucontext_$"
find ./gcc-4.7.4/lib* -type f -name *.h | xargs sudo sed -i "s/ ucontext_$/ ucontext_t/g"
echo
find ./gcc-4.7.4/lib* -type f -name *.h | xargs grep -n "struct ucontext "
find ./gcc-4.7.4/lib* -type f -name *.h | xargs sudo sed -i "s/struct ucontext /ucontext_t /g"
cd gcc-4.7.4
sudo sed -i "/wget/d" ./contrib/download_prerequisites
sudo ./contrib/download_prerequisites
cd ../gcc_build
第1~2行是清理目录,每次编译失败都要清理这两个目录。
第3~6行是解压 gcc 并且将需要的包拷进 gcc 目录下。第20行是把这个脚本中带有 wget 的行删除,因为我们已经把这些包手动下载了。第21行是执行它自带的这个脚本,这个脚本实际上做的也是解压工作。这里强烈建议用我这种方式把这3个包放进 gcc 目录里,而不是放到外面解压并手动编译,许多教程以及我看的 mooc 都是这么做的,但是这种行为被 GNU 官方 称为非常的 silly。
第7~9行把我刚刚说的3个补丁打上,没有的话 make 的时候会有 error。当然你也可以注释掉试试,说不定你的版本就没这个问题。
echo 换行不解释。
第11~18行是为了替换 struct ucontext。这个应该是已经不支持了,现在用的是 POSIX 标准的 ucontext_t。可以参考 Use ucontext_t not struct ucontext in linux-unwind.h files 。之所以写了3组是为了适应不同的情况,这个地方其实也可以打补丁,但是我觉得用命令行替换更好更方便。其中第3组是网上许多补丁完成的功能,但是在我的机子上有些特殊的情况比如 struct uncontext_ 这种,还有一些文件那些补丁没有覆盖到,所以使用了 find 命令进行查找。
第22行前往编译目录。
4. 进行编译
可以先创建个 log 文件,一会儿把 make 的屏幕输出重定向到这。
进入当前目录,执行 source ./aaa.sh 预处理,执行后自动进入 ./gcc_build,现在就要开始 configure、make、make install 组合拳了。
执行
sudo ../gcc-4.7.4/configure --prefix=/opt/gcc-4.7.4 --disable-multilib --disable-nls --enable-shared --enable-__cxa_atexit --enable-threads=posix --enable-language=c,c++ --enable-checking=release
语言你自己选,路径就是这个路径,其他参数反正我这边使用正常,网上不同人的教程参数基本都不一样,自己斟酌。
官方对配置参数有详细的解释:Installing GCC: Configuration
注意:我一直说的当前目录也就是 . 在我的机器上是 /opt,在这条命令里为了安全我使用的是绝对路径。
这条命令执行后应该成功创建了 Makefile。
执行
su
time make -j4 > /opt/log 2>&1
time 是为了计时,你也可以不要,后面的这个是把屏幕输出重定向到 /opt/log,也不是必要的。本质上就是 make -j4。
正常情况(一般都不正常)下可以编译成功,我用了40多分钟。有问题的话看 /opt/log 进行排查,就看最后10来行,找 error,或者直接执行
grep -n error: /opt/log
进行 debug。排查修改完后重新进行第4步,先预处理,然后……
5. 安装
执行
sudo make install
即可。