Skip to content

Commit

Permalink
Rewrite the code with a better approach
Browse files Browse the repository at this point in the history
* Added 'minimize' command #5
* Added support for applications that verify the signature of the DLL #7
* More transparent way for handling PREFIX
* Less CPU usage by packaged applications
* More fast initialization of packaged applications
* Commands now show how many steps it takes to complete the task
* Splits some commands
  • Loading branch information
sudo-give-me-coffee committed Mar 8, 2020
1 parent 046054a commit 2722ad0
Show file tree
Hide file tree
Showing 19 changed files with 628 additions and 369 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ COPY . /srv/wine

WORKDIR /srv/wine

RUN /srv/wine/deploy/build.sh
RUN /srv/wine/build.sh
65 changes: 8 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,13 @@
Win32-AppImage | <a href="https://github.com/sudo-give-me-coffee/wine-appimage/releases/tag/continuous">Downloads</a>
</h1>

<p align="center"><i>"A simple, lightweight way to distribute the 32-bit Microsoft Windows® application on Linux"</i>.<br> It works on Ubuntu, Fedora, Debian, their derivates and all other major Linux
<p align="center"><i>"A simple and lightweight way to distribute the 32-bit Microsoft Windows® application on Linux"</i>.<br> It works on most Linux
distributions.</p>

<hr>

# Basic usage:

The basic usage is relative simple and use only 8 steps and is basically composed by composed bt 2 groups of steps:

#### First group: Create the bottle

1. Download Wine AppImage by clicking on "**Downloads**" link above and selecting desired version
2. Open a terminal where you has Win32 AppImage
3. Turn it executable:
```bash
chmod +x Wine-*-x86_64.AppImage
```
4. Create an bottle:
```bash
./Wine-*-x86_64.AppImage create-bottle "My Bottle"
```

5. Modify with winetricks (if needed):
```bash
./Wine-*-x86_64.AppImage winetricks "My Bottle"
```
> Please read [How to package fonts avoiding copyright infringement](https://github.com/sudo-give-me-coffee/win32-appimage/wiki/Packaging-fonts) if you want use winetricks to install fonts
6. Install your application:
```bash
./Wine-*-x86_64.AppImage install "My Bottle" "/path/to/my/application-setup.exe"
```

#### Second group: Package as AppImage::

7. First, test your application:

```bash
./Wine-*-x86_64.AppImage run "My Bottle" "C:/Where/Application/was/installed/application.exe"
```
8. Remove unnecessary resources:

```bash
./Wine-*-x86_64.AppImage --strip "My Bottle" mono gecko
```

9. Let's package it:
```bash
./Wine-*-x86_64.AppImage package "My Bottle" \
"C:/Where/Application/was/installed/application.exe" \
Utility
"data/icon.png"
```

# A more detailed usage:
The **wine32-appimage** Commands
# Usage:
The **wine32-deploy** Commands

> Note: All commands must receive a bottle name
Expand Down Expand Up @@ -152,11 +103,11 @@ At last, the commands for Wine tools bundled with **wine32-appimage**:

| Command | | What its does |
|-----------------|----|-------------------------------------------------|
| --winetricks | => | Open Winetricks |
| --winecfg | => | Open Wine configurator |
| --regedit | => | Open Wine register editor |
| --taskmgr | => | Open a task manager for wine apps |
| --uninstaller | => | Open the 'Wine Uninstaller' |
| winetricks | => | Open Winetricks |
| winecfg | => | Open Wine configurator |
| regedit | => | Open Wine register editor |
| taskmgr | => | Open a task manager for wine apps |
| uninstaller | => | Open the 'Wine Uninstaller' |

* [winetricks](https://wiki.winehq.org/Winetricks)
* [winecfg](https://wiki.winehq.org/Winecfg)
Expand Down
76 changes: 76 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash

# Setup environment

export ARCH="x86_64"
export Version="4.21"
export BuildDependencies="aptitude wget file gzip bzip2 curl cabextract"
export WorkingDir="Wine.AppDir"
export PackagesDirectory='/tmp/.cache'
export wgetOptions="-nv -c --show-progress --progress=bar:force:noscroll"
export DownloadURLs=(
"https://www.playonlinux.com/wine/binaries/phoenicis/upstream-linux-x86/PlayOnLinux-wine-${Version}-upstream-linux-x86.tar.gz"
"https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
"https://github.com/Hackerl/Wine_Appimage/releases/download/v0.9/libhookexecv.so"
"https://github.com/Hackerl/Wine_Appimage/releases/download/v0.9/wine-preloader_hook"
"https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks"
)

# Install build deps

dpkg --add-architecture i386
apt update
apt install ${BuildDependencies} -y

# Create Directories

mkdir -p "${PackagesDirectory}"
mkdir -p "${WorkingDir}/Resources"
mkdir -p "${WorkingDir}/Flags"

# Download files

wget ${wgetOptions} ${DownloadURLs[@]}

# Turn executable

chmod +x "appimagetool-x86_64.AppImage"
chmod +x "data/"*
chmod +x "winetricks"

# Get WINE deps

aptitude -y -d -o dir::cache::archives="${PackagesDirectory}" install libwine:i386
wget -q "http://ftp.us.debian.org/debian/pool/main/libp/libpng/libpng12-0_1.2.50-2+deb8u3_i386.deb" -O "${PackagesDirectory}/libpng12.deb"

# Extract WINE

tar -xzf "PlayOnLinux-wine-${Version}-upstream-linux-x86.tar.gz" -C "${WorkingDir}" 2> /dev/null || \
tar -xjf "PlayOnLinux-wine-${Version}-upstream-linux-x86.tar.gz" -C "${WorkingDir}"

# Copy wine dependencies to AppDir

find "${PackagesDirectory}" -name '*deb' ! -name 'libwine*' -exec dpkg -x {} "./${WorkingDir}" \;

# Copy data to AppDir

cp -r data/* "${WorkingDir}"
cp -r flags/* "${WorkingDir}/Flags"
cp -r resources/* "${WorkingDir}/Resources"

ls
pwd
ls ..

mv "libhookexecv.so" "${WorkingDir}/bin"
mv "wine-preloader_hook" "${WorkingDir}/bin"
mv "winetricks" "${WorkingDir}/bin"
cp "$(which cabextract)" "${WorkingDir}/bin"
cp appimagetool-x86_64.AppImage "${WorkingDir}"

# Build AppImage

./appimagetool-x86_64.AppImage --appimage-extract-and-run "${WorkingDir}"
mv "Wine-x86_64.AppImage" "Wine-${Version}-x86_64.AppImage"

exit
176 changes: 176 additions & 0 deletions data/AppDirTool.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@

function appdir.create-appdir(){
appdir.hasCreated
bottle.loadEnvironment
echo "[ 1/8 ] Creating AppDir..."
mkdir -p "${BOTTLE_NAME}.AppDir/"
WINE_FILES=$(ls "${HERE}" | grep -Ev "${BOTTLE_NAME}|${BOTTLE_NAME}.AppDir|.*.sh$|Resources|Wine.png|wine.desktop|Flags|AppRun")

echo "[ 2/8 ] Copying Wine..."
echo " This will take a while..."
echo "${WINE_FILES}" | sed "s|^|cp -r ${HERE}/|g" | sed "s|$| ${BOTTLE_NAME}.AppDir|g" | sh

echo "[ 3/8 ] Copying bottle..."
echo " This will take a while..."
cp -r ${BOTTLE_NAME}/* ${BOTTLE_NAME}.AppDir

echo "[ 4/8 ] Removing unecessary data..."
rm -rf ${BOTTLE_NAME}.AppDir/include
rm -rf ${BOTTLE_NAME}.AppDir/config

echo "[ 5/8 ] Getting added keys to registry..."
diff ${BOTTLE_NAME}.AppDir/prefix/system.reg ${BOTTLE_NAME}.AppDir/system.reg.orig | grep ^"< " \
| head -n -44 \
| cut -c 3-| grep -v ^"#" \
| rev | sed '/^[0-9]\{10\}/ s/ /# /' \
| rev | sed 's/^\[S/\[HKEY_LOCAL_MACHINE\\S/g' \
| sed '/^\[/ s|\\\\|\\|g' \
| sed "/\"InstallDate\"/c\{Install date here}" \
>> ${BOTTLE_NAME}.AppDir/default.reg
rm ${BOTTLE_NAME}.AppDir/system.reg.orig
rm ${BOTTLE_NAME}.AppDir/prefix/*.reg

# Fixes https://github.com/sudo-give-me-coffee/win32-appimage/issues/7
[ "${1}" == "--keep-registry" ] && {
cp ${BOTTLE_NAME}/prefix/system.reg ${BOTTLE_NAME}.AppDir/prefix/
}

rm ${BOTTLE_NAME}.AppDir/prefix/.update-timestamp
rm -rf ${BOTTLE_NAME}.AppDir/prefix/dosdevices
rm -rf ${BOTTLE_NAME}.AppDir/prefix/drive_c/users

echo "[ 6/8 ] Deduplicating files..."
file_list=$(find ${BOTTLE_NAME}.AppDir/prefix/drive_c/windows -type f | sort | uniq)
for file in ${file_list[@]}; do
[[ -L "${BOTTLE_NAME}.AppDir/lib/wine/$(basename ${file})" ]] && {
file="dummy"
}

[ -f "${BOTTLE_NAME}.AppDir/lib/wine/$(basename ${file})" ] && {
rm "${BOTTLE_NAME}.AppDir/lib/wine/$(basename ${file})"
ln -s "../../"$(echo ${file} | sed "s|^${BOTTLE_NAME}.AppDir/||g") "${BOTTLE_NAME}.AppDir/lib/wine/$(basename ${file})"
}
done
rm -rf "${BOTTLE_NAME}.AppDir/lib/wine/fakedlls"
rm "${BOTTLE_NAME}.AppDir/share/wine/wine.inf"

echo "[ 7/8 ] Creating AppRun..."
cat "${HERE}/WineAppRun.sh" | sed "s|§bottle|${BOTTLE_NAME}|g" > ${BOTTLE_NAME}.AppDir/AppRun
chmod +x ${BOTTLE_NAME}.AppDir/AppRun

echo "" >> ${BOTTLE_NAME}.AppDir/flags.sh

for flag in ${BOTTLE_NAME}.AppDir/*.flag; do
cat "${flag}" >> ${BOTTLE_NAME}.AppDir/flags.sh &> /dev/null
rm ${flag} &> /dev/null
done

echo "[ 8/8 ] All AppDir Creation steps is done"
echo
echo "The nexts steps is:"
echo
echo " Test your AppDir¹"
echo " ${APPIMAGE} test ${BOTTLE_NAME}"
echo
echo " Minimize AppDir to reduce AppImage size²"
echo " ${APPIMAGE} minimize ${BOTTLE_NAME}"
echo
echo " Package AppDir in to AppImage"
echo " ${APPIMAGE} package path/to/icon.png"
echo
echo "Notes: "
echo " ¹ This will create a temporary \${HOME}"
echo " ² You will may be asked for root password, it is needed to mount a tmpfs"
echo
}

function appdir.test(){
appdir.hasCreated
echo "[ 1/3 ] Creating Environment..."
export HOME=$(mktemp -d)
export XDG_CONFIG_HOME="${HOME}/config"
echo
echo HOME=${HOME}
echo XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
echo WINEPREFIX="${XDG_CONFIG_HOME}/${BOTTLE_NAME}"
echo
echo "[ 2/3 ] Initializing test..."
echo
${BOTTLE_NAME}.AppDir/AppRun
echo
echo "[ 3/3 ] Ending test..."
echo
rm -rf ${HOME}
rm -rf ${XDG_CONFIG_HOME}
}

function appdir.minimize(){
appdir.hasCreated
export LANG=en.UTF-8
echo "[ 1/8 ] Creating Environment..."
export HOME=$(mktemp -d)
export XDG_CONFIG_HOME="${HOME}/config"
export TMPFS_APPDIR=$(mktemp -d)
echo
echo HOME=${HOME}
echo XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
echo WINEPREFIX="${XDG_CONFIG_HOME}/${BOTTLE_NAME}"
echo TMPFS_APPDIR="${TMPFS_APPDIR}"
echo

echo "[ 2/8 ] Mounting tmpfs..."
sudo mount -t tmpfs tmpfs ${TMPFS_APPDIR} -o strictatime,nodiratime

echo "[ 3/8 ] Copying ${BOTTLE_NAME}.AppDir to tmpfs..."
echo " This will take a while..."
cp -r ${BOTTLE_NAME}.AppDir/* ${TMPFS_APPDIR}

echo "[ 4/8 ] Initializing test..."
echo
REFERENCE_FILE=$(mktemp)
${TMPFS_APPDIR}/AppRun
echo

echo "[ 5/8 ] Getting a list unused files..."
LIST=$(find ${TMPFS_APPDIR} -mindepth 3 -type f -not -anewer ${REFERENCE_FILE} | sed "s|^${TMPFS_APPDIR}||g")
WINE_FILES=$(echo "${LIST}" | grep -v ^"/prefix/")
PREFIX_FILES=$(echo "${LIST}" | grep ^"/prefix/drive_c/windows/")

echo "[ 6/8 ] Removing unused files..."
echo " This may take a while..."
echo "${WINE_FILES}" | sed "s|^|rm \"${BOTTLE_NAME}.AppDir|g" | sed "s|$|\"|g" | sh
echo "${PREFIX_FILES}" | sed "s|^|rm \"${BOTTLE_NAME}.AppDir|g" | sed "s|$|\"|g" | sh
find "${BOTTLE_NAME}.AppDir" -type l ! -exec test -e {} \; -delete
find "${BOTTLE_NAME}.AppDir" -type d -empty -delete

type strip &> /dev/null && {
[ ! "${1}" = "--no-strip" ] && {
find "${BOTTLE_NAME}.AppDir" -not -path '*/prefix/drive_c/*' | sed 's/^/strip --strip-unneeded "/g' | sed 's/$/"/g' | sh &> /dev/null
}
}

echo "[ 7/8 ] Umounting tmpfs..."
sudo umount ${TMPFS_APPDIR}

echo "[ 8/8 ] Ending test..."
rm -rf ${HOME}
rm -rf ${XDG_CONFIG_HOME}
rm -rf ${TMPFS_APPDIR}
rm -f ${REFERENCE_FILE}
}

function appdir.package(){
appdir.hasCreated
[ ! "${1}" = "--package-style" ] && {
rm -r "${BOTTLE_NAME}.AppDir/prefix/drive_c/windows/Resources/Themes/kupofl"
}
ARCH=x86_64 "${HERE}/appimagetool-x86_64.AppImage" --appimage-extract-and-run --no-appstream "${BOTTLE_NAME}.AppDir"
}

function appdir.hasCreated(){
[ ! -f "${BOTTLE_NAME}.AppDir/default.reg" ] && {
help.youMust "create a bottle AppDir" "create-appdir"
exit 1
}
}

0 comments on commit 2722ad0

Please sign in to comment.