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.

626 lines
16 KiB

5 years ago
5 years ago
  1. #!/bin/env bash
  2. # Compile DXVK git on Debian/Ubuntu/Mint and 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. DXVKROOT="${PWD}"
  22. # datedir variable supplied by ../updatewine_debian.sh script file
  23. datedir="${1}"
  24. ########################################################
  25. # Divide input args into array indexes
  26. i=0
  27. for p in ${@:2}; do
  28. params[$i]=${p}
  29. let i++
  30. done
  31. ########################################################
  32. # Parse input git override hashes
  33. # This order is mandatory!
  34. # If you change the order or contents of 'githash_overrides'
  35. # array in ../updatewine.sh, make sure to update these
  36. # variables!
  37. #
  38. git_commithash_dxvk=${params[0]}
  39. git_commithash_glslang=${params[1]}
  40. git_commithash_meson=${params[2]}
  41. git_branch_dxvk=${params[4]}
  42. git_branch_glslang=${params[5]}
  43. git_branch_meson=${params[6]}
  44. ########################################################
  45. # Parse input arguments, filter user parameters
  46. # The range is defined in ../updatewine.sh
  47. # All input arguments are:
  48. # <datedir> 4*<githash_override> 4*<gitbranch_override> <args>
  49. # 0 1 2 3 4 5 6 7 8 9...
  50. # Filter all but <args>, i.e. the first 0-8 arguments
  51. i=0
  52. for arg in ${params[@]:8}; do
  53. args[$i]="${arg}"
  54. let i++
  55. done
  56. for check in ${args[@]}; do
  57. case ${check} in
  58. --no-install)
  59. NO_INSTALL=
  60. ;;
  61. # --no-winetricks)
  62. # NO_WINETRICKS=
  63. # ;;
  64. --updateoverride)
  65. UPDATE_OVERRIDE=
  66. ;;
  67. --buildpkg-rm)
  68. BUILDPKG_RM=
  69. ;;
  70. esac
  71. done
  72. ########################################################
  73. # PRESENCE OF WINE
  74. # Check presence of Wine. Some version of Wine should
  75. # be found in the system in order to install DXVK.
  76. known_wines=(
  77. 'wine'
  78. 'wine-stable'
  79. 'wine32'
  80. 'wine64'
  81. 'libwine:amd64'
  82. 'libwine:i386'
  83. 'wine-git'
  84. 'wine-staging-git'
  85. )
  86. known_winetricks=(
  87. 'winetricks'
  88. )
  89. function runtimeCheck() {
  90. # Friendly name for this package
  91. local pkgreq_name=${1}
  92. # Known package names to check on Debian
  93. local known_pkgs=${2}
  94. # Check if any of these Wine packages are present on the system
  95. i=0
  96. for pkg in ${known_pkgs[@]}; do
  97. if [[ $(echo $(dpkg -s ${pkg} &>/dev/null)$?) -eq 0 ]]; then
  98. local pkglist[$i]=${pkg}
  99. let i++
  100. fi
  101. done
  102. if [[ -z ${pkglist[*]} ]]; then
  103. echo -e "\e[1mWARNING:\e[0m Not installing DXVK because \e[1m${pkgreq_name}\e[0m is missing on your system.\n\
  104. ${pkgreq_name} should be installed in order to use DXVK. Just compiling DXVK for later use.\n"
  105. # Do this check separately so we can warn about all missing runtime dependencies above
  106. if [[ ! -v NO_INSTALL ]]; then
  107. # Force --no-install switch
  108. NO_INSTALL=
  109. fi
  110. fi
  111. }
  112. ########################################################
  113. # If the script is interrupted (Ctrl+C/SIGINT), do the following
  114. function DXVK_intCleanup() {
  115. rm -rf ${DXVKROOT}/{dxvk-git,meson,glslang}
  116. rm -rf ${DXVKROOT}/../compiled_deb/"${datedir}"
  117. exit 0
  118. }
  119. # Allow interruption of the script at any time (Ctrl + C)
  120. trap "DXVK_intCleanup" INT
  121. ########################################################
  122. # http://wiki.bash-hackers.org/snipplets/print_horizontal_line#a_line_across_the_entire_width_of_the_terminal
  123. function INFO_SEP() { printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - ; }
  124. ########################################################
  125. # Update all packages if UPDATE_OVERRIDE given
  126. if [[ -v UPDATE_OVERRIDE ]]; then
  127. echo -en "Updating all packages" && \
  128. if [[ $(printf $(sudo -n uptime &>/dev/null)$?) -ne 0 ]]; then printf " Please provide your sudo password.\n"; else printf "\n\n"; fi
  129. sudo apt update && sudo apt upgrade -y
  130. fi
  131. ########################################################
  132. # Check do we need to compile the package
  133. # given as input for this function
  134. function pkgcompilecheck() {
  135. local install_function=${1}
  136. local pkg=${2}
  137. local pkg_data=${3}
  138. if [[ $(echo $(dpkg -s ${pkg} &>/dev/null)$?) -ne 0 ]] || [[ -v UPDATE_OVERRIDE ]]; then
  139. ${install_function} ${pkg_data}
  140. fi
  141. }
  142. ########################################################
  143. # DXVK CUSTOM INSTALLATION HOOKS
  144. # These are custom installation instructions for DXVK
  145. # They are not used independently.
  146. function dxvk_install_custom() {
  147. # Use posix alternates for MinGW binaries
  148. function dxvk_posixpkgs() {
  149. local packages=(
  150. 'i686-w64-mingw32-g++'
  151. 'i686-w64-mingw32-gcc'
  152. 'x86_64-w64-mingw32-g++'
  153. 'x86_64-w64-mingw32-gcc'
  154. )
  155. for package in "${packages[@]}"; do
  156. local option=$(echo "" | sudo update-alternatives --config "${package}" | grep posix | sed 's@^[^0-9]*\([0-9]\+\).*@\1@')
  157. echo "${option}" | sudo update-alternatives --config "${package}" &> /dev/null
  158. if [[ $? -ne 0 ]]; then
  159. echo -e "\e[1mERROR:\e[0m Error occured while running 'update-alternatives' for '${package}'. Aborting\n"
  160. exit 1
  161. fi
  162. done
  163. }
  164. ############################
  165. # DXVK - CUSTOM PATCHES
  166. # Add and apply custom DXVK patches
  167. function dxvk_custompatches() {
  168. # Get our current directory, since we will change it during patching process below
  169. # We want to go back here after having applied the patches
  170. local CURDIR="${PWD}"
  171. # Check if the following folder exists, and proceed.
  172. if [[ -d "${DXVKROOT}/../../dxvk_custom_patches" ]]; then
  173. cp -r "${DXVKROOT}/../../dxvk_custom_patches/"*.{patch,diff} "${DXVKROOT}/${pkg_name}/" 2>/dev/null
  174. local dxvk_builddir_name=$(ls -l "${DXVKROOT}/${pkg_name}" | grep ^d | awk '{print $NF}')
  175. # TODO Expecting just one folder here. This method doesn't work with multiple dirs present
  176. if [[ $(echo ${dxvk_builddir_name} | wc -l) -gt 1 ]]; then
  177. echo -e "\e[1mERROR:\e[0m Multiple entries in dxvk build directory detected. Can't decide which one to use. Aborting\n"
  178. exit 1
  179. fi
  180. local dxvk_builddir_path="${DXVKROOT}/${pkg_name}/${dxvk_builddir_name}"
  181. cd "${dxvk_builddir_path}"
  182. for pfile in ../*.{patch,diff}; do
  183. if [[ -f ${pfile} ]]; then
  184. echo -e "Applying DXVK patch: ${pfile}\n"
  185. patch -Np1 < ${pfile}
  186. fi
  187. if [[ $? -ne 0 ]]; then
  188. echo -e "\e[1mERROR:\e[0m Error occured while applying DXVK patch '${pfile}'. Aborting\n"
  189. cd ${CURDIR}
  190. exit 1
  191. fi
  192. done
  193. cd "${CURDIR}"
  194. fi
  195. }
  196. ############################
  197. # DXVK - CUSTOM HOOKS EXECUTION
  198. dxvk_custompatches && \
  199. dxvk_posixpkgs && \
  200. dxvk_custom_deb_build
  201. }
  202. ########################################################
  203. # COMMON - COMPILE AND INSTALL DEB PACKAGE
  204. # Instructions to compile and install a deb package
  205. # on Debian system
  206. # Global variable to track buildtime dependencies
  207. z=0
  208. function compile_and_install_deb() {
  209. ############################
  210. # Set local variables
  211. local _pkg_name="${1}"
  212. local _pkg_license="${2}"
  213. local _pkg_giturl="${3}"
  214. local _pkg_gitbranch="${4}"
  215. local _git_commithash="${5}"
  216. local _pkg_gitver="${6}"
  217. local _pkg_debinstall="${7}"
  218. local _pkg_debcontrol="${8}"
  219. local _pkg_debrules="${9}"
  220. local _pkg_installfile="${10}"
  221. local _pkg_controlfile="${11}"
  222. local _pkg_rulesfile="${12}"
  223. local _pkg_deps_build="${13}"
  224. local _pkg_deps_runtime="${14}"
  225. local _pkg_debbuilder="${15}"
  226. ############################
  227. # COMMON - ARRAY PARAMETER FIX
  228. # Separate array indexes correctly
  229. # We have streamed all array indexes, separated
  230. # by | symbol. We reconstruct the arrays here.
  231. function arrayparser_reverse() {
  232. local arrays=(
  233. '_pkg_deps_build'
  234. '_pkg_deps_runtime'
  235. )
  236. for w in ${arrays[@]}; do
  237. local s=\${${w}}
  238. local IFS='|'
  239. local y=0
  240. for t in $(eval printf '%s\|' ${s}); do
  241. eval ${w}[$y]=\"${t}\"
  242. let y++
  243. done
  244. unset IFS
  245. done
  246. }
  247. arrayparser_reverse
  248. ############################
  249. echo -e "Starting compilation$(if [[ ! -v NO_INSTALL ]] || [[ ${_pkg_name} =~ ^meson|glslang$ ]]; then printf " & installation"; fi) of ${_pkg_name}\n"
  250. ############################
  251. # COMMON - PACKAGE DEPENDENCIES CHECK
  252. # Check and install package related dependencies if they are missing
  253. function pkg_dependencies() {
  254. local _pkg_list="${1}"
  255. local _pkg_type="${2}"
  256. local IFS=$'\n'
  257. case ${_pkg_type} in
  258. buildtime)
  259. local _pkg_type_str="build time"
  260. ;;
  261. runtime)
  262. local _pkg_type_str="runtime"
  263. ;;
  264. esac
  265. if [[ ${_pkg_list[0]} == "empty" ]]; then
  266. return 0
  267. fi
  268. # Generate a list of missing dependencies
  269. local a=0
  270. for p in ${_pkg_list[@]}; do
  271. local p=$(printf '%s' ${p} | awk '{print $1}')
  272. if [[ $(echo $(dpkg -s ${p} &>/dev/null)$?) -ne 0 ]]; then
  273. local _validlist[$a]=${p}
  274. let a++
  275. # Global array to track installed build dependencies
  276. if [[ ${_pkg_type} == "buildtime" ]]; then
  277. _buildpkglist[$z]=${p}
  278. let z++
  279. fi
  280. fi
  281. done
  282. # Install missing dependencies, be informative
  283. local b=0
  284. for _pkg_dep in ${_validlist[@]}; do
  285. echo -e "$(( $b + 1 ))/$(( ${#_validlist[*]} )) - Installing ${_pkg_name} ${_pkg_type_str} dependency ${_pkg_dep}"
  286. sudo apt install -y ${_pkg_dep} &> /dev/null
  287. if [[ $? -eq 0 ]]; then
  288. let b++
  289. else
  290. echo -e "\n\e[1mERROR:\e[0m Error occured while installing ${_pkg_dep}. Aborting.\n"
  291. exit 1
  292. fi
  293. done
  294. if [[ -n ${_validlist[*]} ]]; then
  295. # Add empty newline
  296. echo ""
  297. fi
  298. }
  299. ############################
  300. # COMMON - RETRIEVE PACKAGE
  301. # GIT VERSION TAG
  302. # Get git-based version in order to rename the package main folder
  303. # This is required by deb builder. It retrieves the version number
  304. # from that folder name
  305. function pkg_gitversion() {
  306. if [[ -n "${_pkg_gitver}" ]] && [[ "${_pkg_gitver}" =~ ^git ]]; then
  307. cd ${_pkg_name}
  308. git checkout ${_pkg_gitbranch}
  309. git reset --hard ${_git_commithash}
  310. if [[ $? -ne 0 ]]; then
  311. echo -e "\e[1mERROR:\e[0m Couldn't find commit ${_git_commithash} for ${_pkg_name}. Aborting\n"
  312. exit 1
  313. fi
  314. _pkg_gitver=$(eval "${_pkg_gitver}")
  315. cd ..
  316. fi
  317. }
  318. ############################
  319. # COMMON - OVERWRITE
  320. # DEBIAN BUILD ENV FILES
  321. # Overwrite a file which is given as user input
  322. # The contents are supplied as input, too.
  323. function pkg_override_debianfile() {
  324. local contents=${1}
  325. local targetfile=${2}
  326. if [[ ${contents} != "empty" ]]; then
  327. echo "${contents}" > "${targetfile}"
  328. if [[ $? -ne 0 ]]; then
  329. echo -e "\e[1mERROR:\e[0m Couldn't create Debian file '${targetfile}' for ${_pkg_name}. Aborting\n"
  330. exit 1
  331. fi
  332. fi
  333. }
  334. ############################
  335. # COMMON - GET SOURCE AND
  336. # PREPARE SOURCE FOLDER
  337. function pkg_folderprepare() {
  338. # Remove old build directory, if present
  339. rm -rf ${_pkg_name}
  340. # Create a new build directory, access it and download git sources there
  341. mkdir ${_pkg_name}
  342. cd ${_pkg_name}
  343. echo -e "Retrieving source code of ${_pkg_name} from $(printf ${_pkg_giturl} | sed 's/^.*\/\///; s/\/.*//')\n"
  344. git clone ${_pkg_giturl} ${_pkg_name}
  345. # If sources could be downloaded, rename the folder properly for deb builder
  346. # Access the folder after which package specific debianbuild function will be run
  347. # That function is defined inside package specific install_main function below
  348. if [[ $? -eq 0 ]]; then
  349. pkg_gitversion && \
  350. mv ${_pkg_name} ${_pkg_name}-${_pkg_gitver}
  351. cd ${_pkg_name}-${_pkg_gitver}
  352. dh_make --createorig -s -y -c ${_pkg_license} && \
  353. pkg_override_debianfile "${_pkg_debinstall}" "${_pkg_installfile}"
  354. pkg_override_debianfile "${_pkg_debcontrol}" "${_pkg_controlfile}"
  355. pkg_override_debianfile "${_pkg_debrules}" "${_pkg_rulesfile}"
  356. else
  357. echo -e "\e[1mERROR:\e[0m Error while downloading source of ${_pkg_name} package. Aborting\n"
  358. exit 1
  359. fi
  360. }
  361. ############################
  362. # COMMON - COMPILE, INSTALL
  363. # AND STORE DEB PACKAGE
  364. function pkg_debianbuild() {
  365. # Start deb builder
  366. bash -c "${_pkg_debbuilder}"
  367. # Once our deb package is compiled, install and store it
  368. # We do not make installation optional because this is a core dependency for DXVK
  369. if [[ $? -eq 0 ]]; then
  370. rm -rf ../*.{changes,buildinfo,tar.xz} && \
  371. sudo dpkg -i ../${_pkg_name}*.deb && \
  372. mv ../${_pkg_name}*.deb ../../../compiled_deb/"${datedir}" && \
  373. echo -e "Compiled ${_pkg_name} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  374. cd ../..
  375. rm -rf ${_pkg_name}
  376. else
  377. buildpkg_removal
  378. exit 1
  379. fi
  380. }
  381. ############################
  382. # COMMON - EXECUTION HOOKS
  383. pkg_dependencies "${_pkg_deps_build[*]}" buildtime && \
  384. if [[ ${_pkg_deps_runtime[0]} != "empty" ]] && [[ ! -v NO_INSTALL ]]; then
  385. pkg_dependencies "${_pkg_deps_runtime[*]}" runtime
  386. fi
  387. pkg_folderprepare
  388. # TODO use package name or separate override switch here?
  389. if [[ ${_pkg_name} == *"dxvk"* ]]; then
  390. dxvk_install_custom
  391. fi
  392. pkg_debianbuild
  393. unset _pkg_gitver
  394. }
  395. ########################################################
  396. # BUILD DEPENDENCIES REMOVAL
  397. function buildpkg_removal() {
  398. # Build time dependencies which were installed but no longer needed
  399. if [[ -v _buildpkglist ]]; then
  400. if [[ -v BUILDPKG_RM ]]; then
  401. sudo apt purge --remove -y ${_buildpkglist[*]}
  402. # In some cases, glslang or meson may still be present on the system. Remove them
  403. for _extrapkg in glslang meson; do
  404. if [[ $(echo $(dpkg -s ${_extrapkg} &>/dev/null)$?) -eq 0 ]]; then
  405. sudo apt purge --remove -y ${_extrapkg}
  406. fi
  407. done
  408. else
  409. echo -e "The following build time dependencies were installed and no longer needed:\n\n$(for l in ${_buildpkglist[*]}; do echo -e ${l}; done)\n"
  410. fi
  411. fi
  412. }
  413. ########################################################
  414. # Package installation instructions
  415. function pkg_install_main() {
  416. # Read necessary variables from debdata file
  417. local pkg_datafile=${1}
  418. if [[ -f ${pkg_datafile} ]]; then
  419. source ${pkg_datafile}
  420. else
  421. echo -e "\e[1mERROR:\e[0m Couldn't read datafile '${pkg_datafile}'. Check the file path and try again.\n"
  422. exit 1
  423. fi
  424. ############################
  425. # Prepare these arrays for 'compile_and_install_deb' input
  426. # Separate each array index with | in these arrays
  427. function pkg_arrayparser() {
  428. local pkg_arrays=(
  429. 'pkg_deps_build'
  430. 'pkg_deps_runtime'
  431. )
  432. local IFS=$'\n'
  433. for w in ${pkg_arrays[@]}; do
  434. local s=\${${w}[@]}
  435. local t=$(eval printf '%s\|' ${s})
  436. unset ${w}
  437. eval ${w}=\"${t}\"
  438. done
  439. }
  440. ############################
  441. # Execute package installation procedure
  442. pkg_arrayparser && \
  443. compile_and_install_deb \
  444. "${pkg_name}" \
  445. "${pkg_license}" \
  446. "${pkg_giturl}" \
  447. "${pkg_gitbranch}" \
  448. "${git_commithash}" \
  449. "${pkg_gitver}" \
  450. "${pkg_debinstall}" \
  451. "${pkg_debcontrol}" \
  452. "${pkg_debrules}" \
  453. "${pkg_installfile}" \
  454. "${pkg_controlfile}" \
  455. "${pkg_rulesfile}" \
  456. "${pkg_deps_build}" \
  457. "${pkg_deps_runtime}" \
  458. "${pkg_debbuilder}"
  459. }
  460. ########################################################
  461. # Check existence of known Wine packages
  462. runtimeCheck Wine "${known_wines[*]}"
  463. # Check existence of known Winetricks packages
  464. runtimeCheck Winetricks "${known_winetricks[*]}"
  465. # Meson - compile (& install)
  466. pkgcompilecheck pkg_install_main meson "${DXVKROOT}/meson.debdata"
  467. # Glslang - compile (& install)
  468. pkgcompilecheck pkg_install_main glslang "${DXVKROOT}/glslang.debdata"
  469. # DXVK - compile (& install)
  470. pkg_install_main "${DXVKROOT}/dxvk.debdata"
  471. # Clean buildtime dependencies
  472. buildpkg_removal