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.

595 lines
17 KiB

6 years ago
6 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. # Parse input arguments
  26. i=0
  27. for arg in ${@:2}; do
  28. args[$i]="${arg}"
  29. let i++
  30. done
  31. # Must be a true array as defined above, not a single index list!
  32. #args="${@:2}"
  33. for check in ${args[@]}; do
  34. case ${check} in
  35. --no-install)
  36. NO_INSTALL=
  37. ;;
  38. --updateoverride)
  39. UPDATE_OVERRIDE=
  40. ;;
  41. --buildpkg-rm)
  42. BUILDPKG_RM=
  43. ;;
  44. esac
  45. done
  46. ###########################################################
  47. # Check presence of Wine. Some version of Wine should
  48. # be found in the system in order to install DXVK.
  49. function wineCheck() {
  50. # Known Wine package names to check on Debian
  51. local known_wines=(
  52. 'wine'
  53. 'wine32'
  54. 'wine64'
  55. 'wine-git'
  56. 'wine-staging-git'
  57. 'libwine:amd64'
  58. 'libwine:i386'
  59. )
  60. # Check if any of these Wine packages are present on the system
  61. i=0
  62. for winepkg in ${known_wines[@]}; do
  63. if [[ $(echo $(dpkg -s ${winepkg} &>/dev/null)$?) -eq 0 ]]; then
  64. winelist[$i]=${winepkg}
  65. let i++
  66. fi
  67. done
  68. if [[ -z ${winelist[*]} ]] && [[ ! -v NO_INSTALL ]] ; then
  69. echo -e "\e[1mWARNING:\e[0m Not installing DXVK because Wine is missing on your system.\n\
  70. Wine should be installed in order to use DXVK. Just compiling DXVK for later use.\n"
  71. # Force --no-install switch
  72. NO_INSTALL=
  73. fi
  74. }
  75. wineCheck
  76. ###########################################################
  77. # If the script is interrupted (Ctrl+C/SIGINT), do the following
  78. function DXVK_intCleanup() {
  79. rm -rf ${DXVKROOT}/{dxvk-git,meson,glslang}
  80. rm -rf ${DXVKROOT}/../compiled_deb/"${datedir}"
  81. exit 0
  82. }
  83. # Allow interruption of the script at any time (Ctrl + C)
  84. trap "DXVK_intCleanup" INT
  85. ########################################################
  86. # http://wiki.bash-hackers.org/snipplets/print_horizontal_line#a_line_across_the_entire_width_of_the_terminal
  87. function INFO_SEP() { printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - ; }
  88. ##################################
  89. # Update all packages if UPDATE_OVERRIDE given
  90. if [[ -v UPDATE_OVERRIDE ]]; then
  91. echo -en "Updating all packages" && \
  92. if [[ $(printf $(sudo -n uptime &>/dev/null)$?) -ne 0 ]]; then printf " Please provide your sudo password.\n"; else printf "\n\n"; fi
  93. sudo apt update && sudo apt upgrade -y
  94. fi
  95. ##################################
  96. # Check do we need to compile the package
  97. # given as input for this function
  98. function pkgcompilecheck() {
  99. local pkg=${1}
  100. local install_function=${2}
  101. if [[ $(echo $(dpkg -s ${pkg} &>/dev/null)$?) -ne 0 ]] || [[ -v UPDATE_OVERRIDE ]]; then
  102. ${install_function}
  103. fi
  104. }
  105. ###################################################
  106. # Global variable to track buildtime dependencies
  107. z=0
  108. function preparepackage() {
  109. # Set local variables
  110. local _pkgname=${1}
  111. local _pkgdeps_build=${2}
  112. local _pkgurl=${3}
  113. local _pkgver=${4}
  114. echo -e "Starting compilation$(if [[ ! -v NO_INSTALL ]] || [[ ${_pkgname} =~ ^meson|glslang$ ]]; then printf " & installation"; fi) of ${1}\n"
  115. # Optional variable for runtime dependencies array
  116. if [[ -n ${5} ]]; then local _pkgdeps_runtime=${5}; fi
  117. # Check and install package related dependencies if they are missing
  118. function pkgdependencies() {
  119. local pkglist="${1}"
  120. local pkgtype="${2}"
  121. # Generate a list of missing dependencies
  122. local a=0
  123. for p in ${pkglist[@]}; do
  124. if [[ $(echo $(dpkg -s ${p} &>/dev/null)$?) -ne 0 ]]; then
  125. local validlist[$a]=${p}
  126. let a++
  127. # Global array to track installed build dependencies
  128. if [[ ${pkgtype} == "buildtime" ]]; then
  129. buildpkglist[$z]=${p}
  130. let z++
  131. fi
  132. fi
  133. done
  134. # Install missing dependencies, be informative
  135. local b=0
  136. for pkgdep in ${validlist[@]}; do
  137. echo -e "$(( $b + 1 ))/$(( ${#validlist[*]} )) - Installing ${_pkgname} dependency ${pkgdep}"
  138. sudo apt install -y ${pkgdep} &> /dev/null
  139. if [[ $? -eq 0 ]]; then
  140. let b++
  141. else
  142. echo -e "\nError occured while installing ${pkgdep}. Aborting.\n"
  143. exit 1
  144. fi
  145. done
  146. if [[ -n ${validlist[*]} ]]; then
  147. # Add empty newline
  148. echo ""
  149. fi
  150. }
  151. # Get git-based version in order to rename the package main folder
  152. # This is required by deb builder. It retrieves the version number
  153. # from that folder name
  154. function pkgversion() {
  155. if [[ -n "${_pkgver}" ]] && [[ "${_pkgver}" =~ ^git ]]; then
  156. cd ${_pkgname}
  157. _pkgver=$(eval "${_pkgver}")
  158. cd ..
  159. fi
  160. }
  161. function pkgfoldername() {
  162. # Remove old build directory, if present
  163. rm -rf ${_pkgname}
  164. # Create a new build directory, access it and download git sources there
  165. mkdir ${_pkgname}
  166. cd ${_pkgname}
  167. echo -e "Retrieving source code of ${_pkgname} from $(printf ${_pkgurl} | sed 's/^.*\/\///; s/\/.*//')\n"
  168. git clone ${_pkgurl} ${_pkgname}
  169. # If sources could be downloaded, rename the folder properly for deb builder
  170. # Access the folder after which package specific debianbuild function will be run
  171. # That function is defined inside package specific install_main function below
  172. if [[ $? -eq 0 ]]; then
  173. pkgversion && \
  174. mv ${_pkgname} ${_pkgname}-${_pkgver}
  175. cd ${_pkgname}-${_pkgver}
  176. else
  177. echo -e "Error while downloading source of ${_pkgname} package. Aborting\n"
  178. exit 1
  179. fi
  180. }
  181. # Execute above functions
  182. pkgdependencies "${_pkgdeps_build[*]}" buildtime && \
  183. if [[ -v _pkgdeps_runtime ]]; then pkgdependencies "${_pkgdeps_runtime[*]}" runtime ; fi
  184. pkgfoldername
  185. unset _pkgver
  186. }
  187. ###################################################
  188. # MESON COMPILATION & INSTALLATION
  189. # Required by DXVK package
  190. function meson_install_main() {
  191. # Package name
  192. local pkgname="meson"
  193. # Build time dependencies
  194. local pkgdeps_build=(
  195. 'python3'
  196. 'dh-python'
  197. 'python3-setuptools'
  198. 'ninja-build'
  199. )
  200. # Git source location
  201. local pkgurl="https://github.com/mesonbuild/meson"
  202. # Parsed version number from git source files
  203. local pkgver_git="git describe --long | sed 's/\-[a-z].*//; s/\-/\./; s/[a-z]//g'"
  204. # Location of Debian compilation instructions archive
  205. local pkgurl_debian="http://archive.ubuntu.com/ubuntu/pool/universe/m/meson/meson_0.45.1-2.debian.tar.xz"
  206. function meson_debianbuild() {
  207. # Download predefined Meson debian rules archive
  208. # Extract it, and finally delete the archive
  209. wget ${pkgurl_debian} -O debian.tar.xz
  210. tar xf debian.tar.xz && rm debian.tar.xz
  211. # Get sed compatible Meson version string
  212. local meson_version=$(printf '%s' $(pwd | sed -e 's/.*\-//' -e 's/\./\\\./g'))
  213. # Do not perform any tests or checks during compilation process
  214. sed -ir '/nocheck/d' debian/control
  215. sed -ir '/\.\/run_tests\.py/d' debian/rules
  216. # Downgrade debhelper version requirement for Debian compatilibity
  217. sed -ir 's/debhelper (>= 11)/debhelper (>= 10)/' debian/control
  218. # Correct & update package version number + debian rules
  219. sed -ir "s/0\.45\.1-2/${meson_version}/" debian/changelog
  220. # Delete the following strings from debian/rules file
  221. # They are deprecated
  222. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/mesontest/d' debian/rules
  223. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/mesonconf/d' debian/rules
  224. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/mesonintrospect/d' debian/rules
  225. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/wraptool/d' debian/rules
  226. sed -ir '/rm \-rf \$\$(pwd)\/debian\/meson\/usr\/lib\/python3/d' debian/rules
  227. # Remove deprecated, downloaded patch files
  228. rm -rf debian/patches
  229. # Remove irrelevant sample files
  230. rm -rf debian/*.{ex,EX}
  231. # Start deb builder. Do not build either debug symbols or doc files
  232. DEB_BUILD_OPTIONS="strip nodocs noddebs nocheck" dpkg-buildpackage -rfakeroot -b -us -uc
  233. # Once compiled, install and store the compiled deb archive
  234. # We do not make installation optional because this is a core dependency for DXVK
  235. if [[ $? -eq 0 ]]; then
  236. rm -rf ../*.{changes,buildinfo,tar.xz} && \
  237. sudo dpkg -i ../${pkgname}*.deb && \
  238. mv ../${pkgname}*.deb ../../../compiled_deb/"${datedir}" && \
  239. echo -e "Compiled ${pkgname} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  240. cd ../..
  241. rm -rf ${pkgname}
  242. else
  243. exit 1
  244. fi
  245. }
  246. # Execute above functions
  247. preparepackage "${pkgname}" "${pkgdeps_build[*]}" "${pkgurl}" "${pkgver_git}" && \
  248. meson_debianbuild
  249. }
  250. ###################################################
  251. # GLSLANG COMPILATION & INSTALLATION
  252. # Required by DXVK package
  253. function glslang_install_main() {
  254. # Package name
  255. local pkgname="glslang"
  256. # Build time dependencies
  257. local pkgdeps_build=('cmake' 'python2.7')
  258. # Git source location
  259. local pkgurl="https://github.com/KhronosGroup/glslang"
  260. # Parsed version number from git source files
  261. local pkgver_git="git describe --long | sed 's/\-[a-z].*//; s/\-/\./; s/[a-z]//g'"
  262. function glslang_debianbuild() {
  263. # Create debian subdirectory
  264. dh_make --createorig -s -y -c bsd
  265. # Set Build dependencies into debian/control file
  266. sed -ie "s/^Build-Depends:.*$/Build-Depends: debhelper (>=10), $(echo ${_coredeps[*]} | \
  267. sed 's/\s/, /g'), $(echo ${pkgdeps_build[*]} | sed 's/\s/, /g')/g" debian/control
  268. # Skip running override_dh_usrlocal while executing deb builder
  269. printf 'override_dh_usrlocal:' | tee -a debian/rules
  270. # Remove irrelevant sample files
  271. rm -rf debian/*.{ex,EX}
  272. # Start deb builder. Do not build either debug symbols or doc files
  273. DEB_BUILD_OPTIONS="strip nodocs noddebs" dpkg-buildpackage -rfakeroot -b -us -uc
  274. # Once compiled, install and store the compiled deb archive
  275. # We do not make installation optional because this is a core dependency for DXVK
  276. if [[ $? -eq 0 ]]; then
  277. rm -rf ../*.{changes,buildinfo,tar.xz} && \
  278. sudo dpkg -i ../${pkgname}*.deb && \
  279. mv ../${pkgname}*.deb ../../../compiled_deb/"${datedir}" && \
  280. echo -e "Compiled ${pkgname} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  281. cd ../..
  282. rm -rf ${pkgname}
  283. else
  284. exit 1
  285. fi
  286. }
  287. # Execute above functions
  288. preparepackage "${pkgname}" "${pkgdeps_build[*]}" "${pkgurl}" "${pkgver_git}" && \
  289. glslang_debianbuild
  290. }
  291. ###################################################
  292. # DXVK COMPILATION & INSTALLATION
  293. function dxvk_install_main() {
  294. # Package name
  295. local pkgname="dxvk-git"
  296. # Build time dependencies
  297. local pkgdeps_build=(
  298. 'meson'
  299. 'glslang'
  300. 'gcc-mingw-w64-x86-64'
  301. 'gcc-mingw-w64-i686'
  302. 'g++-mingw-w64-x86-64'
  303. 'g++-mingw-w64-i686'
  304. 'mingw-w64-x86-64-dev'
  305. 'mingw-w64-i686-dev'
  306. )
  307. # Runtime dependencies
  308. local pkgdeps_runtime=('wine' 'winetricks')
  309. # Git source location
  310. local pkgurl="https://github.com/doitsujin/dxvk"
  311. # Parsed version number from git source files
  312. local pkgver_git="git describe --long | sed 's/\-[a-z].*//; s/\-/\./; s/[a-z]//g'"
  313. # Use posix alternates for MinGW binaries
  314. function dxvk_posixpkgs() {
  315. local packages=(
  316. 'i686-w64-mingw32-g++'
  317. 'i686-w64-mingw32-gcc'
  318. 'x86_64-w64-mingw32-g++'
  319. 'x86_64-w64-mingw32-gcc'
  320. )
  321. for package in "${packages[@]}"; do
  322. local option=$(echo "" | sudo update-alternatives --config "${package}" | grep posix | sed 's@^[^0-9]*\([0-9]\+\).*@\1@')
  323. echo "${option}" | sudo update-alternatives --config "${package}" &> /dev/null
  324. if [[ $? -ne 0 ]]; then
  325. echo -e "Error occured while running 'update-alternatives' for '${package}'. Aborting\n"
  326. exit 1
  327. fi
  328. done
  329. }
  330. function dxvk_custompatches() {
  331. # Get our current directory, since we will change it during patching process below
  332. # We want to go back here after having applied the patches
  333. local CURDIR=${PWD}
  334. # Check if the following folder exists, and proceed.
  335. if [[ -d ${DXVKROOT}/../../dxvk_custom_patches ]]; then
  336. cp -r ${DXVKROOT}/../../dxvk_custom_patches/*.{patch,diff} ${DXVKROOT}/${pkgname}/ 2>/dev/null
  337. local dxvk_builddir_name=$(ls ${DXVKROOT}/${pkgname}/)
  338. # TODO Expecting just one folder here. This method doesn't work with multiple dirs present
  339. if [[ $(echo ${dxvk_builddir_name} | wc -l) -gt 1 ]]; then
  340. echo "Error: Multiple entries in dxvk build directory detected. Can't decide which one to use. Aborting\n"
  341. exit 1
  342. fi
  343. local dxvk_builddir_path="${DXVKROOT}/${pkgname}/${dxvk_builddir_name}"
  344. cd "${dxvk_builddir_path}"
  345. for pfile in ../*.{patch,diff}; do
  346. if [[ -f ${pfile} ]]; then
  347. echo -e "Applying DXVK patch: ${pfile}\n"
  348. patch -Np1 < ${pfile}
  349. fi
  350. if [[ $? -ne 0 ]]; then
  351. echo -e "Error occured while applying DXVK patch '${pfile}'. Aborting\n"
  352. cd ${CURDIR}
  353. exit 1
  354. fi
  355. done
  356. cd ${CURDIR}
  357. fi
  358. }
  359. # Debian-specific compilation & installation rules
  360. function dxvk_debianbuild() {
  361. local dxvx_relative_builddir="debian/source/dxvk-master"
  362. # Create debian subdirectory, add supplied LICENSE file
  363. dh_make --createorig -s -y -c custom --copyrightfile ../LICENSE
  364. # Set Build dependencies into debian/control file
  365. sed -ie "s/^Build-Depends:.*$/Build-Depends: debhelper (>=10), $(echo ${_coredeps[*]} | \
  366. sed 's/\s/, /g'), $(echo ${pkgdeps_build[*]} | sed 's/\s/, /g')/g" debian/control
  367. # Set Runtime dependencies into debian/control file
  368. sed -ie "s/^Depends:.*$/Depends: $(echo ${pkgdeps_runtime} | sed 's/\s/, /g')/g" debian/control
  369. # Tell deb builder to bundle these files
  370. printf "${dxvx_relative_builddir}/setup_dxvk.verb usr/share/dxvk/" > debian/install
  371. printf "\n${dxvx_relative_builddir}/bin/* usr/bin/" >> debian/install
  372. # Remove irrelevant sample files
  373. rm -rf debian/*.{ex,EX}
  374. # Overwrite debian/rules file with the following contents
  375. cat << 'DXVK-DEBIANRULES' > debian/rules
  376. #!/usr/bin/make -f
  377. %:
  378. dh $@
  379. override_dh_auto_configure:
  380. override_dh_usrlocal:
  381. DXVK-DEBIANRULES
  382. # Start DXVK compilation
  383. bash ./package-release.sh master debian/source/ --no-package
  384. if [[ $? -ne 0 ]]; then
  385. echo "Error while compiling ${pkgname}. Check messages above. Aborting\n"
  386. exit 1
  387. fi
  388. # Make a proper executable script for setup_dxvk.verb file
  389. mkdir -p ${dxvx_relative_builddir}/bin
  390. echo -e "#!/bin/sh\nwinetricks --force /usr/share/dxvk/setup_dxvk.verb" \
  391. > "${dxvx_relative_builddir}/bin/setup_dxvk"
  392. chmod +x "${dxvx_relative_builddir}/bin/setup_dxvk"
  393. # Tell deb builder to install DXVK x32 & x64 subfolders
  394. for arch in 64 32; do
  395. mkdir -p ${dxvx_relative_builddir}/x${arch}
  396. printf "\n${dxvx_relative_builddir}/x${arch}/* usr/share/dxvk/x${arch}/" >> debian/install
  397. done
  398. # Start deb builder. Do not build either debug symbols or doc files
  399. DEB_BUILD_OPTIONS="strip nodocs noddebs" dpkg-buildpackage -us -uc -b --source-option=--include-binaries
  400. # Once compiled, possibly install and store the compiled deb archive
  401. if [[ $? -eq 0 ]]; then
  402. if [[ ! -v NO_INSTALL ]]; then
  403. sudo dpkg -i ../${pkgname}*.deb
  404. fi
  405. rm -rf ../*.{changes,buildinfo,tar.xz}
  406. mv ../${pkgname}*.deb ../../../compiled_deb/"${datedir}" && \
  407. echo -e "Compiled ${pkgname} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  408. cd ../..
  409. rm -rf ${pkgname}
  410. else
  411. exit 1
  412. fi
  413. }
  414. # Execute above functions
  415. # Do not check runtime dependencies as our check method expects exact package name in
  416. # function 'preparepackage'. This does not apply to runtime dependency 'wine', which
  417. # may be 'wine', 'wine-git', 'wine-staging-git' etc. in truth
  418. #
  419. preparepackage "${pkgname}" "${pkgdeps_build[*]}" "${pkgurl}" "${pkgver_git}" && \
  420. dxvk_posixpkgs && \
  421. dxvk_custompatches && \
  422. dxvk_debianbuild
  423. }
  424. ####################################################################
  425. pkgcompilecheck meson meson_install_main
  426. pkgcompilecheck glslang glslang_install_main
  427. dxvk_install_main
  428. ##########################
  429. # Build time dependencies which were installed but no longer needed
  430. if [[ -v buildpkglist ]]; then
  431. if [[ -v BUILDPKG_RM ]]; then
  432. sudo apt purge --remove -y "${buildpkglist[*]}"
  433. # In some cases, glslang or meson may still be present on the system. Remove them
  434. for extrapkg in glslang meson; do
  435. if [[ $(echo $(dpkg -s ${extrapkg} &>/dev/null)$?) -eq 0 ]]; then
  436. sudo apt purge --remove -y ${extrapkg}
  437. fi
  438. done
  439. else
  440. 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"
  441. fi
  442. fi