由于父亲大人病重,自上月上旬以来基本停止一切开发方向的活动,无论是开源库也好、工具也好,还是 blog 文字也好,都基本停滞。偶尔会有一些不费事的更新,如同本文内容这样的。
要等。
想要有尊严地活着,是多么地不容易啊。
由于时间关系,本文暂时仅作列举而不讨论编程(脚本)细节。
安装 gcc-13
上个月某一天,更新 homebrew 时偶然注意到 gcc-13 都发布了。尽管它有些啥新东西这阵子根本没关注,但也还是更了。
然后就涉及到 Linux Server 上的问题。我主要的 server 平台基本都是 Ubuntu 22.04 Server,这比较省心。然而这上面经过研究发现无法通过 apt/ppa 安装 gcc-13。
起初以为过些时日 ppa 上就会更新。但它们没有。于是抽空去检查了下,没太认真,得到的结论是:如果升级到 Ubuntu 23.04 Server 的话,那么就可以直接安装 gcc-13,也可以通过 ppa 安装;但对于这之前到发行版,就没有可能性了,除非通过源码自行编译。
Ubuntu 23.04 - apt
在 Ubuntu 23.04 上,可以直接安装 gcc-13。这有两种方法:借助于 build-essential 伪 package;直接安装 gcc-13。
它们的 bash 指令分别如下:
1
2
3
4
sudo apt-get install build-essentail
sudo apt-get install g++-13 gcc-13-locales g++-multilib
两者没有什么区别,但后者或许会有 alternate links 破损的可能性,不建议那么做,除非你手工 update-alternate。
Ubuntu 22.04 and earlier - source
在 Ubuntu 早期版本,或者其他 Linux 发行本,你可能需要从源码编译 gcc,这会需要一些附加操作来解决 links 问题,即将编译后的二进制融合到系统中的问题。
本文中针对 Ubuntu Server 做出相应解决,其他发行版则需要自行研究。
编译 gcc 源码
首先是 gcc 源码的编译与构建,其本身是可以精简如下:
1
2
3
4
5
6
7
8
9
tar xzf gcc-4.6.2.tar.gz
cd gcc-4.6.2
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
$PWD/../gcc-4.6.2/configure --prefix=$HOME/GCC-4.6.2 --enable-languages=c,c++,fortran,go
make
make install
参阅 https://gcc.gnu.org/wiki/InstallingGCC
但,实际上用在 devops 中的脚本是不可能这么简单的,还需要检测一系列的冥等性问题。所以我这里给出一个范本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
install_gcc_13_src() {
echo && headline " - $(fn_name_dyn)"
install_gcc # bundled gcc first for building gcc-13 from sources
ig13src
upd_alter_gcc
}
install_gcc() {
echo && headline "$(fn_name_dyn)"
# $SUDO add-apt-repository --yes -u ppa:ubuntu-toolchain-r/test
# install_packages 等价于 sudo apt-get install -y
install_packages build-essential gcc-locales g++-multilib \
git \
gdb gdbserver \
automake bison flex xsltproc libfl-dev \
libtool pkg-config \
make || :
upd_alter_gcc
}
ig13src() {
SRCDIR=$HOME/gcc-source
INSTDIR=$HOME/gcc-install
BUILDDIR=./gcc-1x-build
VER=gcc-13
VERSION=gcc-13.1.0
# VER=gcc-12
# VERSION=gcc-12.2.0
[ -d $SRCDIR ] || {
# tip set git insteadOf
git config --global url."https://gcc.gnu.org/".insteadOf https://gcc.gnu.org
# tip clone gcc sources
git clone https://gcc.gnu.org/git/gcc.git $SRCDIR
}
cd $SRCDIR/
# git branch -a | grep $VER
# git checkout remotes/origin/releases/$VERSION
git checkout releases/$VERSION
# instead of: ./contrib/download_prerequisites
apt-cache search MPFR | grep dev
$SUDO apt-get install -y libmpfrc++-dev
apt-cache search MPC | grep dev
$SUDO apt-get install -y libmpc-dev
apt-cache search GMP | grep dev
$SUDO apt-get install -y libgmp-dev
$SUDO apt-get install -y gcc-multilib
echo && gcc -v && echo && ls -l $(which gcc) && echo
[ -d $BUILDDIR ] || mkdir $BUILDDIR
cd $BUILDDIR
[ -f Makefile ] ||
../configure --prefix=$INSTDIR --enable-languages=c,c++ # ,fortran,go
if [ ! -x $INSTDIR/bin/gcc ]; then
[ -f /swapfile ] || {
# $SUDO dd if=/dev/zero of=/swapfile bs=64M count=16 # 1GB swap file
$SUDO dd if=/dev/zero of=/swapfile bs=64M count=64 # 4GB swap file
# $SUDO dd if=/dev/zero of=/swapfile bs=64M count=320 # 20GB swap file
$SUDO mkswap /swapfile
}
$SUDO swapon --show | grep -q '/swapfile' || $SUDO swapon /swapfile
$SUDO swapon --show
make -j4 # decerase the cores so that reduce the memery usages to avoid out of memory whenn compiling
make install
[ -f /swapfile ] && $SUDO swapoff /swapfile && $SUDO rm /swapfile
fi
ig13local
}
ig13local() {
PREFIX=/usr/local/lib/gcc-$VERSION
if [ ! -L $PREFIX ]; then
# $SUDO cp -R $INSTDIR $PREFIX
$SUDO ln -sf $INSTDIR $PREFIX
$SUDO ln -sf $PREFIX/bin/gcc /usr/local/bin/gcc-13
$SUDO ln -sf $PREFIX/bin/g++ /usr/local/bin/g++-13
#
# To run an executable compiled with this gcc, PRELOAD its lib64/ directory:
# LD_LIBRARY_PATH=/usr/local/lib/gcc-13.1.0/lib64 ./hello
[ -f /etc/profile.d/gcc-$VERSION ] || $SUDO echo "LD_LIBRARY_PATH=$PREFIX/lib64" >/etc/profile.d/gcc-$VERSION
fi
upd_alter_gcc
}
upd_alter_gcc() {
$SUDO update-alternatives --list gcc || :
$SUDO update-alternatives --list g++ || :
W=/usr/bin/gcc-7 && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 90 --slave /usr/bin/g++ g++ "${W//gcc/g++}" && V="$W"
W=/usr/bin/gcc-9 && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 90 --slave /usr/bin/g++ g++ "${W//gcc/g++}" && V="$W"
W=/usr/bin/gcc-10 && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 90 --slave /usr/bin/g++ g++ "${W//gcc/g++}" && V="$W"
W=/usr/bin/gcc-11 && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 90 --slave /usr/bin/g++ g++ "${W//gcc/g++}" && V="$W"
W=/usr/bin/gcc-12 && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 90 --slave /usr/bin/g++ g++ "${W//gcc/g++}" && V="$W"
W=/usr/bin/gcc-13 && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 90 --slave /usr/bin/g++ g++ "${W//gcc/g++}" && V="$W"
W="$(which gcc-11)" && WX="$(which g++-11)"
[ "$W" != "" ] && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 60 --slave /usr/bin/g++ g++ $WX && V="$W"
W="$(which gcc-12)" && WX="$(which g++-12)"
[ "$W" != "" ] && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 50 --slave /usr/bin/g++ g++ $WX && V="$W"
W="$(which gcc-13)" && WX="$(which g++-13)"
[ "$W" != "" ] && [ -x $W ] && $SUDO update-alternatives --install /usr/bin/gcc gcc $W 49 --slave /usr/bin/g++ g++ $WX && V="$W"
echo
# echo 1 | $SUDO update-alternatives --config gcc
[ "$V" != "" ] && $SUDO update-alternatives --set gcc "$V"
echo
gcc --version
echo
g++ -v
echo
}
headline, install_packages 等等是 devops 工具脚本函数,大部分源码已经公开在 bash.sh 中,可以参阅,亦可自行改写。
需要说明的内容如下:
make -j4
我是在一台 vagrant VM 上调试上述脚本的,该 VM 拿到了 8 core 8GB Memory,但一开始编译总是崩掉。后来我注意到 swap file 问题,所以 make -j4 的前面和后面分别有打开交换文件、回收交换文件的脚本嵌入。除此之外,使用 make -j 仍然继续崩,所以必须用 -j4
来限制 make 使用的 CPU 核心数,否则依然会内存不足。
如果发生内存不足,那就要继续缩减核心数。但 VM 不要小于 4 core 8GB,否则恐怕减无可减都无法完成编译。
ig13local
为了防止污染,我们首先将 gcc 编译到一个临时的安装目录。即设置 --prefix=$HOME/gcc13-install
完成 configure
,从而让 make install
将最终的有效安装文件全部复制到 $HOME/gcc13-install
中,再通过 ig13local
来真正安装到系统中。
ig13local 的细节值得注意,针对 Ubuntu / Debian 体系,它要将安装文件放到 /usr/local/lib/gcc-13.1.0
之下,然后在 /usr/local/bin/
中建立 gcc-13
, g++-13
的符号链接,最后通过 update-alternative config 将这两个符号链接绑定到 /usr/bin/gcc
之中。
/usr/bin/gcc
会跟踪多个版本的 gcc ,并选择活动的替代品来提供标准 gcc 功能。
这里原本有一堆需要解说的内容。
但鉴于我没有时间讲解,那就自己看源码、自己理解吧。
小结
暂时写这么多。
需要完整的 bootstrap.sh 源码的话,留言或者开 issue,如果真的有那么多人需要,我就抽空整理 vagrant folder 发布出来。
留下评论