Automate installation of DXVK, D9VK + Wine/Wine Staging & update GPU drivers + PlayonLinux wineprefixes (Debian/Ubuntu/Mint/Arch Linux/Manjaro)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

380 lines
10 KiB

6 years ago
  1. #!/bin/bash
  2. # Set up Wine Staging + DXVK on Arch Linux & Variants
  3. # Copyright (C) 2018 Pekka Helenius
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. ########################################################
  18. # DO NOT RUN INDIVIDUALLY, ONLY VIA ../updatewine.sh PARENT SCRIPT!
  19. ########################################################
  20. # Root directory of this script file
  21. ARCH_BUILDROOT="${PWD}"
  22. # datedir variable supplied by ../updatewine.sh script file
  23. datedir="${1}"
  24. ########################################################
  25. # http://wiki.bash-hackers.org/snipplets/print_horizontal_line#a_line_across_the_entire_width_of_the_terminal
  26. function INFO_SEP() { printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - ; }
  27. ########################################################
  28. # Parse input arguments
  29. i=0
  30. for arg in ${@:2}; do
  31. args[$i]="${arg}"
  32. let i++
  33. done
  34. # Must be a true array as defined above, not a single index list!
  35. #args="${@:2}"
  36. for check in ${args[@]}; do
  37. case ${check} in
  38. --no-staging)
  39. NO_STAGING=
  40. ;;
  41. --no-install)
  42. NO_INSTALL=
  43. # Do not check for PlayOnLinux wine prefixes
  44. NO_POL=
  45. ;;
  46. --no-wine)
  47. NO_WINE=
  48. ;;
  49. --no-dxvk)
  50. NO_DXVK=
  51. ;;
  52. --no-pol)
  53. NO_POL=
  54. ;;
  55. esac
  56. done
  57. ###########################################################
  58. # If the script is interrupted (Ctrl+C/SIGINT), do the following
  59. function Arch_intCleanup() {
  60. rm -rf ${ARCH_BUILDROOT}/{0-wine-staging-git/{wine-patches,*.tar.xz},0-dxvk-git/{dxvk-git,*.tar.xz}}
  61. exit 0
  62. }
  63. # Allow interruption of the script at any time (Ctrl + C)
  64. trap "Arch_intCleanup" INT
  65. ###########################################################
  66. # Check existence of ccache package
  67. function ccacheCheck() {
  68. if [[ $(pacman -Q | awk '{print $1}' | grep -wE "ccache" | wc -l) -eq 0 ]]; then
  69. echo -e "NOTE: Please consider using 'ccache' for faster compilation times.\nInstall it by typing 'sudo pacman -S ccache'\n"
  70. fi
  71. }
  72. ###########################################################
  73. # Validate all core build files for Wine and/or DXVK exist
  74. function checkFiles() {
  75. local wine_files=('30-win32-aliases.conf' 'PKGBUILD')
  76. local dxvk_files=('PKGBUILD')
  77. function validatefiles() {
  78. local list=${1}
  79. local name=${2}
  80. local path=${3}
  81. for file in ${list[@]}; do
  82. if [[ ! -f "${path}/${file}" ]]; then
  83. echo -e "Could not locate file ${} for ${name}. Aborting\n"
  84. exit 1
  85. fi
  86. done
  87. }
  88. if [[ ! -v NO_WINE ]]; then
  89. validatefiles "${wine_files[*]}" Wine "${ARCH_BUILDROOT}/0-wine-staging-git"
  90. fi
  91. if [[ ! -v NO_DXVK ]]; then
  92. validatefiles "${dxvk_files[*]}" DXVK "${ARCH_BUILDROOT}/0-dxvk-git"
  93. fi
  94. }
  95. ###########################################################
  96. # Disable or enable Wine Staging, depending on user's
  97. # choice
  98. function checkStaging() {
  99. # Enable Wine Staging
  100. if [[ ! -v NO_STAGING ]]; then
  101. sed -i 's/enable_staging=[0-9]/enable_staging=1/' "${ARCH_BUILDROOT}/0-wine-staging-git/PKGBUILD"
  102. wine_name="wine-staging-git"
  103. # Enable Wine, disable Staging
  104. else
  105. sed -i 's/enable_staging=[0-9]/enable_staging=0/' "${ARCH_BUILDROOT}/0-wine-staging-git/PKGBUILD"
  106. wine_name="wine"
  107. fi
  108. }
  109. ###########################################################
  110. # Check package dependencies beforehand, just to avoid
  111. # annoying situations which could occur later while the script
  112. # is already running.
  113. # Just for "packages which are not found" array <=> ERRPKGS
  114. # We need to set it outside of checkDepends function
  115. # because it is a global variable for all checked packages
  116. l=0
  117. function checkDepends() {
  118. # The first and the second argument
  119. local packagedir=${1}
  120. local package=${2}
  121. # We get necessary variables to check from this file
  122. local file="./${packagedir}/PKGBUILD"
  123. # All but the (zero), the first and the second argument
  124. # We check the value of these file variables
  125. local file_vars=${@:3}
  126. for var in ${file_vars[*]}; do
  127. # Get the variable and set it as a new variable in the current shell
  128. # This is applicable only to variable arrays! Do not use if the variable is not an array.
  129. local field=$(awk "/^${var}/,/)/" ${file} | sed -r "s/^${var}=|[)|(|']//g")
  130. local i=0
  131. for parse in ${field[*]}; do
  132. if [[ ! $parse =~ ^# ]]; then
  133. local PKGS[$i]=$(printf '%s' $parse | sed 's/[=|>|<].*$//')
  134. let i++
  135. fi
  136. done
  137. # Sort list and delete duplicate index values
  138. local PKGS=($(sort -u <<< "${PKGS[*]}"))
  139. for pkg in ${PKGS[*]}; do
  140. if [[ $(printf $(pacman -Q ${pkg} &>/dev/null)$?) -ne 0 ]]; then
  141. ERRPKGS[$l]=${pkg}
  142. echo -e "\e[91mError:\e[0m Dependency '${pkg}' not found, required by '${package}' (${file} => ${var})"
  143. let l++
  144. fi
  145. done
  146. done
  147. echo -e "\e[92m==>\e[0m\e[1m Dependency check for ${package} done.\e[0m\n"
  148. }
  149. function check_alldeps() {
  150. if [[ -v ERRPKGS ]]; then
  151. echo -e "The following dependencies are missing:\n\e[91m\
  152. $(for o in ${ERRPKGS[@]}; do printf '%s\n' ${o}; done)\
  153. \e[0m\n"
  154. exit 1
  155. fi
  156. }
  157. ###########################################################
  158. # Prepare building environment for the current runtime
  159. function prepare_env() {
  160. # Copy Wine & DXVK patch files
  161. cp -rf ${ARCH_BUILDROOT}/../wine_custom_patches ${ARCH_BUILDROOT}/0-wine-staging-git/wine-patches
  162. cp -rf ${ARCH_BUILDROOT}/../dxvk_custom_patches ${ARCH_BUILDROOT}/0-dxvk-git/dxvk-patches
  163. # Create identifiable directory for this build
  164. mkdir -p ${ARCH_BUILDROOT}/compiled_pkg/"${datedir}"
  165. }
  166. ###########################################################
  167. # Remove any existing pkg,src or tar.xz packages left by previous pacman commands
  168. function cleanUp() {
  169. rm -rf ${ARCH_BUILDROOT}/*/{pkg,src,*.tar.xz}
  170. rm -rf ${ARCH_BUILDROOT}/0-wine-staging-git/{*.patch}
  171. rm -rf ${ARCH_BUILDROOT}/0-dxvk-git/{*.patch}
  172. }
  173. ###########################################################
  174. # Build & install package
  175. function build_pkg() {
  176. local pkgname=${1}
  177. local pkgname_friendly=${2}
  178. local pkgdir=${3}
  179. local cleanlist=${4}
  180. # Create package and install it to the system
  181. cd "${ARCH_BUILDROOT}"/${pkgdir}
  182. bash -c "updpkgsums && makepkg"
  183. # After successful compilation...
  184. if [[ $(ls ${pkgname}-*tar.xz | wc -l) -ne 0 ]]; then
  185. if [[ ! -v NO_INSTALL ]]; then
  186. yes | sudo pacman -U ${pkgname}-*.tar.xz
  187. fi
  188. mv ${pkgname}-*.tar.xz ${ARCH_BUILDROOT}/compiled_pkg/${datedir}/ && \
  189. echo -e "\nCompiled ${pkgname_friendly} is stored at '$(readlink -f ${ARCH_BUILDROOT}/compiled_pkg/${datedir}/)/'\n"
  190. for rml in ${cleanlist[*]}; do
  191. rm -rf "${ARCH_BUILDROOT}/${pkgdir}/${rml}"
  192. done
  193. else
  194. echo -e "Error occured while compliling ${pkgname} from source.\n"
  195. for rml in ${cleanlist[*]}; do
  196. rm -rf "${ARCH_BUILDROOT}/${pkgdir}/${rml}"
  197. done
  198. exit 1
  199. fi
  200. cd "${ARCH_BUILDROOT}"
  201. }
  202. ##########################################################
  203. # Update user's PlayOnLinux Wine prefixes if present
  204. function updatePOL() {
  205. # Check whether we will update user's PoL wine prefixes
  206. if [[ ! -v NO_POL ]]; then
  207. # Check existence of PoL default folder in user's homedir
  208. if [[ ! -d "$HOME/.PlayOnLinux" ]]; then
  209. echo -e "Warning. Couldn't find PoL directories in the user's $USERNAME homedir.\n"
  210. return 0
  211. fi
  212. fi
  213. if [[ ! -v NO_WINE ]]; then
  214. # If a new Wine Staging version was installed and 'System' version of Wine has been used in
  215. # PoL wineprefix configurations, update those existing PoL wineprefixes
  216. for wineprefix in $(find $HOME/.PlayOnLinux/wineprefix -mindepth 1 -maxdepth 1 -type d); do
  217. if [[ -d ${wineprefix}/dosdevices ]]; then
  218. # If VERSION string exists, skip updating that prefix.
  219. if [[ $(printf $(grep -ril "VERSION" ${wineprefix}/playonlinux.cfg &> /dev/null)$?) -ne 0 ]]; then
  220. WINEPREFIX=${wineprefix} wineboot -u
  221. fi
  222. fi
  223. done
  224. fi
  225. if [[ ! -v NO_DXVK ]]; then
  226. for wineprefix in $(find $HOME/.PlayOnLinux/wineprefix -mindepth 1 -maxdepth 1 -type d); do
  227. if [[ -d ${wineprefix}/dosdevices ]]; then
  228. WINEPREFIX=${wineprefix} setup_dxvk
  229. fi
  230. done
  231. fi
  232. }
  233. ##########################################################
  234. # Clean these temporary folders & files
  235. # TODO Shall we remove git folders or keep them?
  236. dxvk_wine_cleanlist=('*.patch' '*.diff' 'pkg' 'src' '*-patches' '*.tar.xz') # dxvk-git wine-*git
  237. ##########################################################
  238. # Validate all buildtime files
  239. checkFiles
  240. # Check whether we build Wine or Wine Staging
  241. checkStaging
  242. # Check whether we have ccache installed
  243. ccacheCheck
  244. # Prepare building environment: copy patches and create timestamped folder for compiled packages
  245. prepare_env
  246. # Clean all previous trash we may have
  247. cleanUp
  248. #########################
  249. # Check Wine & DXVK dependencies, depending on whether these packages
  250. # are to be built
  251. echo -e "\e[1mINFO:\e[0m Checking dependencies for packages.\n"
  252. if [[ ! -v NO_WINE ]]; then
  253. checkDepends "0-wine-staging-git" "${wine_name}" _depends makedepends
  254. fi
  255. if [[ ! -v NO_DXVK ]]; then
  256. checkDepends "0-dxvk-git" "dxvk-git" depends makedepends
  257. fi
  258. check_alldeps
  259. #########################
  260. # Compile Wine & DXVK, depending on whether these packages
  261. # are to be built
  262. if [[ ! -v NO_WINE ]]; then
  263. build_pkg wine "${wine_name}" "0-wine-staging-git" "${dxvk_wine_cleanlist[*]}"
  264. fi
  265. if [[ ! -v NO_DXVK ]]; then
  266. build_pkg dxvk DXVK "0-dxvk-git" "${dxvk_wine_cleanlist[*]}"
  267. fi
  268. #########################
  269. # Update user's PlayonLinux wine prefixes if needed
  270. if [[ ! -v NO_POL ]]; then
  271. echo -e "Updating your PlayOnLinux Wine prefixes.\n"
  272. updatePOL
  273. fi