Import vkd3d pages from MediaWiki. authored by Alexandre Julliard's avatar Alexandre Julliard
As of version 7.4, Wine comes with a bundled version of vkd3d.
However, if you want to use a more modern version of vkd3d, apply
certain patches to it, or test fixes of your own, you will need Wine to
work with a custom version of vkd3d.
For this purpose, it is necessary to build both projects and link them
correctly.
Compiling a Windows on Windows (WoW) version of Wine, so that it
supports both 32-bits and 64-bits Windows applications – which is often
desired – adds a layer of complexity to the build process.
Furthermore, you may want to use MinGW to cross-compile the Wine
executables and DLLs in the Windows PE format. This is because various
programs expect the on-disk DLLs to look like real PE DLLs.
This guide aims to help you through that process.
# Preliminaries
## Install Wine dependencies
First, install the dependencies listed in the [Building
Wine](https://gitlab.winehq.org/wine/wine/-/wikis/Building-Wine#satisfying-build-dependencies) article.
Remember to install the `:i386` version of the required packages too (if
your system has multi-lib support).
The **mingw** and **vulkan** packages are of particular importance.
It is also recommended that you install `ccache`, as it may save us a
considerable amount of time during the builds.
If you have a system-wide installation of vkd3d, it may be good to
uninstall it using `make uninstall`. To ensure that the correct version
of vkd3d is linked in this tutorial.
## Directory organization
For this tutorial we will need to create several build directories and
have several git repositories. For this reason, we will start by
creating a common directory for them:
``` sh
$ mkdir -p $HOME/wine-dirs
```
## Cloning `wine` and `vkd3d` repositories
First, we clone the `wine` repository if we haven't already:
``` sh
$ git clone https://gitlab.winehq.org/wine/wine.git $HOME/wine-dirs/wine-git
```
We also need to clone `vkd3d` repository if we haven't already:
``` sh
$ git clone https://gitlab.winehq.org/wine/vkd3d.git $HOME/wine-dirs/vkd3d-git
```
In case you already have these repositories somewhere else, you can
create symbolic links inside `wine-dirs` instead:
``` sh
$ cd $HOME/wine-dirs
$ ln -s <relative-path-to-wine-repo> wine-git
$ ln -s <relative-path-to-vkd3d-repo> vkd3d-git
```
Now it is a good time to pick a particular branch or apply the desired
patches to these repositories.
# Building
## Build WIDL
If the distribution provides a recent enough version (3.21 or later as
of this writing) of WIDL, we can skip this step. On Debian that's
provided by the `mingw-w64-tools` package. We can also skip this step if
we already have 64-bit Wine available and built.
Vkd3d uses WIDL to compile its IDL files, and if the distribution
doesn't provide a package, we'll have to build it from the Wine
repository to get it. We start by creating the build directory:
``` sh
$ cd $HOME/wine-dirs
$ mkdir wine64p
```
We run the Wine `configure` script from the installation folder
``` sh
$ cd wine64p
$ ../wine-git/configure --enable-win64 CC='ccache gcc' x86_64_CC='ccache x86_64-w64-mingw32-gcc'
```
Note that we use `x86_64_CC` to indicate the compiler used for
cross-compilation, in this case we need the 64-bit mingw32 compiler. We
prepend `ccache` which works as a wrapper for the compiler. The same is
done for the regular C compiler, `gcc`, passed with the `CC` variable.
Note that to know about other parameters for the `configure` script we
can use:
``` sh
$ ../wine-git/configure --help
```
Also, if something from the configure command fails, it is useful to
search in `config.log` for the line that contains the pertinent error,
and the lines before and after it.
Once the configure script has finished, we use `make tools/widl/widl` to
only compile WIDL. We can pass `-j`<n> to use <n> threads.
``` sh
$ make -j8 tools/widl/widl
```
## Build a 64-bit vkd3d installation
Now we need to build 64-bit vkd3d. For that purpose we will also need
the Vulkan and SPIR-V headers. One way of getting them is downloading
the [Vulkan SDK](https://vulkan.lunarg.com).
Alternativelly, you can get them from the official
[Vulkan-Headers](https://github.com/KhronosGroup/Vulkan-Headers) and
[SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers)
repositories.
Another alternative is to copy them from your distribution. Usually the
host headers will be installed in `/usr/include/vulkan/` and
`/usr/include/spirv/`.
Assuming you downloaded and extracted the SDK, move it to the common
directory:
``` sh
$ mv <vulkan sdk path> $HOME/wine-dirs/vulkan-sdk
```
You must change the first argument of the `mv` command depending on
where you downloaded and extracted the SDK. e.g.
`~/Downloads/vulkansdk-linux-x86_64-1.3.204.1/1.3.204.1`.
We have to run `autogen.sh` in `vkd3d-git` to generate vkd3d's
`configure` script
``` sh
$ cd $HOME/wine-dirs/vkd3d-git
$ ./autogen.sh
```
Now we create a folder for the 64-bit vkd3d build
``` sh
$ cd $HOME/wine-dirs
$ mkdir vkd3d64
```
We run the configure script in the installation folder:
``` sh
$ cd vkd3d64
$ ../vkd3d-git/configure \
--host=x86_64-w64-mingw32 \
--prefix="$HOME/wine-dirs/vkd3d64-prefix" \
WIDL="$HOME/wine-dirs/wine64p/tools/widl/widl" \
SONAME_LIBVULKAN="vulkan-1.dll" \
CPPFLAGS="-I$HOME/wine-dirs/vulkan-sdk/x86_64/include" \
LDFLAGS="-static-libgcc"
```
- `--host=x86_64-w64-mingw32` indicates that we want to cross-compile
the programs and libraries using the 64-bit MinGW compiler.
- `--prefix="$HOME/wine-dirs/vkd3d64-prefix"` is used to set this
build's installation directory. In this case, we will create a new
folder inside `wine-dirs`. We have to keep in mind that the other
programs will expect the vkd3d libraries to be in this directory at
run-time.
- We set the `WIDL` variable to point to our provisional 64-bit Wine's
WIDL. When using the distribution's WIDL, `configure` should generally
be able to find WIDL on its own and this variable can be omitted; if
not, point it to the location of the distribution's WIDL.
- `SONAME_LIBVULKAN` indicates the name of the Vulkan library to load at
run-time.
- We use `CPPFLAGS` so that the compiler knows to search in the
`vulkan-sdk` folder for the vulkan headers (`-I` flag). Note that you
cannot pass `-I/usr/include/` here to use the host headers; this will
result in incorrect detection of headers like `dlfcn.h`. You will need
to copy or link host headers to a separate directory.
- We use `LDFLAGS="-static-libgcc"` because MinGW gcc depends on
`libgcc_s_sjlj-1.dll`; this links a static version. Alternatively, you
can add the correct path to `--with-system-dllpath` as described
below.
Then we run
``` sh
$ make
```
Append `-j$(nproc)` to parallelize.
And if the build succeeds, then we run
``` sh
$ make install
```
to install 64-bit vkd3d in `$HOME/wine-dirs/vkd3d64-prefix`.
## Build 64-bit wine
Now with the 64-bit `vkd3d` installation, we can compile a 64-bit Wine
linked to it.
If you do not have a 64-bit wine tree already, create a new one:
``` sh
$ cd $HOME/wine-dirs
$ mkdir wine64
```
Alternatively, you can reuse the same "provisional" Wine tree.
We run the Wine `configure` script again, but now specifying the
parameters to link Wine to the 64-bit vkd3d prefix we just created. We
will also need to include the vulkan headers:
``` sh
$ cd wine64
$ ../wine-git/configure --enable-win64 \
CC='ccache gcc' x86_64_CC='ccache x86_64-w64-mingw32-gcc' \
--with-system-dllpath="$HOME/wine-dirs/vkd3d64-prefix/bin:<mingw 64-bit gcc dynamic dependencies>" \
VKD3D_PE_CFLAGS="-I$HOME/wine-dirs/vulkan-sdk/x86_64/include -I$HOME/wine-dirs/vkd3d64-prefix/include/vkd3d" \
VKD3D_PE_LIBS="-L$HOME/wine-dirs/vkd3d64-prefix/lib -lvkd3d -lvkd3d-shader"
```
- We use `--with-system-dllpath` so that wine knows to search our vkd3d
prefix for the vkd3d DLLs. If you did not use `-static-libgcc` to
compile vkd3d, you should also add the libgcc path here. Depending on
distribution it may be `/usr/x86_64-w64-mingw32/bin/` (Arch),
`/usr/x86_64-w64-mingw32/sys-root/mingw/bin/` (Fedora), or
`/usr/lib/gcc/x86_64-w64-mingw32/##-win32/`, where `##` depends on the
gcc version (Debian).
- Notice that multiple paths should be separated with a colon.
- We set `VKD3D_PE_CFLAGS` and `VKD3D_PE_LIBS` to indicate that we will
use a custom version of vkd3d. We use `VKD3D_PE_CFLAGS` to include the
vulkan headers and the vkd3d headers and `VKD3D_PE_LIBS` to load
vkd3d's dynamic libraries.
- Alternatively, you can install MinGW pkg-config, and pass
`PKG_CONFIG_PATH="$HOME/wine-dirs/vkd3d64-prefix/lib/pkgconfig"`.
If you get the following message around the last lines:
```
configure: libvkd3d 64-bit MinGW development files not found; using bundled version.
```
Wine was **not** correctly linked to your custom version of vkd3d. Check
the `config.log`.
Clean ntdll to make sure that the new system DLL path is picked up, and
then rebuild wine:
``` sh
$ make dlls/ntdll/clean
$ make
```
Append "-j\$(nproc)" to make commands to parallelize.
## Build a 32-bit vkd3d installation
``` sh
$ cd $HOME/wine-dirs
$ mkdir vkd3d32
```
``` sh
$ cd vkd3d32
$ ../vkd3d-git/configure \
--host=i686-w64-mingw32 \
--prefix="$HOME/wine-dirs/vkd3d32-prefix" \
WIDL="$HOME/wine-dirs/wine64p/tools/widl/widl" \
SONAME_LIBVULKAN="vulkan-1.dll" \
CPPFLAGS="-I$HOME/wine-dirs/vulkan-sdk/x86_64/include" \
LDFLAGS="-static-libgcc"
```
- We now use `--host=i686-w64-mingw32` to indicate that we will use the
32-bit MinGW compiler.
- We are changing the prefix so that this 32-bit vkd3d is installed in
the `vkd3d32-prefix` folder instead of `vkd3d64-prefix`.
- We're using 64-bit WIDL like before; this is fine.
- We can also still use the Vulkan headers from our 64-bit vulkan-sdk.
We then run:
``` sh
$ make
$ make install
```
## Build 32-bit Wine
We can now build our 32-bit Wine, linking it to our 32-bit vkd3d.
``` sh
$ cd $HOME/wine-dirs
$ mkdir wine32
```
``` sh
$ cd wine32
$ ../wine-git/configure --with-wine64=../wine64/ \
CC='ccache gcc' i386_CC='ccache i686-w64-mingw32-gcc' \
--with-system-dllpath="$HOME/wine-dirs/vkd3d32-prefix/bin:<mingw 32-bit dynamic dependencies>" \
VKD3D_PE_CFLAGS="-I$HOME/wine-dirs/vulkan-sdk/x86_64/include -I$HOME/wine-dirs/vkd3d32-prefix/include/vkd3d" \
VKD3D_PE_LIBS="-L$HOME/wine-dirs/vkd3d32-prefix/lib -lvkd3d -lvkd3d-shader"
```
- We now point `--with-system-dllpath` and `VKD3D_PE_LIBS` to the
directories inside `vkd3d32-prefix`.
As above, clean ntdll to make sure that the new system DLL path is
picked up, and then rebuild wine:
``` sh
$ make dlls/ntdll/clean
$ make
```
# Updating your build
If you want to update either wine or vkd3d's source code, we can execute
the following commands in order. `ccache` should help reducing the
compilations times.
``` sh
# Recompile 64-bit vkd3d
cd $HOME/wine-dirs/vkd3d64
make
make install
# Recompile 64-bit wine
cd $HOME/wine-dirs/wine64
make
# Recompile 32-bit vkd3d
cd $HOME/wine-dirs/vkd3d32
make
make install
# Recompile 32-bit wine
cd $HOME/wine-dirs/wine32
make
```