01.Alpine编译glibc
概要
本文档采用glibc2.28版本作为示例,模拟内网环境无法访问github等开源社区
为精简docker容器镜像,采用Alpine镜像,需要手动编译glibc源代码
制作编译好的glibc二进制文件
获取glibc二进制文件构建工具
# 内网环境可下载该工具包手动上传到服务器
git pull https://github.com/sgerrand/docker-glibc-builder.git
该构建工具中需要采用wget命令从第三方仓库下载glibc源代码,由于内网环境无法访问第三方仓库,我们需要对构建工具做一些修改
修改Dockerfile
本例采用修改过的openeuler-x86镜像,在原生的基础上安装了一些常用的命令例如vim、tar、telnet 等
FROM euleros-x86:202405V1
ENV DEBIAN_FRONTEND=noninteractive \
GLIBC_VERSION=2.28 \
PREFIX_DIR=/usr/glibc-compat
COPY configparams /glibc-build/configparams
COPY builder /builder
# 内网环境 手动下载glibc源代码上传至根目录
COPY glibc-2.28.tar.gz /glibc-2.28.tar.gz
# gcc bison make m4 都是编译所必须的命令
RUN yum -y install gcc bison make m4
ENTRYPOINT ["/builder"]
修改bulider脚本
#!/usr/bin/env bash
set -eo pipefail; [[ "$TRACE" ]] && set -x
main() {
# 声明 version 和 prefix 如果不存在入参指定version和prefix就使用环境变量 GLIBC_VERSION 和 PREFIX_DIR
declare version="${1:-$GLIBC_VERSION}" prefix="${2:-$PREFIX_DIR}"
: "${version:?}" "${prefix:?}"
{
# 此处只删除了使用wget从第三方仓库下载glibc的步骤
tar zxf /glibc-$version.tar.gz
mkdir -p /glibc-build && cd /glibc-build
"/glibc-$version/configure" \
--prefix="$prefix" \
--libdir="$prefix/lib" \
--libexecdir="$prefix/lib" \
--enable-multi-arch \
--enable-stack-protector=strong
make && make install
tar --dereference --hard-dereference -zcf "/glibc-bin-$version.tar.gz" "$prefix"
} >&2
[[ $STDOUT ]] && cat "/glibc-bin-$version.tar.gz"
}
main "$@"
构建编译glibc的镜像
# 首先进入Dockerfile文件同级目录
docker build -t "euler-glibc:2.28" .
运行 euler-glibc:2.28 镜像
# docker run --rm --env STDOUT=1 euler-glibc:2.28 {version} {prefix} > glibc-bin.tar.gz
# 上述命令的 {version} 和{prefix}即 builder脚本的入参,如果在Dockerfile中写好了环境变量,这两个值可以不要
# 直接运行该镜像,编译时间可能比较长,要稍微等待一段时间
docker run --rm --env STDOUT=1 euler-glibc:2.28 > glibc-bin.tar.gz
# 编译完成就会在当前文件夹内获得 名为 glibc-bin.tar.gz 的 libc二进制文件
制作alpine镜像apk包
获取apk包构建工具
# 内网环境同样手动下载 2.28 版本APKBUILD 有问题,建议直接使用2.35版本
git https://github.com/sgerrand/alpine-pkg-glibc.git
获取alpine镜像并配置apk源
构建apk包需要用的apk-sdk,apk是alpine的包管理工具,此处需要获取一个alpine镜像并配置apk仓库地址。
获取alpine镜像
可以直接从dockerhub拉取一个和alpine镜像,也可以下载rootfs自己构建,此处不赘述拉取过程配置apk源
# 此处是我自己构建的alpine镜像所以tag是v1,具体名字根据实际的填写
FROM alpine:v1
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && apk update && apk add build-base alpine-sdk编写完成Dockerfile之后构建该镜像并命名为
alpine:v2
修改APKBUILD文件
# Maintainer: Sasha Gerrand <alpine-pkgs@sgerrand.com>
pkgname="glibc"
pkgver="2.28"
_pkgrel="0"
pkgrel="0"
pkgdesc="GNU C Library compatibility layer"
arch="x86"
url="https://github.com/sgerrand/alpine-pkg-glibc"
license="LGPL"
source="$pkgname-bin.tar.gz
nsswitch.conf
ld.so.conf"
subpackages="$pkgname-bin $pkgname-dev $pkgname-i18n"
triggers="$pkgname-bin.trigger=/lib:/usr/lib:/usr/glibc-compat/lib"
package() {
echo "----------------------------package start"
echo "$pkgdir $srcdir $builddir"
mkdir -p "$pkgdir/lib" "$pkgdir/usr/glibc-compat/lib/locale" "$pkgdir"/usr/glibc-compat/lib64 "$pkgdir"/etc
cp -a "$srcdir"/usr "$pkgdir"
cp "$srcdir"/ld.so.conf "$pkgdir"/usr/glibc-compat/etc/ld.so.conf
rm "$pkgdir"/usr/glibc-compat/etc/rpc
rm -rf "$pkgdir"/usr/glibc-compat/bin
rm -rf "$pkgdir"/usr/glibc-compat/sbin
rm -rf "$pkgdir"/usr/glibc-compat/lib/gconv
rm -rf "$pkgdir"/usr/glibc-compat/lib/getconf
rm -rf "$pkgdir"/usr/glibc-compat/lib/audit
rm -rf "$pkgdir"/usr/glibc-compat/share
rm -rf "$pkgdir"/usr/glibc-compat/var
ln -s /usr/glibc-compat/lib/ld-linux-x86-64.so.2 ${pkgdir}/lib/ld-linux-x86-64.so.2
ln -s /usr/glibc-compat/lib/ld-linux-x86-64.so.2 ${pkgdir}/usr/glibc-compat/lib64/ld-linux-x86-64.so.2
ln -s /usr/glibc-compat/etc/ld.so.cache ${pkgdir}/etc/ld.so.cache
echo "----------------------------package end"
}
bin() {
echo "----------------------------bin start"
depends="$pkgname libgcc"
mkdir -p "$subpkgdir"/usr/glibc-compat
cp -a "$srcdir"/usr/glibc-compat/bin "$subpkgdir"/usr/glibc-compat
cp -a "$srcdir"/usr/glibc-compat/sbin "$subpkgdir"/usr/glibc-compat
echo "----------------------------bin end"
}
i18n() {
echo "----------------------------i18n start"
depends="$pkgname-bin"
arch="noarch"
mkdir -p "$subpkgdir"/usr/glibc-compat
cp -a "$srcdir"/usr/glibc-compat/share "$subpkgdir"/usr/glibc-compat
echo "----------------------------i18n end"
}
编写构建apk包的Dockerfile
FROM alpine:v2
LABEL maintainer="su.yingjun" email="i9xswanan@gmail.com"
VOLUME ["/home/docker/alpine-pkg-glibc","/tmp"]
# 创建构建用户
RUN adduser -D packager && addgroup packager abuild && echo 'packager ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/packager && chmod o+w /tmp
#RUN adduser -D -s /bin/sh build && echo "build:build2024" | chpasswd && adduser build abuild && apk add alpine-sdk build-base abuild cmake git
COPY APKBUILD /home/packager/APKBUILD
COPY glibc-bin.tar.gz /home/packager/glibc-bin.tar.gz
COPY glibc-bin.trigger /home/packager/glibc-bin.trigger
COPY ld.so.conf /home/packager/ld.so.conf
COPY nsswitch.conf /home/packager/nsswitch.conf
USER packager
WORKDIR /home/packager
RUN abuild-keygen -n --append --install
dockerbuild -t alpine-apk-build:v1 .
运行构建apk包容器
# 此处挂载目录的原因是方便取出apk包和公钥文件,也可以使用docker cp取出
docker run --rm -it -v /home/docker/alpine-pkg-glibc:/tmp alpine-apk-build:v1 sh
# 下方为登录容器后的命令 保证处于 /home/packager 目录下
abuild checksum
abuild -r
# 执行完成之后会在构建目录下出现 packages目录,该目录中存放打包好的apk文件,公钥文件存放在当前用户家目录下的.abuild 文件夹中,执行cp命令拷贝到挂载的目录中
cp ~/.abuild/*.rsa.pub ~/packages/glibc*.apk /tmp
# 退出容器
exit
参考资料
- GNU下载地址
- https://github.com/sgerrand/alpine-pkg-glibc
- https://github.com/sgerrand/docker-glibc-builder
- Alpine apk源
- Alpine Wiki
- https://www.youtube.com/watch?v=ibeqoQpO33w&t=697s
附录
abuild -r 构建流程
abuild 是 Alpine Linux 的构建工具,用于构建 APK 包。执行 abuild -r 命令的全流程涉及多个步骤,包括准备构建环境、构建包、运行测试和创建最终的 APK 包。以下是 abuild -r 的详细流程:
1. 准备构建环境
更新并安装依赖
abuild会根据APKBUILD文件中的依赖定义安装构建所需的包。
初始化环境变量
- 设置必要的环境变量,如
srcdir、builddir、pkgdir等。
2. 提取源代码
- 下载源代码:根据
APKBUILD文件中的source字段下载源代码和补丁文件。 - 校验文件完整性:通过校验和文件(如
sha512sums)验证下载的文件是否完整。 - 解压源代码:将下载的源代码文件解压到
srcdir。
3. 运行构建流程
prepare() 函数
- 这是一个可选的函数,用于在实际构建之前应用补丁或进行其他准备工作。
build() 函数
- 执行构建过程。这通常包括配置、编译和链接源代码。
- 具体步骤由
APKBUILD文件中的build()函数定义。例如,可能使用./configure脚本、make命令等。
4. 安装步骤
package() 函数
- 安装构建好的文件到
pkgdir。 - 设置文件的权限和属性。
- 安装文档文件(如
README、LICENSE等)。
5. 创建 APK 包
abuild会将pkgdir中的内容打包成一个 APK 文件。- 生成的 APK 文件会放在
packages目录下。
6. 签名 APK 包
- 如果你有签名密钥,
abuild会对生成的 APK 包进行签名。签名密钥通常存储在~/.abuild/目录中。
7. 运行测试(可选)
abuild也可以运行测试(如果定义了check()函数)。这通常在构建后执行,用于验证包的正确性。
8. 清理
- 清理临时文件和目录,确保构建环境干净。
01.Alpine编译glibc的更多相关文章
- alpine编译安装tengine,并使用supervisor启动
Alpine是一个小型的linux系统,官方docker镜像只有不到5MB,非常适合作为容器镜像. Alpine Linux is a security-oriented, lightweight L ...
- uboot-2012.04.01移植编译前准备
一:准备移植1.从下面的官网下载uboot-2012.04.012.建立sourceinsight工程 a.解压并在E:\colin weidongshan\transplant_u-boot-201 ...
- uboot 2013.01 s3c6400编译失败
通常我们对s3c6410平台开发u-boot是在s3c6400的基础上修改而成的,但是从uboot 2013.01这个版本之后的版本都把smdk6400对应的配置给删除了. 这是因为该版本smdk64 ...
- [笔记]Modelsim系列01:编译Altera库的方法
意义:一劳永逸,不用每次对那些包含Quartus II生成文件的工程进行功能仿真时,都需要重新编译一堆东西.节约时间成本. 版本:ModelSim SE 6.5d 打开Modelsim软件,默认会打开 ...
- 深入理解Java虚拟机 #01# 自己编译JDK
x 首先用书上的脚本尝试,失败. 之后根据源文件的 README 编译,抛出: root@linux:/opt/openjdk# sh ./get_source.sh ERROR: Need init ...
- 在openwrt 17.01上编译最新nginx 1.14.2的笔记
openwrt 17.01源码对应的nginx版本是1.10.2,有些新功能没有,所以需要升级到nginx 1.14.2最新的稳定版 https://github.com/macports/macpo ...
- 如何使用新的glibc来编译自己的程序
http://www.sysnote.org/2015/08/25/use-new-glibc/ 通常情况下我们都是直接使用glibc提供的一些库函数,但是某些特殊的情况,比如要修改glibc的一些代 ...
- 009全志R16平台tinav3.0下编译不过的问题
009全志R16平台tinav3.0下编译不过的问题 2018/11/13 11:39 版本:V1.0 开发板:SC3817R SDK:tina v3.0 1.01原始编译全志r16平台tinav3. ...
- 编译软件基础知识(1/2) via LinuxSir
内容来自LinuxSir: 如果不出意外的话,会出现say.so => not found. 这时的./test是不能运行的.但至少说明程序运行时是需要这个库的.那为什么找不到这个库呢?那就让我 ...
- X86上搭建交叉工具链,来给龙芯笔记本编译本地工具链(未完待续)
故事的背景是,我买了一台龙芯2F的笔记本来装B. 为什么说是装B呢?因为不但操作系统是Linux,而且CPU还是龙芯的. 一般人有这么酷的装备吗?简直是装B大圣啊. 这里一定要申明一点,本人不是IT技 ...
随机推荐
- locust常用的配置参数【locust版本:V1.1.1】
locust 官网文档地址:https://docs.locust.io/en/stable/configuration.html Locust QQ 群: 执行命令如: master: locust ...
- kolla-ansible部署OpenStack Train版技术方案
简单架构示意 项目目标 1. 实现容器化部署docker+ Ansible+openstack-tarin 2. 使用keeplived监控nova服务实现在单台服务器宕机的情况下能迅速切断连接减轻平 ...
- 红日安全vulnstack (一)
网络拓扑图 靶机参考文章 CS/MSF派发shell 环境搭建 IP搭建教程 本机双网卡 65网段和83网段是自己本机电脑(虚拟机)中的网卡, 靶机外网的IP需要借助我们这两个网段之一出网 Kali ...
- Oracle SQL 创建一个简单的存储过程procedure
Oracle 简单的创建一个存储过程procedure 如果学过别的语言,例如java,c这些,那么其实很好理解,其实就是面向数据库的操作 简单的例子如下: --创建或者重写存储过程 create o ...
- 【ASPLOS 2022】机器学习访存密集计算编译优化框架AStitch,大幅提升任务执行效率
简介: 近日,关于机器学习访存密集计算编译优化框架的论文<AStitch: Enabling A New Multi-Dimensional Optimization Space for Mem ...
- 阿里云飞天论文获国际架构顶会 ATC 2021最佳论文:全球仅三篇
简介: 近日,计算机系统结构国际顶级学术会议 USENIX ATC在线上举行.ATC 始办于1992年,是由USENIX组织的计算机系统领域的顶级会议,至今已成功举办31届,计算机系统领域中Oak语言 ...
- [GF] 与 Laravel 设计相近的 Golang 框架 GoFrame
在 GoFrame (gogf/gf) 框架中有明确的代码分层设计,分别是 api, service, dao, model. model (结构模型)一般由工具自动生成,用于定义数据结构,只可被 m ...
- dotnet 推荐一个使用 Json 直接路由通讯的 IPC 库
本文将和大家推荐一个我所在团队开源的本机多进程通讯 IPC 库,此 IPC 支持使用 JSON 格式进行直接路由通讯,具有使用方便,稳定性高,性能好的优点 这是我所在的团队在 GitHub 上使用最友 ...
- 2019-8-31-C#-自动翻页-PPT-测试脚本
title author date CreateTime categories C# 自动翻页 PPT 测试脚本 lindexi 2019-08-31 16:55:58 +0800 2019-08-1 ...
- DE10-Lite锁相环使用教程
DE10-Lite锁相环使用教程 目标:本文讲述如何在Quartus里设置和例化一个锁相环. 引言 锁相环(PLL)是一种闭环频率控制电路,用于比较压控振荡器的输入信号和输出信号之间的相位差. 负反馈 ...