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.

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