{"id":13505498,"url":"https://github.com/Hackerl/Wine_Appimage","last_synced_at":"2025-03-30T00:30:54.483Z","repository":{"id":153018167,"uuid":"128619090","full_name":"Hackerl/Wine_Appimage","owner":"Hackerl","description":"Appimage For Wine","archived":false,"fork":false,"pushed_at":"2021-04-19T07:06:43.000Z","size":1298,"stargazers_count":481,"open_issues_count":12,"forks_count":71,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-03-29T15:08:11.340Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Hackerl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-04-08T08:37:13.000Z","updated_at":"2025-03-24T23:57:13.000Z","dependencies_parsed_at":"2024-01-07T22:24:21.921Z","dependency_job_id":null,"html_url":"https://github.com/Hackerl/Wine_Appimage","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hackerl%2FWine_Appimage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hackerl%2FWine_Appimage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hackerl%2FWine_Appimage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hackerl%2FWine_Appimage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hackerl","download_url":"https://codeload.github.com/Hackerl/Wine_Appimage/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246262490,"owners_count":20749170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T00:01:09.083Z","updated_at":"2025-03-30T00:30:54.453Z","avatar_url":"https://github.com/Hackerl.png","language":"Shell","funding_links":[],"categories":["AppImage developer tools"],"sub_categories":["Deployment tools for Windows applications"],"readme":"# Appimage For Wine\n## 简介\nAppImage 是一种把应用打包成单一文件的格式，允许在各种不同的目标系统（基础系统(Debian、RHEL等)，发行版(Ubuntu、Deepin等)）上运行，无需进一步修改。\n创建Appimage就是搜集可执行程序及其依赖，放到一个文件夹下面。然后设置可执行文件依赖库路径，使得程序的执行不再依赖当前系统环境。此文件夹就相当于程序执行时的系统环境，然后将文件夹压缩，最后打包成Appimage。\n运行Appimage时会解压出文件夹，然后运行其中的可执行脚本。\n## Download\n[Appimage Releases](https://github.com/Hackerl/Wine_Appimage/releases)\n### Windows Apps\n* Wine-x86_64.AppImage\n* QQ-x86_64.AppImage QQ\n* QQLight-x86_64.AppImage QQ轻聊版\n* Wechat-x86_64.AppImage 微信\n* ThunderMini-x86_64.AppImage 迅雷精简版\n* ThunderSpeed-x86_64.AppImage 迅雷极速版\n* TIM-x86_64.AppImage TIM\n* BaiduDisk 百度网盘v5.5.2 如果出现问题请删除 $HOME/.BaiduDisk\n\n应用皆依赖于Wine-x86_64.AppImage，所以请先下载Wine-x86_64.AppImage，执行：\n```Bash\nsudo ln -s $(pwd)/Wine-x86_64.AppImage /usr/bin/wine\n```\nPS: QQ/迅雷/百度网盘已有Linux版本。\n## Wine\nWine （“Wine Is Not an Emulator” 的递归缩写）是一个能够在多种 POSIX-compliant 操作系统（诸如 Linux，Mac OSX 及 BSD 等）上运行 Windows 应用的兼容层。\n而Wine的依赖库比较多，而且必须安装i386架构才能执行Win32位程序，如果能打包成一个Appimage，将省去安装、配置等繁琐步骤。\n## AppDir\n先创建打包Appimage的文件夹，然后我们需要搜集Wine的可执行程序。\n从源下载的包安装后，可执行文件及库会分布在系统不同路径，于是我想手动编译，指定prefix就能搜集Wine的所有文件。\n但我发现PlayOnLinux提供编译好的[压缩包](https://www.playonlinux.com/wine/binaries/linux-x86/)，下载最新版本的Wine -- PlayOnLinux-wine-3.5-linux-x86.pol。\n解压查看文件目录：\n\n![](/images/1.png)\n\n删除无关的files、playonlinux目录，将Wine目录移到AppDir下：\n\n![](/images/2.png)\n\n\n## 搜集系统依赖\n现在我们有了Wine的所有可执行文件、依赖，但是没有系统依赖。此次打包的是wine32，所以需要安装i386系统环境。\n我选择让apt帮我寻找依赖：\n```Bash\nsudo apt install wine32:i386\n```\n得到依赖：\n\u003e gcc-6-base:i386 i965-va-driver:i386 libasound2:i386 libasound2-plugins:i386 libasyncns0:i386 libavahi-client3:i386 libavahi-common-data:i386 libavahi-common3:i386 libavcodec57:i386 libavresample3:i386 libavutil55:i386 libbsd0:i386 libc6:i386 libcairo2:i386 libcap2:i386 libcomerr2:i386 libcrystalhd3:i386 libcups2:i386 libdb5.3:i386 libdbus-1-3:i386 libdrm-amdgpu1:i386 libdrm-intel1:i386 libdrm-nouveau2:i386 libdrm-radeon1:i386 libdrm2:i386 libedit2:i386 libelf1:i386 libexpat1:i386 libffi6:i386 libflac8:i386 libfontconfig1:i386 libfreetype6:i386 libgcc1:i386 libgcrypt20:i386 libgl1-mesa-dri:i386 libgl1-mesa-glx:i386 libglapi-mesa:i386 libglu1-mesa:i386 libgmp10:i386 libgnutls30:i386 libgomp1:i386 libgpg-error0:i386 libgpm2:i386 libgsm1:i386 libgssapi-krb5-2:i386 libhogweed4:i386 libice6:i386 libicu57:i386 libidn11:i386 libjack-jackd2-0:i386 libjbig0:i386 libjpeg62-turbo:i386 libk5crypto3:i386 libkeyutils1:i386 libkrb5-3:i386 libkrb5support0:i386 liblcms2-2:i386 libldap-2.4-2:i386 libllvm3.9:i386 libltdl7:i386 liblz4-1:i386 liblzma5:i386 libmp3lame0:i386 libmpg123-0:i386 libncurses5:i386 libnettle6:i386 libnuma1:i386 libodbc1:i386 libogg0:i386 libopenal1:i386 libopenjp2-7:i386 libopus0:i386 libosmesa6:i386 libp11-kit0:i386 libpcap0.8:i386 libpciaccess0:i386 libpcre3:i386 libpixman-1-0:i386 libpng16-16:i386 libpulse0:i386 libsamplerate0:i386 libsasl2-2:i386 libsasl2-modules:i386 libsasl2-modules-db:i386 libselinux1:i386 libsensors4:i386 libshine3:i386 libsm6:i386 libsnappy1v5:i386 libsndfile1:i386 libsndio6.1:i386 libsoxr0:i386 libspeex1:i386 libspeexdsp1:i386 libssl1.1:i386 libstdc++6:i386 libswresample2:i386 libsystemd0:i386 libtasn1-6:i386 libtheora0:i386 libtiff5:i386 libtinfo5:i386 libtwolame0:i386 libtxc-dxtn-s2tc:i386 libuuid1:i386 libva-drm1:i386 libva-x11-1:i386 libva1:i386 libvdpau-va-gl1:i386 libvdpau1:i386 libvorbis0a:i386 libvorbisenc2:i386 libvpx4:i386 libwavpack1:i386 libwebp6:i386 libwebpmux2:i386 libwrap0:i386 libx11-6:i386 libx11-xcb1:i386 libx264-148:i386 libx265-95:i386 libxau6:i386 libxcb-dri2-0:i386 libxcb-dri3-0:i386 libxcb-glx0:i386 libxcb-present0:i386 libxcb-render0:i386 libxcb-shm0:i386 libxcb-sync1:i386 libxcb1:i386 libxcomposite1:i386 libxcursor1:i386 libxdamage1:i386 libxdmcp6:i386 libxext6:i386 libxfixes3:i386 libxi6:i386 libxinerama1:i386 libxml2:i386 libxrandr2:i386 libxrender1:i386 libxshmfence1:i386 libxslt1.1:i386 libxtst6:i386 libxvidcore4:i386 libxxf86vm1:i386 libzvbi0:i386 mesa-va-drivers:i386 mesa-vdpau-drivers:i386 ocl-icd-libopencl1:i386 va-driver-all:i386 vdpau-driver-all:i386 zlib1g:i386\n\n下载所有依赖：\n```Bash\napt download files\n```\n避免各版本fontconfig不兼容，所以需要打包fontconfig-config:\n```Bash\napt download fontconfig-config\n```\n将所有deb包放入AppDir/debs中，使用dpkg解压文件：\n```Bash\nfind ./debs -exec dpkg -x {} ./ \\;\n```\n执行完后，所有deb包中的内容都解压出来了：\n\n![](/images/3.png)\n\n## ld-linux.so\n### 旧方法\n这是负责加载动态库的解释器，在程序中是硬编码指定的：\n\n![](/images/4.png)\n\n对于32位程序是/lib/ld-linux.so.2,64位是/lib64/ld-linux-x86-64.so.2。\n此文件包含在libc6中，我们已经解压了libc6:i386.deb，ld-linux.so.2 在 AppDir/lib 中。\n有一个办法是，手动复制 AppDir/lib/ld-linux.so.2 至 /lib，不过这就需要每个使用者下载后都执行此操作。\n\n还有一个方式是改变可执行文件的硬编码解释器路径，执行：\n```Bash\nFILES=$(grep -r ld-linux.so.2 ./bin | cut -d \" \" -f 3)\nfor FILE in $FILES ; do\n    patchelf --set-interpreter /tmp/ld-linux.so.2 $FILE\ndone\n```\n改变所有路径为/tmp/ld-linux.so.2，然后在执行Appimage时，创建软链接/tmp/ld-linux.so.2 指向 AppDir/lib/ld-linux.so.2。\n### 新方法\n利用LD_PRELOAD以及Ptrace进行Hook，控制Wine加载的ld.so。\n\n具体参考: https://github.com/Hackerl/Wine_Appimage/issues/11\n\n```bash=\nsudo apt-get -y install gcc-multilib\ngcc -shared -fPIC -m32 -ldl libhookexecv.c -o libhookexecv.so\ngcc -std=c99 -m32 -static preloaderhook.c -o wine-preloader_hook\n```\n将libhookexecv.so、wine-preloader_hook放入AppDir/bin目录中，通过环境变量WINELDLIBRARY即可以传递指定的ld.so。\n## 声音播放问题\n声音播放依赖于AppDir/usr/lib/libpulse.so.0，libpulse.so中指定了runpath：\n\n![](/images/5.png)\n\n动态库加载顺序：\n\u003e libraries goes as follows:\n1 - rpath\n2 - $LD_LIBRARY_PATH\n3 - runpath\n4 - ld.so.cache\n5 - default ld.so directories (where glibc has been installed)\n\n此时 pulseaudio 在 AppDir/usr/lib/i386-linux-gnu 中，所以在 LD_LIBRARY_PATH 中添加 AppDir/usr/lib/i386-linux-gnu/pulseaudio：\n```Bash\n#Sound Library\nexport LD_LIBRARY_PATH=\"$HERE/usr/lib/i386-linux-gnu/pulseaudio\":$LD_LIBRARY_PATH\n#插件\nexport LD_LIBRARY_PATH=\"$HERE/usr/lib/i386-linux-gnu/alsa-lib\":$LD_LIBRARY_PATH\n```\n## 打包\n编写AppRun：\n```Bash\n#!/bin/bash\nHERE=\"$(dirname \"$(readlink -f \"${0}\")\")\"\n\nexport LD_LIBRARY_PATH=\"$HERE/usr/lib\":$LD_LIBRARY_PATH\nexport LD_LIBRARY_PATH=\"$HERE/usr/lib/i386-linux-gnu\":$LD_LIBRARY_PATH\nexport LD_LIBRARY_PATH=\"$HERE/lib\":$LD_LIBRARY_PATH\nexport LD_LIBRARY_PATH=\"$HERE/lib/i386-linux-gnu\":$LD_LIBRARY_PATH\n\n#Sound Library\nexport LD_LIBRARY_PATH=\"$HERE/usr/lib/i386-linux-gnu/pulseaudio\":$LD_LIBRARY_PATH\nexport LD_LIBRARY_PATH=\"$HERE/usr/lib/i386-linux-gnu/alsa-lib\":$LD_LIBRARY_PATH\n\n#Font Config\nexport FONTCONFIG_PATH=\"$HERE/etc/fonts\"\n\n#LD\nexport WINELDLIBRARY=\"$HERE/lib/ld-linux.so.2\"\n\nLD_PRELOAD=\"$HERE/bin/libhookexecv.so\" \"$WINELDLIBRARY\" \"$HERE/bin/wine\" \"$@\" | cat\n```\n此时Wine已经可以执行，完全不依赖系统环境，执行打包命令：\n```Bash\nexport ARCH=x86_64; appimagetool-x86_64.AppImage AppDir\n```\n成功完成Wine的Appimage打包。\n\n---\n# 构建Windows Appimage应用\n## 创建wine软链接\n其实在构建Windows Appimage时，不必将Wine放入每个应用中。完全可以将Wine Appimage的软链接放入/usr/bin，在各个Windows Appimage应用中调用Wine Appimage。\n下载Wine Appimage，创建软链接：\n```Bash\nln $(pwd)/Wine-x86_64.AppImage /usr/bin/wine\n```\n## 构建应用AppDir\n将应用Wine配置目录放入AppDir，以迅雷精简版为例：\n\n![](/images/6.png)\n\n之后通过设置 WINEPREFIX 变量，使得Wine以目录为起始，作为读写源。\n## 虚拟目录\nWine需要对Appimage中的WINEPREFIX目录进行读写，但Appimage中的内容挂载出来是只读属性。\n所以需要使用使用虚拟目录，将对WINEPREFIX的写操作重定向至$HOME，从而存储应用数据：\n```Bash\nRO_DATADIR=\"$HERE/opt/apps.com.thunder.mini/\"\nRW_DATADIR=\"$HOME/.ThunderMini\"\nTOP_NODE=\"/tmp/.ThunderMini.unionfs\"\n\nmkdir -p $RW_DATADIR $TOP_NODE\n\n$HERE/usr/bin/unionfs-fuse -o use_ino,nonempty,uid=$UID -ocow \"$RW_DATADIR\"=RW:\"$RO_DATADIR\"=RO \"$TOP_NODE\" || exit 1\n```\n将unionfs-fuse放入Appimage中，使用unionfs-fuse形成虚拟节点。\n上面的命令将创建 TOP_NODE 虚拟节点，只读目录 RO_DATADIR 指向WINEPREFIX目录，而读写目录 RW_DATADIR 用来储存数据。\n当对虚拟节点 TOP_NODE 进行读时，会到RO_DATADIR、RW_DATADIR中寻找文件。\n当对 TOP_NODE 进行写时，会重定向至 RW_DATADIR。\n## AppRun\n创建运行脚本：\n```Bash\n#!/bin/bash\ncommand -v wine \u003e/dev/null 2\u003e\u00261 || { echo -e \u003e\u00262 \"I require wine.\\nYou can download Wine-x86_64.AppImage from https://github.com/Hackerl/Wine_Appimage/releases.\\nThen run: chmod 777 \\$(pwd)/Wine-x86_64.AppImage; sudo ln -s \\$(pwd)/Wine-x86_64.AppImage /usr/bin/wine\"; exit 1; }\n\nHERE=\"$(dirname \"$(readlink -f \"${0}\")\")\"\n\nexport WINEDEBUG=-all\n\nRO_DATADIR=\"$HERE/opt/apps.com.thunder.mini/\"\nRW_DATADIR=\"$HOME/.ThunderMini\"\nTOP_NODE=\"/tmp/.ThunderMini.unionfs\"\n\nmkdir -p $RW_DATADIR $TOP_NODE\n\n$HERE/usr/bin/unionfs-fuse -o use_ino,nonempty,uid=$UID -ocow \"$RW_DATADIR\"=RW:\"$RO_DATADIR\"=RO \"$TOP_NODE\" || exit 1\n\nfunction finish {\n  echo \"Cleaning up\"\n  killall $HERE/usr/bin/unionfs-fuse\n}\ntrap finish EXIT\n\nexport WINEPREFIX=\"$TOP_NODE\"\nwine \"c:\\\\Program Files\\\\Thunder Network\\\\MiniThunder\\\\Bin\\\\ThunderMini.exe\" \"$@\"\n```\n最后的命令运行wine，必须保证指向Wine Appimage的软链接/usr/bin/wine存在。\n## 打包运行\n```Bash\nexport ARCH=x86_64; ./appimagetool-x86_64.AppImage squashfs-root\n```\n运行：\n\n![](/images/7.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHackerl%2FWine_Appimage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FHackerl%2FWine_Appimage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHackerl%2FWine_Appimage/lists"}