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技 ...
随机推荐
- Linux命令之查找CPU资源利用情况(lscpu和top详解)
1.lscpu命令:获取CPU架构完整详细信息,例如架构信息,CPU模式,CPU频率,CPU核心数.线程数.缓存大小. 在终端输入"lscpu": 参数详解: [Architect ...
- 谢老师2024春 - Day1:组合数学
Day1:组合数学 A - P5520 [yLOI2019] 青原樱 隔板法: 已选择的位置:\(m\) 棵樱花树. 未选择的位置:\(n-m\) 个空位置 板的数量(一棵樱花树就是一个板):\(m\ ...
- 云钉一体:EventBridge 联合钉钉连接器打通云钉生态
简介:今天,EventBridge 联合钉钉连接器,打通了钉钉生态和阿里云生态,钉钉的生态伙伴可以通过通道的能力驱动阿里云上海量的计算力. 作者:尘央 背景 "以事件集成阿里云,从 Eve ...
- Serverless Kubernetes 落地实践
简介:如何通过原生 Kubernetes 提供 Serverless 能力?如何借力丰富的云原生社区生态?本文将给大家介绍一下我们在 Serverless Kubernetes 上的落地实践. 作者 ...
- Dataphin核心功能(四):安全——基于数据权限分类分级和敏感数据保护,保障企业数据安全
简介:<数据安全法>的发布,对企业的数据安全使用和管理提出了更高的要求.Dataphin提供基于数据分级分类和数据脱敏的敏感数据识别和保护能力,助力企业建立合规的数据安全体系,保障企业数据 ...
- 日志审计携手DDoS防护助力云上安全
简介: 本文主要介绍日志审计结合DDoS防护保障云上业务安全的新实践. 日志审计携手DDoS防护助力云上安全 1 背景介绍 设想一下,此时你正在高速公路上开车去上班,路上还有其他汽车,总体而言,大家 ...
- 用python编写向通信产品发送AT指令的程序实例
一.安装pyserial包pip install pyserial 二.实例代码 # -*- coding: utf-8 -*- import time import hashlib from ser ...
- UOS 开启 VisualStudio 远程调试 .NET 应用之旅
本文记录的是在 Windows 系统里面,使用 VisualStudio 2022 远程调试运行在 UOS 里面 dotnet 应用的配置方法 本文写于 2024.03.19 如果你阅读本文的时间距离 ...
- Mysql带条件取多条随机记录
有个文章段落表part,有两种类型的段落,即part_type取1或2,要从表中随机取多条任意类型的段落,比如3条. 方法一 ORDER BY后接RAND() select * from part w ...
- 有意思!一个关于 Spring 历史的在线小游戏
发现 Spring One 的官网上有个好玩的彩蛋,分享给大家! 进到Spring One的官网,可以看到右下角有个类似马里奥游戏中的金币图标. 点击该金币之后,会打开一个新的页面,进入下面这样一个名 ...