前言 @

此文讲解一下大部分源码编译的过程和常用linux库的编译方法

一般而言,基本的编译工具包括make/cmake、gcc/g++/clang、ld等

在 Debian/Ubuntu 系统上,可以安装 build-essential

sudo apt-get install build-essential

一般的软件包都会提供configure​ 脚本,其核心作用是检测系统环境并生成适配的构建文件

可以通过./configure --help​ 来查看其脚本的帮助文档,也可以直接使用默认配置执行./configure

但一般默认配置会将程序安装到 /usr/local​ 目录(可执行文件在 /usr/local/bin​,库在 /usr/local/lib 等),以下提供一些常用的参数

参数 作用 示例
--prefix=PATH 指定安装路径(最常用) ./configure --prefix=/opt/myapp
--enable-FEATURE 启用某个功能 ./configure --enable-ssl
--disable-FEATURE 禁用某个功能 ./configure --disable-gui
--with-LIB=PATH 指定依赖库的路径(库不在默认位置时) ./configure --with-openssl=/usr/local/ssl
--without-LIB 不使用某个可选库 ./configure --without-zlib

编译gcc @

  • 编译

wget http://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.gz	# 自己选择需要安装的版本

tar -zxvf gcc-11.2.0.tar.gz
cd gcc-11.2.0
./contrib/download_prerequisites		# 下载依赖包

# 生成构建文件
mkdir build && cd build/
../configure -enable-checking=release -enable-languages=c,c++ -disable-multilib

# --prefix=/usr/local 配置安装目录
# –enable-languages表示你要让你的gcc支持那些语言,
# –disable-multilib不生成编译为其他平台可执行代码的交叉编译器。
# –disable-checking生成的编译器在编译过程中不做额外检查,
# 也可以使用*–enable-checking=xxx*来增加一些检查

make -j$(nproc)    # 并发编译(取决于机器核心数)
make install
  • 配置
# 配置全局可用
ln -s /usr/local/bin/gcc /usr/bin/gcc
ln -s /usr/local/bin/g++ /usr/bin/g++

# 查看当前的动态库
strings /usr/lib64/libstdc++.so.6 | grep CXXABI
rm -f /usr/lib64/libstdc++.so.6
ln -s /usr/local/lib64/libstdc++.so.6.0.29 /usr/lib64/libstdc++.so.6

# 查看更新后的动态库
strings /usr/lib64/libstdc++.so.6 | grep CXXABI
# 安装后的动态库会位于/usr/local/lib64目录下,
# 其他版本在该目录下寻找对应的动态库libstdc++.so.6.X.XX

编译基于musl的gcc @

  • 拉取代码仓库
# 克隆某个指定分支的最近一次commit
git clone --depth 1 https://github.com/richfelker/musl-cross-make
  • 配置config.mak
cd musl-cross-make && cp config.mak.dist config.mak	# 创建config.mak文件

# vim打开config.mak进行配置
TARGET = x86_64-linux-musl    # 用来设置编译出来的GCC是要用来编译哪个平台的程序
GCC_VER = 11.2.0    		  # 变量用来指定GCC的版本

# 用来设置编译选项。-g0是要关闭调试信息;-O3可进行运算速度优先的优化。-s可以用来禁用符号表(symbol table),缩减运行档的文件大小
COMMON_CONFIG += CFLAGS="-g0 -O3" CXXFLAGS="-g0 -O3" LDFLAGS="-s"

# 用来设置GCC的功能
GCC_CONFIG += --enable-default-pie --enable-static-pie
  • 编译
# 默认编译的结果在output
make -j $(nproc) && make install

# 安装
sudo cp -r output /opt/musl

# 快速修改/opt/musl目录下函数库文件的所在路径
sudo find /opt/musl -iname "*.la" -type f -exec sed -i "s/libdir='/libdir='\/opt\/musl/g" "{}" \;
# 将.la文件的installed=yes改为installed=no
sudo find /opt/musl -iname "*.la" -type f -exec sed -i "s/installed=yes/installed=no/g" "{}" \;
  • 使用交叉编译工具编译
export CC="/opt/musl/bin/x86_64-linux-musl-gcc -static"
./Configure no-shared linux-x86_64 --prefix="$(pwd)/output" && make clean && make -j$(nproc) && make install

编译安装phantomjs @

  • 安装依赖
sudo apt-get install build-essential g++ flex bison gperf ruby perl \
  libsqlite3-dev libfontconfig1-dev libicu-dev libfreetype6 libssl-dev \
  libpng-dev libjpeg-dev python libx11-dev libxext-dev

git clone git://github.com/ariya/phantomjs.git
  • phantomjs​ 依赖的 qtwebkit​,在 arm64 编译时存在 bug,需要修改源码后编译
# vim src/qt/qtwebkit/Source/JavaScriptCore/API/JSStringRef.h

--- webkitgtk-2.4.11.orig/Source/JavaScriptCore/API/JSStringRef.h    2016-04-10 08:48:36.000000000 +0200
+++ webkitgtk-2.4.11/Source/JavaScriptCore/API/JSStringRef.h    2017-12-20 23:04:55.000000000 +0100
@@ -27,6 +27,7 @@
 #define JSStringRef_h

 #include <JavaScriptCore/JSValueRef.h>
+#include <uchar.h>

 #ifndef __cplusplus
 #include <stdbool.h>
@@ -43,7 +44,7 @@
 @typedef JSChar
 @abstract A Unicode character.
 */
-    typedef unsigned short JSChar;
+    typedef char16_t JSChar;
 #else
     typedef wchar_t JSChar;
 #endif
  • 编译
cd phantomjs
git checkout 2.1.1
git submodule init
git submodule update
# qt-config 的路径是上面 openssl 编译后库的路径
python build.py --qt-config="-L/usr/local/ssl/lib" --qt-config="-I/usr/local/ssl/include" --qt-config="-no-pch"

编译zlib库 @

  • 查看当前版本
#查看当前动态库版本
strings /lib64/libz.so.1 |grep "ZLIB*"
  • 编译zlib
#下载zlib编译安装
wget http://www.zlib.net/fossils/zlib-1.2.9.tar.gz
tar zxvf zlib-1.2.9.tar.gz
cd zlib-1.2.9/ && ./configure && make && make install

#创建软连接
cp libz.so.1.2.9 /usr/lib64/
cd /usr/lib64/
rm -f libz.so.1
ln -s  libz.so.1.2.9 libz.so.1

#确认新版本是否存在
strings /lib64/libz.so.1 |grep "ZLIB*"

编译安装openssl @

wget https://www.openssl.org/source/openssl-1.0.2l.tar.gz --no-check-certificate
tar -xzvf openssl-1.0.2l.tar.gz
cd openssl-1.0.2l && ./config shared && make install    # shared编译动态链接库