diff --git a/doc/BUILD-win32.md b/doc/BUILD-win32.md new file mode 100644 index 0000000000..b78f5fc230 --- /dev/null +++ b/doc/BUILD-win32.md @@ -0,0 +1,347 @@ +# Compile VLC for Windows + +There are multiple ways to compile VLC for Windows. All of them involve `gcc` or `llvm` with `mingw-w64`. +Compilation with MSVC or clang-cl is currently not supported. + +# UNIX Shell + +You will also need a UNIX shell to run the build process. On Windows you can either +use [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) (recommended) or [msys2](https://www.msys2.org/). +You may also build inside a Docker on [Linux](https://docs.docker.com/desktop/install/linux-install/) +or on [Windows](https://docs.docker.com/desktop/install/windows-install/). + +The choice of which is best depends on your goals. In terms of build times, Docker is the fastest +then WSL and msys2 is the slowest. + +Unless you use a Docker image, you will need to install multiple development packages that VLC +needs to build itself and its contribs. + +* On Ubuntu/Debian (or WSL), they are the same tools installed in our [Docker Images](https://code.videolan.org/videolan/docker-images/-/blob/master/vlc-debian-win64/Dockerfile#L27): +``` +sudo apt-get update -qq +sudo apt-get install -qqy \ + git wget bzip2 file libwine-dev unzip libtool libtool-bin libltdl-dev pkg-config ant \ + build-essential automake texinfo ragel yasm p7zip-full autopoint \ + gettext cmake zip wine nsis g++-mingw-w64-i686 curl gperf flex bison \ + libcurl4-gnutls-dev python3 python3-setuptools python3-mako python3-requests \ + gcc make procps ca-certificates \ + openjdk-11-jdk-headless nasm jq gnupg \ + meson autoconf +``` + +* On msys2 you should install similar packages: +``` +pacman -Syu +pacman -S --needed git wget bzip2 file unzip libtool pkg-config \ + automake autoconf texinfo yasm p7zip \ + gettext cmake zip curl gperf flex bison \ + python3 python3-setuptools python3-mako \ + gcc make ca-certificates nasm gnupg patch help2man \ + ragel python3 meson +``` + + +# Toolchains + +There are 2 toolchains supported to build VLC for Windows: +* mingw-w64 with gcc +* mingw-w64 with llvm + +The `gcc` is the most common one as it comes as packages in Linux distributions and msys2. +The problem with the gcc toolchain is that if you need to debug your build with `gdb`. +It is very slow when you use breakpoints because for each of the 200+ DLLs loaded +during the VLC launch, it looks for your breakpoints. + +The 'llvm' toolchain solves this issue by producing .pdb files. You then debug your +code with the Windows Debugger, even within Visual Studio. + +## Install mingw-w64 LLVM + +The 'llvm' toolchain is normally not found in Linux or msys2. You will need to install it yourself. +You can download prebuilt packages from https://github.com/mstorsjo/llvm-mingw. And then add the +place where you decompressed it, followed by `/bin`, in your `PATH`. + +You also have a choice between `ucrt` and `msvcrt`. `ucrt` is the one you should use if you don't care about +support on Windows versions older than Windows 10. If you need to support older Windows versions you +should go with the `msvcrt` version. The official VLC builds use `msvcrt` for desktop builds, and +`ucrt` for Universal Windows Platform (UWP) builds. + +* On Linux: +```sh +wget https://github.com/mstorsjo/llvm-mingw/releases/download/20220906/llvm-mingw-20220906-msvcrt-ubuntu-18.04-x86_64.tar.xz +tar xvf llvm-mingw-20220906-msvcrt-ubuntu-18.04-x86_64.tar.xz -C /opt +export PATH=/opt/llvm-mingw-20220906-msvcrt-ubuntu-18.04-x86_64/bin:$PATH +``` + +* On msys2, **use the mingw64 (blue) environment** (ie not msys (purple) the or mingw32 (grey) environments): +```sh +wget https://github.com/mstorsjo/llvm-mingw/releases/download/20220906/llvm-mingw-20220906-msvcrt-x86_64.zip +unzip llvm-mingw-20220906-msvcrt-x86_64.zip -d /opt +export PATH=/opt/llvm-mingw-20220906-msvcrt-x86_64/bin:$PATH +``` + +Every time you build VLC, you will need to have the toolchain in your PATH. +A convenient way to setup your environment is to set command in a file and call +it when you start your build sesson: + +Create toolchain.sh: +```sh +cat export PATH=/opt/llvm-mingw-20220906-msvcrt-x86_64/bin:$PATH > toolchain.sh +``` + +Use toolchain.sh to set the path to your compiler: +```sh +source toolchain.sh +``` + +* On Docker, you can use these 2 images: + + * msvcrt: `registry.videolan.org/vlc-debian-llvm-msvcrt:20221011232542` + * ucrt: `registry.videolan.org/vlc-debian-llvm-ucrt:20221012005047` + +You can find the latest Docker images we use in [extras/ci/gitlab-ci.yml](/extras/ci/gitlab-ci.yml) + +## Install mingw-w64 gcc + +This is the default build environment of VLC when cross-compiling. This is also +the environment used to produce the official builds that everyone uses. The mingw-w64 +toolchain is usually found in all Linux distributions and in msys2. +You can install it this way: + +* On Linux: +```sh +sudo apt-get install -qqy \ + gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 mingw-w64-tools +``` + +* On msys2: +```sh +pacman -S mingw-w64-x86_64-toolchain +> :: Repository mingw64 + 1) mingw-w64-x86_64-binutils 2) mingw-w64-x86_64-crt-git 3) mingw-w64-x86_64-gcc 4) mingw-w64-x86_64-gcc-ada 5) mingw-w64-x86_64-gcc-fortran 6) mingw-w64-x86_64-gcc-libgfortran 7) mingw-w64-x86_64-gcc-libs 8) mingw-w64-x86_64-gcc-objc + 9) mingw-w64-x86_64-gdb 10) mingw-w64-x86_64-gdb-multiarch 11) mingw-w64-x86_64-headers-git 12) mingw-w64-x86_64-libgccjit 13) mingw-w64-x86_64-libmangle-git 14) mingw-w64-x86_64-libwinpthread-git 15) mingw-w64-x86_64-make 16) mingw-w64-x86_64-pkgconf + 17) mingw-w64-x86_64-tools-git 18) mingw-w64-x86_64-winpthreads-git 19) mingw-w64-x86_64-winstorecompat-git +> Enter a selection (default=all): + +Type enter to select "all" +``` + + +* On Docker, you can use the `registry.videolan.org/vlc-debian-win64:20221011230137` image. + +You can find the latest Docker images we use in [extras/ci/gitlab-ci.yml](/extras/ci/gitlab-ci.yml) + + +# Getting VLC + +This is the easy part. In your UNIX Shell type: + +```sh +git config --global core.autocrlf false +git clone https://code.videolan.org/videolan/vlc.git +``` + +This will download the VLC source code into the `vlc` folder, in your current directory. + +# Building VLC + +Fully build in a separate folder `build`: + +```sh +mkdir build +cd build +../vlc/extras/package/win32/build.sh -a x86_64 +``` + +This will build +* VLC "extra tools" in case you are missing some in your environment. +* VLC "contribs", a hundred different libraries that VLC uses like FFmpeg, Qt, etc. +* VLC "core" (libvlccore.dll) the heart of VLC. +* VLC "modules" which contains all the possible extensions to add functionality to VLC. +* libvlc.dll a DLL to use VLC from external code with a stable API. + +## Prebuilt contribs + +You may not want to spend one or two hours building all the contribs if you're never going to +want to touch any of them. In that case you may want to reuse prebuilt binaries and save some time. +To build with prebuilt contribs you need to have a **matching compiler** and especially +a **matching C++ compiler**. So the ones available may not match your environment. In that case you +still need to build the contribs yourself. + +The choice of compiler may depend on how you plan to debug your code. See the [Debugging +section](#debugging) below for more information. + +## Building with gcc (11) prebuilt contribs + +If your mingw-w64 compiler/toolchain is gcc 11 you can use these commands to build VLC +and reuse prebuilt contribs: + +```sh +mkdir build +cd build +export VLC_CONTRIB_SHA="$(cd ../vlc; extras/ci/get-contrib-sha.sh)" +export VLC_PREBUILT_CONTRIBS_URL="https://artifacts.videolan.org/vlc/win64/vlc-contrib-x86_64-w64-mingw32-${VLC_CONTRIB_SHA}.tar.bz2" +../vlc/extras/package/win32/build.sh -a x86_64 -p +``` + +## Building with LLVM (13) prebuilt contribs + +If your mingw-w64 compiler/toolchain is LLVM 13 you can use these commands to build VLC +and reuse prebuilt contribs. The name of the prebuilt tarball is the same, but the folder is different: + +```sh +mkdir build +cd build +export VLC_CONTRIB_SHA="$(cd ../vlc; extras/ci/get-contrib-sha.sh)" +export VLC_PREBUILT_CONTRIBS_URL="https://artifacts.videolan.org/vlc/win64-llvm/vlc-contrib-x86_64-w64-mingw32-$VLC_CONTRIB_SHA.tar.bz2" +time ../vlc/extras/package/win32/build.sh -a x86_64 -p +``` + +## libvlc + +You may be interested in just building libvlc without the desktop app. In that case +you can add `-z` to you build.sh call. It will save you some building time, especially +if you build contribs. And it will also avoid creating the Qt gui plugins you will never use. + +```sh +mkdir build +cd build +../vlc/extras/package/win32/build.sh -a x86_64 -z +``` + +# Other options + +## CPU Control + +You may want to reduce the load on your CPU, and thus your memory, when building. +You can control the number of maximum threads used during compilation with the `JOBS` +environment variable. + +Due to a missing feature in ninja, contribs built from Meson will use all your CPU's +regardless of the `JOBS` value. You can reduce the problem by allocating a single +CPU thread to each Meson contrib with the `MESON_BUILD` environment variable. + +Here is an example limit the build to 8 threads and 1 per Meson/ninja contrib. + +```sh +JOBS=8 MESON_BUILD="-j 1" ../vlc/extras/package/win32/build.sh -a x86_64 +``` + +## Config Flags + +When building VLC manually, it's possible to enable/disable certain features of +VLC or select/unselect some compilation configurations. +You can find the list of options when running : + +```sh +../vlc/configure -h +``` + +You can pass all these options to `build.sh` using the `CONFIGFLAGS` environment +variable. +For example you can enable the address sanitizer with: + +```sh +CONFIGFLAGS="--with-sanitizer=address" ../vlc/extras/package/win32/build.sh -a x86_64 +``` + +## Contrib Flags + +When building VLC manually, it's possible to select/unselect certain contribs or +enable/disable some features. +You can find the list of options when running: + +```sh +../vlc/contribs/bootstrap -h +``` + +You can pass all these options to `build.sh` using the `CONTRIBFLAGS` environment +variable. +For example you can disable bluray building with: + +```sh +CONTRIBFLAGS="--disable-bluray" ../vlc/extras/package/win32/build.sh -a x86_64 +``` + +# Debugging + +Most of the time, if you need to build VLC yourself, you will also need to debug it. +The way to debug VLC on Windows depends on the toolchain you are using. When building +with gcc you need to use `gdb`. When building with LLVM, you can use `gdb` or +the `Windows Debugger`. + +The latter is much faster than gdb which is very slow to pick breakpoints in the +hundred of VLC DLL's. + +## Debugging with Windows Debugger + +By default VLC is built with debug symbols. But if you want to use the **`Windows Debugger` +with LLVM**, you need to build with `.pdb` files. You can do that by adding `-d` to +the `build.sh` call. + +```sh +../vlc/extras/package/win32/build.sh -a x86_64 -d +``` + +This will create PDB files, but since we are building in a UNIX environment, the +paths written in the PDB are UNIX files. The debugger will fail to find the proper +source files when you are debugging. There are different ways to fix this. Both +involve mapping the UNIX paths to paths in your Windows machine. That also means +if you want to debug properly the code you are editing, it needs to be visible +in Windows. It's always the case in msys2. It can be the case with WSL also it's +faster in a WSL1 environment than in WSL2. In Docker it's also possible by +mapping a Windows folder to make it accessible in your Docker. In the end your +VLC source code **should be on a partition/drive that Windows can see**, +and thus the Windows Debugger. + +You can set the UNIX to Windows mapping when enabling PDB's in `build.sh`. You need +to set the Windows path where the VLC sources are this way: + +```sh +../vlc/extras/package/win32/build.sh -a x86_64 -D "c:/path/to/sources/vlc" +``` + +You can also set it in your environment `CFLAGS` and `CXXFLAGS` which you can also add +in your `toolchain.sh` described [above](#install-mingw-w64-llvm): + +```sh +CFLAGS="-fdebug-prefix-map='/mnt/c/'='c:/'" CXXFLAGS="-fdebug-prefix-map='/mnt/c/'='c:/'" ../vlc/extras/package/win32/build.sh -a x86_64 -d +``` + +## VLC desktop debug + +The VLC you download has all plugins structured in different folders, all in a `"plugins"` folder. +But when you build VLC this is not the case. VLC cannot be used that way. It needs to be +either *installed* with the following command: + +```sh +cd win64; make package-win-common +``` + +You will end up with a `vlc-4.0.0-dev` folder with the vlc EXE's and DLL's in the +proper place. You can debug from there. But this way of building is much slower than +just building the files that have been modified. + +A faster way to debug is to just build with `build.sh` or even just calling make +in the `win64` folder. In that case you need to setup your debugging environment to +pick `libvlccore.dll`, `libvlc.dll` and plugins that you built. `libvlccore.dll` is +found in `win64/src/.libs` and `libvlc.dll` is found in `win64/lib/.libs`. You need to +add these paths to your `PATH`. + +``` +PATH="c:\path\to\sources\vlc\win64\lib\.libs;c:\path\to\sources\vlc\win64\src\.libs;C:\Windows\System32;C:\Windows;C:\Windows\System32\downlevel" +``` + +And when you run vlc.exe, you also need to set the `VLC_PLUGIN_PATH` environment variable +to the folder with all the plugins you built: + +``` +VLC_PLUGIN_PATH=c:\path\to\sources\vlc\win64\modules +``` + +# Future + +In the future it might be possible to build VLC with Meson. With a native Windows toolchain it might +be possible to have proper Windows paths when compiling, which makes it even easier to +develop (click on the file path on compilation error). It will also avoid mapping the +PDB paths of UNIX paths to Windows paths.