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.

420 lines
12 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. #!/bin/bash
  2. # getsource - Simple script to set up Wine Staging + DXVK for PoL wineprefixes
  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. # REQUIREMENTS:
  19. # - Arch Linux or equivalent (uses pacman)
  20. #
  21. # - Existing PlayonLinux package installation and $HOME/.PlayOnLinux folder
  22. # with all relevant subfolders
  23. #
  24. # - git, sudo, pwd...etc.
  25. #
  26. # - dxvk-git and wine-staging-git package dependencies installed
  27. # (see PKGBUILD files ./PKGBUILD and ./0-dxvk-git/PKGBUILD for details)
  28. #
  29. # - Internet connection
  30. #
  31. # - GPU Vulkan support and the most recent Nvidia/AMD drivers
  32. ###########################################################
  33. # Usage
  34. # Run with sudo
  35. #
  36. # # sudo bash ./updatewine.sh
  37. #
  38. # NOTE: All commands are executed as user (defined above).
  39. # Only commands which require root permissions are ones
  40. # which install packages wine-staging-git and dxvk into
  41. # your system
  42. # All regular user commands have prefix 'cmd' below
  43. # Switches:
  44. #
  45. # --refresh
  46. #
  47. # Check for new Staging/DXVK releases, update PoL Wine prefixes if needed
  48. # Does a comparison between local & remote git repos
  49. #
  50. # --check
  51. #
  52. # Check for new Staging/DXVK releases
  53. # Does a comparison between local & remote git repos
  54. #
  55. # --force
  56. #
  57. # Force Wine Staging & DXVK installation
  58. #
  59. ###########################################################
  60. # Get current date
  61. CURDATE=$(date "+%d-%m-%Y %H:%M:%S")
  62. # This variable value is automatically generated. DO NOT CHANGE.
  63. LASTUPDATE=
  64. # This variable value is automatically generated. DO NOT CHANGE.
  65. WINE_VERSION=
  66. ###########################################################
  67. if [[ $UID -ne 0 ]]; then
  68. echo "Run as root or sudo. This permission is required only for package installation."
  69. exit 1
  70. fi
  71. ###########################################################
  72. # Your system username (who has PoL profile // existing Wine prefixes)
  73. # Get it by running 'whoami'
  74. unset USERNAME ERRPKGS
  75. read -r -p "Who has PoL profiles // existing Wine prefixes on the system? [username] " username
  76. echo ""
  77. function check_username {
  78. if [[ $(printf '%s' $username | sed 's/[[:blank:]]//g') == "" ]]; then
  79. echo "Empty username is invalid. Aborting."
  80. exit 1
  81. fi
  82. if [[ $username == "root" ]]; then
  83. echo "Can't use 'root' user. Aborting."
  84. exit 1
  85. fi
  86. local IFS=$'\n'
  87. for validname in $(cat /etc/passwd | awk -F : '{print $1}'); do
  88. if [[ $validname == $username ]]; then
  89. USERNAME=$username
  90. fi
  91. done
  92. if [[ ! -n $USERNAME ]]; then
  93. echo "Couldn't find user '$username'. Please check the name and try again."
  94. exit 1
  95. fi
  96. }
  97. function check_pol {
  98. # Check existence of PoL default folder in user's homedir
  99. local USERHOME=$(grep $USERNAME /etc/passwd | awk -F : '{print $(NF-1)}')
  100. if [[ ! -d "$USERHOME/PlayOnLinux's virtual drives" ]]; then
  101. echo "Warning. Couldn't find PoL directories in the homedir of user $USERNAME."
  102. NOPOL=
  103. fi
  104. }
  105. check_username
  106. check_pol
  107. ###########################################################
  108. # Check package dependencies beforehand, just to avoid
  109. # annoying situations which could occur later while the script
  110. # is already running.
  111. # Just for "packages which are not found" array <=> ERRPKGS
  112. # We need to set it outside of checkDepends function
  113. # because it is a global variable for all checked packages
  114. l=0
  115. function checkDepends {
  116. # The first and the second argument
  117. local packagedir=${1}
  118. local package=${2}
  119. # We get necessary variables to check from this file
  120. local file="./${packagedir}/PKGBUILD"
  121. # All but the (zero), the first and the second argument
  122. # We check the value of these file variables
  123. local file_vars=${@:3}
  124. for var in ${file_vars[*]}; do
  125. # Get the variable and set it as a new variable in the current shell
  126. # This is applicable only to variable arrays! Do not use if the variable is not an array.
  127. local field=$(awk "/^${var}/,/)/" ${file} | sed -r "s/^${var}=|[)|(|']//g")
  128. local i=0
  129. for parse in ${field[*]}; do
  130. if [[ ! $parse =~ ^# ]]; then
  131. local PKGS[$i]=$(printf '%s' $parse | sed 's/[=|>|<].*$//')
  132. let i++
  133. fi
  134. done
  135. # Sort list and delete duplicate index values
  136. # https://stackoverflow.com/questions/13648410/how-can-i-get-unique-values-from-an-array-in-bash
  137. local PKGS_sort=($(printf "${PKGS[*]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
  138. for pkg in ${PKGS_sort[*]}; do
  139. if [[ $(printf $(pacman -Q ${pkg} &>/dev/null)$?) -ne 0 ]]; then
  140. ERRPKGS[$l]=${pkg}
  141. echo -e "\e[91mError:\e[0m Dependency '${pkg}' not found, required by '${package}' (${file} => ${var})"
  142. let l++
  143. fi
  144. done
  145. unset PKGS PKGS_sort var i
  146. done
  147. echo -e " \e[92m=>\e[0m Dependency check for ${package} done.\n"
  148. }
  149. checkDepends "0-wine-staging-git" "wine-staging-git" _depends makedepends
  150. checkDepends "0-dxvk-git" "dxvk-git" depends makedepends
  151. if [[ -v ERRPKGS ]]; then
  152. echo -e "The following dependencies are missing:\n\e[91m$(for o in ${ERRPKGS[@]}; do printf '%s\n' ${o}; done)\e[0m\n"
  153. exit 1
  154. fi
  155. ###########################################################
  156. # Switches
  157. if [[ "${1}" == "--refresh" ]]; then
  158. WINE_INSTALL=
  159. CHECK=
  160. fi
  161. if [[ "${1}" == "--check" ]]; then
  162. CHECK=
  163. fi
  164. if [[ "${1}" == "--force" ]] || [[ $WINE_VERSION == "" ]] || [[ $LASTUPDATE == "" ]]; then
  165. WINE_INSTALL=
  166. FORCE_INSTALL=
  167. fi
  168. if [[ $LASTUPDATE == "" ]]; then
  169. LASTUPDATE="Unknown"
  170. fi
  171. ###########################################################
  172. echo -e "\nLast update: $LASTUPDATE\n"
  173. ORG_CURDIR=$(pwd)
  174. cmd() {
  175. sudo -u $USERNAME bash -c "${*}"
  176. }
  177. ###########################################################
  178. # Check for existing PoL user folder
  179. #if [[ ! -d /home/$USERNAME/.PlayOnLinux ]]; then
  180. # echo "No existing PlayonLinux profiles in $USERNAME's home folder. Aborting"
  181. # exit 1
  182. #fi
  183. ###########################################################
  184. # Check internet connection
  185. function netCheck() {
  186. if [[ $(echo $(wget --delete-after -q -T 5 github.com -o -)$?) -ne 0 ]]; then
  187. echo -e "\nInternet connection failed (GitHub). Please check your connection and try again.\n"
  188. exit 1
  189. fi
  190. cmd "rm -f ./index.html.tmp"
  191. }
  192. ###########################################################
  193. # Local/Remote git comparisons
  194. function gitCheck() {
  195. netCheck
  196. if [[ -v FORCE_INSTALL ]]; then
  197. NEEDSBUILD=1
  198. return 0
  199. fi
  200. if [[ ! -d "${1}" ]]; then
  201. NEEDSBUILD=1
  202. return 1
  203. fi
  204. echo -e "=> Checking ${2} GIT for changes\n"
  205. local CURDIR="${PWD}"
  206. cd "${1}"
  207. local LOCAL_GIT=$(git rev-parse @)
  208. local REMOTE_GIT=$(git ls-remote origin -h refs/heads/master | awk '{print $1}')
  209. echo -e "\t${2}:\n\tlocal git: $LOCAL_GIT\n\tremote git: $REMOTE_GIT"
  210. if [[ $LOCAL_GIT != $REMOTE_GIT ]]; then
  211. # true
  212. echo -e "\e[91m\n\t${2} needs to be updated\e[0m\n"
  213. NEEDSBUILD=1
  214. else
  215. # false
  216. echo -e "\e[92m\n\t${2} is updated\e[0m\n"
  217. NEEDSBUILD=0
  218. fi
  219. cd "${CURDIR}"
  220. }
  221. ###########################################################
  222. # Remove any existing pkg,src or tar.xz packages left by previous pacman commands
  223. cmd "rm -rf ./*/{pkg,src,*.tar.xz}"
  224. cmd "rm -f ./0-wine-staging-git/*.patch"
  225. if [[ $? -ne 0 ]]; then
  226. echo "Could not remove previous pacman-generated Wine source folders"
  227. exit 1
  228. fi
  229. ###########################################################
  230. # Do git check for Wine Staging
  231. gitCheck ./0-wine-staging-git/wine-staging-git Wine
  232. # If needs build and --check switch is not used
  233. if [[ $NEEDSBUILD -eq 1 ]] && [[ ! -v CHECK ]]; then
  234. # Create wine-staging-git package and install it to the system
  235. cd "${ORG_CURDIR}"/0-wine-staging-git
  236. cmd "updpkgsums && makepkg ;"
  237. if [[ $(find . -mindepth 1 -maxdepth 1 -type f -iname "wine-*tar.xz" | wc -l) -ne 0 ]]; then
  238. pacman -U --noconfirm wine-*.tar.xz
  239. else
  240. cmd "rm -rf ./{*.patch,pkg,src}"
  241. exit 1
  242. fi
  243. if [[ $? -eq 0 ]]; then
  244. cmd "rm -rf ./{*.patch,pkg,src,*.tar.xz}"
  245. WINE_INSTALL=
  246. WINE_VERSION_UPDATE=$(pacman -Qi wine-staging-git | grep 'Version' | awk '{print $NF}')
  247. else
  248. exit 1
  249. fi
  250. cd ..
  251. fi
  252. #############################
  253. # Create dxvk-git package and install it to the system
  254. gitCheck ./0-dxvk-git/dxvk-git DXVK
  255. # If needs build and --check switch is not used
  256. if [[ $NEEDSBUILD -eq 1 ]] && [[ ! -v CHECK ]]; then
  257. # Create dxvk-git package and install it to the system
  258. cd "${ORG_CURDIR}"/0-dxvk-git
  259. cmd "updpkgsums && makepkg ;"
  260. if [[ $(find . -mindepth 1 -maxdepth 1 -type f -iname "dxvk-git-*tar.xz" | wc -l) -ne 0 ]]; then
  261. pacman -U --noconfirm dxvk-git*.tar.xz
  262. else
  263. cmd "rm -rf ./{pkg,src}"
  264. exit 1
  265. fi
  266. if [[ $? -eq 0 ]]; then
  267. cmd "rm -rf ./{pkg,src,dxvk-git*.tar.xz}"
  268. else
  269. exit 1
  270. fi
  271. fi
  272. cd ..
  273. # If a new Wine Staging version was installed and 'System' version of Wine has been used in
  274. # PoL wineprefix configurations, update those existing PoL wineprefixes
  275. if [[ -v WINE_INSTALL ]] && [[ ! -v NOPOL ]]; then
  276. for wineprefix in $(find /home/$USERNAME/.PlayOnLinux/wineprefix -mindepth 1 -maxdepth 1 -type d); do
  277. if [[ -d ${wineprefix}/dosdevices ]]; then
  278. # If VERSION string exists, skip updating that prefix.
  279. if [[ $(printf $(grep -ril "VERSION" ${wineprefix}/playonlinux.cfg &> /dev/null)$?) -ne 0 ]]; then
  280. # If currently installed Wine version is not same than we just built.
  281. if [[ -v WINE_VERSION_UPDATE ]]; then
  282. if [[ "${WINE_VERSION}" != "${WINE_VERSION_UPDATE}" ]]; then
  283. cmd "WINEPREFIX=${wineprefix} wineboot -u"
  284. fi
  285. fi
  286. fi
  287. fi
  288. done
  289. fi
  290. # Install dxvk-git to every PlayOnLinux wineprefix
  291. if [[ $? -eq 0 ]] && [[ ! -v NOPOL ]]; then
  292. for wineprefix in $(find /home/$USERNAME/.PlayOnLinux/wineprefix -mindepth 1 -maxdepth 1 -type d); do
  293. if [[ -d ${wineprefix}/dosdevices ]]; then
  294. if [[ $(printf $(grep -ril "\"d3d11\"=\"native\"" ${wineprefix}/user.reg &> /dev/null)$?) -ne 0 ]]; then
  295. cmd "WINEPREFIX=${wineprefix} setup_dxvk32"
  296. cmd "WINEPREFIX=${wineprefix} setup_dxvk64"
  297. fi
  298. # For D3D10 DXVK support
  299. if [[ $(printf $(grep -ril "\"\*d3dcompiler_43\"=\"native\"" ${wineprefix}/user.reg &> /dev/null)$?) -ne 0 ]]; then
  300. cmd "WINEPREFIX=${wineprefix} winetricks d3dcompiler_43"
  301. fi
  302. fi
  303. done
  304. fi
  305. # If a new Wine Staging version was installed, update WINE_VERSION string variable in this script file
  306. if [[ -v WINE_VERSION_UPDATE ]]; then
  307. cmd "sed -i 's/^WINE_VERSION=.*/WINE_VERSION=\"${WINE_VERSION_UPDATE}\"/' $ORG_CURDIR/updatewine.sh"
  308. fi
  309. # Update LASTUPDATE variable string, if --check switch is not used + a new Wine Staging version is used or NEEDSBUILD variable is set to 1
  310. if [[ ! -v CHECK ]]; then
  311. if [[ -v WINE_INSTALL ]] || [[ $NEEDSBUILD -eq 1 ]]; then
  312. cmd "sed -i 's/^LASTUPDATE=.*/LASTUPDATE=\"$CURDATE\"/' $ORG_CURDIR/updatewine.sh"
  313. fi
  314. fi
  315. # Unset various env vars
  316. unset CHECK WINE_INSTALL FORCE_INSTALL l