在 LFS 和 BLFS 中,许多软件包使用内部附带的 libtool 副本,以便在各种 Unix 平台上构建。这些平台包括 AIX、Solaris、IRIX、HP-UX、Cygwin 以及 Linux。该工具的起源相当久远,其设计初衷是在比现代 Linux 系统功能更弱的系统上管理库。
在 Linux 系统上,libtool 特定的文件通常是不需要的。通常,库在构建过程的链接阶段被指定。由于 Linux 系统对可执行文件和动态库使用 可执行与可链接格式(ELF),完成该任务所需的信息已嵌入在文件中。链接器和程序加载器都可以查询相应的文件,并正确地链接或执行程序。
静态库在 LFS 和 BLFS 中很少使用。而且,如今大多数软件包将链接静态库所需的信息存储在 .pc 文件中,而不是依赖 libtool。pkg-config --static --libs 命令会输出足够的标志,供链接器在无需任何 libtool 魔法的情况下链接静态库。
问题在于,libtool 通常会为软件包库创建一个或多个文本文件,称为 libtool 存档。这些小型文件扩展名为“.la”,包含的信息与嵌入在库或 pkg-config 文件中的信息类似。当构建使用 libtool 的软件包时,构建过程会自动查找这些文件。有时 .la 文件可能包含构建期间使用但未安装的静态库的名称或路径,那么构建过程将因 .la 文件引用了系统中不存在的内容而中断。同样,如果软件包更新后不再使用 .la 文件,旧的 .la 文件也会导致构建过程失败。
解决方案是移除 .la 文件。但有一个例外。某些软件包,例如 ImageMagick-7.1.2-13,使用 libtool 函数 lt_dlopen,在执行期间按需加载库,并在运行时解析其依赖关系。在这种情况下,应保留 .la 文件。
下面的脚本会移除所有不需要的 .la 文件,并将它们保存到一个目录中(默认为 /var/local/la-files),而非正常的库路径中。它还会搜索所有 pkg-config 文件(.pc),查找其中嵌入的对 .la 文件的引用,并将其修正为构建应用程序或库时所需的常规库引用。您可以根据需要运行该脚本,以清理可能引发问题的目录。
cat > /usr/sbin/remove-la-files.sh << "EOF"
#!/bin/bash
# /usr/sbin/remove-la-files.sh
# Written for Beyond Linux From Scratch
# by Bruce Dubbs <bdubbs@linuxfromscratch.org>
# 确保以 root 权限运行
if test "${EUID}" -ne 0; then
echo "Error: $(basename ${0}) must be run as the root user! Exiting..."
exit 1
fi
# 确保 PKG_CONFIG_PATH 在 sudo 丢弃后仍已设置
source /etc/profile
OLD_LA_DIR=/var/local/la-files
mkdir -p $OLD_LA_DIR
# 只搜索 /opt 中的目录,但不搜索指向目录的符号链接
OPTDIRS=$(find /opt -mindepth 1 -maxdepth 1 -type d)
# 将所有找到的 .la 文件移出到另一个目录
find /usr/lib $OPTDIRS -name "*.la" ! -path "/usr/lib/ImageMagick*" \
-exec mv -fv {} $OLD_LA_DIR \;
###############
# 修复可能包含 .la 引用的任何 .pc 文件
STD_PC_PATH='/usr/lib/pkgconfig
/usr/share/pkgconfig
/usr/local/lib/pkgconfig
/usr/local/share/pkgconfig'
# 对于每个可能有 .pc 文件的目录
for d in $(echo $PKG_CONFIG_PATH | tr : ' ') $STD_PC_PATH; do
# 对于每个 .pc 文件
for pc in $d/*.pc ; do
if [ $pc == "$d/*.pc" ]; then continue; fi
# 检查包含 .la 引用的行中的每个单词
for word in $(grep '\.la' $pc); do
if $(echo $word | grep -q '.la$' ); then
mkdir -p $d/la-backup
cp -fv $pc $d/la-backup
basename=$(basename $word )
libref=$(echo $basename|sed -e 's/^lib/-l/' -e 's/\.la$//')
# 修复 .pc 文件
sed -i "s:$word:$libref:" $pc
fi
done
done
done
EOF
chmod +x /usr/sbin/remove-la-files.sh