构建流程
预安装
安装必要的工具
sudo dnf install gcc rpm-build rpm-devel rpmlint make python bash coreutils diffutils patch rpmdevtools -y
初始化构建目录
rpmdev-setuptree
在家目录下会生成一个文件夹 rpmbuild
[root@fedora ~]# tree ~/rpmbuild/
/root/rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
创建 spec 文件
前往 ~/rpmbuild/SPECS
下,使用 rpmdev-newspec
可以基于默认模板生成一份 spec 文件
rpmdev-newspec -o pkg-name.spec
构建
使用 rpmbuild
命令可以立即构建rpm包
rpmbuild -b[action] pkg-name.spec
其中 [action] 是构建动作,有以下几个选项
选项 | 说明 |
---|---|
-bp | #只执行spec的%pre 段(解开源码包并打补丁,即只做准备) |
-bc | #执行spec的%pre和%build 段(准备并编译) |
-bi | #执行spec中%pre,%build与%install(准备,编译并安装) |
-bl | #检查spec中的%file段(查看文件是否齐全) |
-ba | #建立源码与二进制包(常用) |
-bb | #只建立二进制包(常用) |
-bs | #只建立源码包 |
构建细节
源包
源包: https://github.com/vufa/deepin-wine-wechat-arch
解包后,目录层级如下:
[x@fedora 下载]$ tree fedora-deepin-wechat-3.4.0.38
fedora-deepin-wechat-3.4.0.38
├── opt
│ └── apps
│ └── com.qq.weixin.deepin
│ └── files
│ ├── dlls
│ │ ├── gdi32.dll.so
│ │ ├── gdi32.so
│ │ ├── gdiplus.dll.so
│ │ ├── imm32.dll.so
│ │ ├── ntdll.dll.so
│ │ ├── ntdll.so
│ │ ├── ole32.dll.so
│ │ ├── qcap.dll.so
│ │ ├── qcap.so
│ │ ├── user32.dll.so
│ │ ├── user32.so
│ │ ├── winex11.drv.so
│ │ └── ws2_32.dll.so
│ ├── files.7z
│ ├── files.md5sum
│ └── run.sh
└── usr
└── share
├── applications
│ └── com.qq.weixin.deepin.desktop
└── icons
└── hicolor
├── 16x16
│ └── apps
│ └── com.qq.weixin.deepin.svg
├── 24x24
│ └── apps
│ └── com.qq.weixin.deepin.svg
├── 32x32
│ └── apps
│ └── com.qq.weixin.deepin.svg
├── 48x48
│ └── apps
│ └── com.qq.weixin.deepin.svg
└── 64x64
└── apps
└── com.qq.weixin.deepin.svg
20 directories, 20 files
查看项目入口
查看起动器: usr/share/applications/com.qq.weixin.deepin.desktop
#!/usr/bin/env xdg-open
[Desktop Entry]
Encoding=UTF-8
Type=Application
X-Created-By=Deepin WINE Team
Categories=chat;Network;
Icon=com.qq.weixin.deepin
Exec="/opt/apps/com.qq.weixin.deepin/files/run.sh"
Name=WeChat
Name[zh_CN]=微信
Comment=Tencent WeChat Client on Deepin Wine
StartupWMClass=wechat.exe
MimeType=
可以知道 程序运行入口是 opt/apps/com.qq.weixin.deepin/files/run.sh
查看 run.sh
文件
#!/bin/sh
# Copyright (C) 2016 Deepin, Inc.
#
# Author: Li LongYu <lilongyu@linuxdeepin.com>
# Peng Hao <penghao@linuxdeepin.com>
# Vufa <countstarlight@gmail.com>
version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
BOTTLENAME="Deepin-WeChat"
APPVER="3.2.1.154deepin14"
WINEPREFIX="$HOME/.deepinwine/$BOTTLENAME"
WECHAT_VER="3.4.0.38"
EXEC_PATH="c:/Program Files/Tencent/WeChat/WeChat.exe"
START_SHELL_PATH="/opt/deepinwine/tools/run_v4.sh"
WECHAT_INSTALLER="WeChatSetup"
WECHAT_INSTALLER_PATH="c:/Program Files/Tencent/$WECHAT_INSTALLER-$WECHAT_VER.exe"
export MIME_TYPE=""
export DEB_PACKAGE_NAME="com.qq.weixin.deepin"
export APPRUN_CMD="deepin-wine5"
DISABLE_ATTACH_FILE_DIALOG=""
export SPECIFY_SHELL_DIR=`dirname $START_SHELL_PATH`
ARCHIVE_FILE_DIR="/opt/apps/$DEB_PACKAGE_NAME/files"
export WINEDLLPATH=/opt/$APPRUN_CMD/lib:/opt/$APPRUN_CMD/lib64
export WINEPREDLL="$ARCHIVE_FILE_DIR/dlls"
OpenWinecfg()
{
env WINEPREFIX=$WINEPREFIX $APPRUN_CMD winecfg
}
Run()
{
if [ -z "$DISABLE_ATTACH_FILE_DIALOG" ];then
export ATTACH_FILE_DIALOG=1
fi
if [ -n "$EXEC_PATH" ];then
if [ ! -f "$WINEPREFIX/reinstalled" ];then
# run installer
env WINEDLLOVERRIDES="winemenubuilder.exe=d" $START_SHELL_PATH $BOTTLENAME $APPVER "$WECHAT_INSTALLER_PATH" "$@"
touch $WINEPREFIX/reinstalled
else
if [ -z "${EXEC_PATH##*.lnk*}" ];then
$START_SHELL_PATH $BOTTLENAME $APPVER "C:/windows/command/start.exe" "/Unix" "$EXEC_PATH" "$@"
else
$START_SHELL_PATH $BOTTLENAME $APPVER "$EXEC_PATH" "$@"
fi
fi
else
$START_SHELL_PATH $BOTTLENAME $APPVER "uninstaller.exe" "$@"
fi
}
HelpApp()
{
echo " Extra Commands:"
echo " winecfg Open winecfg"
echo " -h/--help Show program help info"
}
if [ -z $1 ]; then
Run "$@"
exit 0
fi
case $1 in
"winecfg")
OpenWinecfg
;;
"-h" | "--help")
HelpApp
;;
*)
Run "$@"
;;
esac
exit 0
依赖解决
从上面的 run.sh
可以知道 启动依赖 START_SHELL_PATH
, 他依赖到了一个shell /opt/deepinwine/tools/run_v4.sh
明显,我们的系统没有,需要解决一下这个依赖。他由deb包 link 提供。我们需要先单独对他打包。
打包 deepin-wine-helper
下载 deepin-wine-helper
的deb包 点击这里下载
解包deb后 得到 data.tar.xz
目录如下:
[x@fedora 下载]$ tree fedora-deepin-wine-helper
fedora-deepin-wine-helper
├── opt
│ └── deepinwine
│ └── tools
│ ├── add_hotkeys
│ ├── fontconfig
│ ├── get_tray_window
│ ├── kill.sh
│ ├── log.sh
│ ├── map_device.sh
│ ├── QQGameRunner
│ ├── register_font.sh
│ ├── run.sh
│ ├── run_v2.sh
│ ├── run_v3.sh
│ ├── run_v4.sh
│ ├── sendkeys.exe
│ ├── sendkeys.sh
│ ├── SetDpi.sh
│ └── updater
└── usr
└── share
└── doc
└── deepin-wine-helper
├── changelog.Debian.gz
└── copyright
查看 opt/deepinwine/tools/run_v4.sh
这是 wechat 启动shell所依赖的
发现第十三行 WINE_CMD
值 deepin-wine
有问题 修正一下
WINE_CMD="deepin-wine5"
看到脚本末尾 是执行该脚本的入口
BOTTLENAME="$1"
WINEPREFIX="$HOME/.deepinwine/$1"
APPDIR="/opt/apps/${DEB_PACKAGE_NAME}/files"
if [ -f "$APPDIR/files.md5sum" ];then
APPVER="$(cat $APPDIR/files.md5sum)"
else
APPVER="$2"
fi
debug_log "Run $*"
#执行lnk文件通过判断第5个参数是否是“/Unix”来判断
if [ "$4" == "/Unix" ];then
RunApp "$3" "$4" "$5"
exit 0
fi
if [ $# -lt 4 ]; then
RunApp "$3"
exit 0
fi
case $4 in
"-r" | "--reset")
ResetApp
;;
"-c" | "--create")
CreateBottle
;;
"-e" | "--remove")
RemoveApp
;;
"-u" | "--uri")
ParseArgs "$@"
;;
"-f" | "--file")
ParseArgs "$@"
;;
"-h" | "--help")
HelpApp
;;
*)
echo "Invalid option: $4"
echo "Use -h|--help to get help"
exit 1
;;
esac
exit 0
我们从上面的 opt/apps/com.qq.weixin.deepin/files/run.sh
可以知道执行时, 运行的命令为:
if [ -n "$EXEC_PATH" ];then
if [ ! -f "$WINEPREFIX/reinstalled" ];then
# run installer
env WINEDLLOVERRIDES="winemenubuilder.exe=d" $START_SHELL_PATH $BOTTLENAME $APPVER "$WECHAT_INSTALLER_PATH" "$@"
touch $WINEPREFIX/reinstalled
else
if [ -z "${EXEC_PATH##*.lnk*}" ];then
$START_SHELL_PATH $BOTTLENAME $APPVER "C:/windows/command/start.exe" "/Unix" "$EXEC_PATH" "$@"
else
$START_SHELL_PATH $BOTTLENAME $APPVER "$EXEC_PATH" "$@"
fi
fi
else
$START_SHELL_PATH $BOTTLENAME $APPVER "uninstaller.exe" "$@"
fi
所以我们最终会执行到
$START_SHELL_PATH $BOTTLENAME $APPVER "$EXEC_PATH" "$@"
对应的 opt/deepinwine/tools/run_v4.sh
脚本是
if [ $# -lt 4 ]; then
RunApp "$3"
exit 0
fi
接着,我们分析 RunApp
函数。看如下代码
RunApp()
{
progpid=$(ps -ef | grep "zenity --progress --title=${BOTTLENAME}" | grep -v grep)
debug_log "run ${BOTTLENAME} progress pid $progpid"
if [ -n "$progpid" ]; then
debug_log "$BOTTLENAME is running"
exit 0
fi
if [ -d "$WINEPREFIX" ]; then
UpdateApp | progressbar "$BOTTLENAME" "更新$BOTTLENAME中..."
else
DeployApp | progressbar $BOTTLENAME "初始化$BOTTLENAME中..."
fi
CallApp "$@"
}
由于我们 $WINEPREFIX
是 ~/.deepinwine/Deepin-WeChat
当文件夹存在的时候, 会执行一次 UpdateApp
不存在就会执行一次 DeployApp
最后执行 CallApp "$@"
调用起程序。
我们看 CallApp
函数[下面做了简化],通过 $BOTTLENAME
走到了 CallWeChat "$@"
我们继续跟踪 CallWeChat
CallApp()
{
FixLink
debug_log "CallApp $BOTTLENAME arg count $#: $*"
case $BOTTLENAME in
"Deepin-WeChat")
CallWeChat "$@"
;;
*)
CallProcess "$@"
;;
esac
}
跟踪一下 CallWeChat
代码如下:
CallWeChat()
{
debug_log "Disable auto update"
_DeleteRegistry "HKCU\\Software\\Tencent\\WeChat" "UpdateFailCnt"
_DeleteRegistry "HKCU\\Software\\Tencent\\WeChat" "NeedUpdateType"
rm "${WINEPREFIX}/drive_c/users/${USER}/Application Data/Tencent/WeChat/All Users/config/configEx.ini"
export DISABLE_RENDER_CLIPBOARD=1
export ATTACH_FILE_DIALOG=1
CallProcess "$@"
}
由于项目执行目录未被创建,所以我们需要手动修正一下shell,追加如下内容到函数的顶部:
if [ ! -f "$WINEPREFIX/drive_c/Program Files/Tencent/WeChat/Wechat.exe" ]; then
echo "deploy wechat app."
DeployApp | progressbar $BOTTLENAME "初始化$BOTTLENAME中..."
mkdir $WINEPREFIX/drive_c/Program\ Files/Tencent/WeChat
cp $WINEPREFIX/drive_c/Program\ Files/Tencent/WeChatSetup-* $WINEPREFIX/drive_c/Program\ Files/Tencent/WeChat/Wechat.exe
fi
所以最终的 CallWeChat
修正后应该长这个样子
CallWeChat()
{
if [ ! -f "$WINEPREFIX/drive_c/Program Files/Tencent/WeChat/Wechat.exe" ]; then
echo "deploy wechat app."
DeployApp | progressbar $BOTTLENAME "初始化$BOTTLENAME中..."
mkdir $WINEPREFIX/drive_c/Program\ Files/Tencent/WeChat
cp $WINEPREFIX/drive_c/Program\ Files/Tencent/WeChatSetup-* $WINEPREFIX/drive_c/Program\ Files/Tencent/WeChat/Wechat.exe
fi
debug_log "Disable auto update"
_DeleteRegistry "HKCU\\Software\\Tencent\\WeChat" "UpdateFailCnt"
_DeleteRegistry "HKCU\\Software\\Tencent\\WeChat" "NeedUpdateType"
rm "${WINEPREFIX}/drive_c/users/${USER}/Application Data/Tencent/WeChat/All Users/config/configEx.ini"
export DISABLE_RENDER_CLIPBOARD=1
export ATTACH_FILE_DIALOG=1
CallProcess "$@"
}
deepin-wine-helper 构建
修正好上面的代码后,我们开始构建 deepin-wine-helper
编辑一份 rpm package spec:
Name: fedora-deepin-wine-helper
Version: 5.1.27
Release: 1%{?dist}
Summary: Deepin Wine Helper
License: extra
URL: http://www.linuxdeepin.com/
Source0: fedora-deepin-wine-helper-%{version}.tar.gz
# BuildRequires:
# Requires:
%description
Deepin Wine Helper
%prep
%setup -q
%build
%global debug_package %{nil}
%install
cd %_builddir/fedora-deepin-wine-helper-%{version}/
cp -r ./ %{buildroot}/
%files
%defattr (-,root,root)
%{_prefix}/share/*
/opt/deepinwine/tools/*
%changelog
* Mon, 19 Jul 2021 09:51:32 +0800 Cui Jiajin <cuijiajin@uniontech.com>
- update
* Fri, 05 Jun 2020 15:39:03 +0800 Cui Jiajin <cuijiajin@uniontech.com>
- Initial release
wechat的构建中
编辑构建 wechat 包的 rpm package spec:
Name: fedora-deepin-wechat
Version: 3.4.0.38
Release: 1%{?dist}
Summary: Deepin Wechat
License: proprietary
URL: https://weixin.qq.com
Source0: fedora-deepin-wechat-%{version}.tar.gz
# BuildRequires: fedora-deepin-wine5
Requires: fedora-deepin-wine5 wine
%description
Deepin打包的微信容器(com.qq.weixin.deepin)移植到Fedora
%prep
%setup -q
%build
%global debug_package %{nil}
%install
rm -rf $RPM_BUILD_ROOT
cd %_builddir/fedora-deepin-wechat-%{version}/
cp -r ./ %{buildroot}/
%files
%defattr (-,root,root)
%{_prefix}/share/*
/opt/apps/com.qq.weixin.deepin/files
%changelog
* Thu Nov 04 2021 root
-
打包既可。