+++
title = "Windows"
weight = 50
+++

## Build under Windows

The maintained Windows build is the one used by our GitLab CI. It builds the
Python module, tests it, and creates a wheel.

### Prerequisites

#### Visual Studio

Install **Visual Studio Community Edition** with the x64 C++ toolchain from
[visualstudio.microsoft.com](https://visualstudio.microsoft.com). The current
build instructions are tested with Visual Studio 2022.

#### CMake and Ninja

Install **CMake** (Windows x64 installer) from
[cmake.org/download](https://cmake.org/download) and **Ninja** from
[ninja-build.org](https://ninja-build.org/).

#### Python

Install Python, preferably through `pyenv-win`. See
[Python on Windows](/deploy/py/win).

#### SWIG

Required to regenerate the Python API wrappers under `auto/Wrap/`, which is
needed for any change that touches the C++ API. Download from
[swig.org/download.html](http://www.swig.org/download.html), unpack the ZIP,
and add the folder (e.g. `C:\swigwin-4.0.2`) to `PATH`. See
[swig.org/Doc4.1/windows.html](http://www.swig.org/Doc4.1/windows.html) for
detailed install instructions.

#### Compiler launcher (optional)

`buildcache.exe` or another compiler launcher reduces rebuild times.

#### Libraries

The BornAgain dependencies are installed into two prefixes:
`C:/opt/vcpkg/installed/x64-windows` for standard libraries and `C:/opt/x64`
for the MLZ-maintained ones.

Standard libraries (`fftw3`, `gsl`, `libtiff`, `boost`, `zlib`, `bzip2`) are
installed via [vcpkg](https://github.com/microsoft/vcpkg) into
`C:/opt/vcpkg/installed/x64-windows`, as the CI does. Alternatively, the
prebuilt zips from
[computing.mlz-garching.de/download/WinLibs](https://computing.mlz-garching.de/download/WinLibs)
can be unpacked into `C:/opt/x64/include` and `C:/opt/x64/lib`.

Relevant WinLibs packages are:

- `libfftw3.win64.zip`
- `libtiff.win64.zip`
- `gsl_*_win64_shared.zip`
- `boost_*.7z`

MLZ-specific libraries must be installed into `C:/opt/x64`:

- **libcerf**: download `cerfcpp-*-win64.zip` from the latest release at
  [jugit.fz-juelich.de/mlz/libcerf](https://jugit.fz-juelich.de/mlz/libcerf/-/releases),
  unpack into `C:/opt/x64`.
- **libformfactor**: download `formfactor-*-win64.zip` from the latest release at
  [jugit.fz-juelich.de/mlz/libformfactor](https://jugit.fz-juelich.de/mlz/libformfactor/-/releases),
  unpack into `C:/opt/x64`.
- **libheinz**: download the source from
  [jugit.fz-juelich.de/mlz/libheinz](https://jugit.fz-juelich.de/mlz/libheinz/-/releases)
  and build:

  ```powershell
  mkdir build
  cd build
  cmake .. -DCMAKE_INSTALL_PREFIX="C:/opt/x64"
  cmake --build . --config Release
  cmake --install . --config Release
  ```

#### Environment paths

Make sure the executable directories for Python, CMake, Ninja, and SWIG are
available in `PATH`. The dependency prefixes are passed to CMake through
`CMAKE_PREFIX_PATH`; their runtime DLL directories must also be visible when
running tests.

For example:

```powershell
$PY_PLATFORM_DIR = "C:/Users/admin/.pyenv/pyenv-win/versions/3.12.0/"
$OPT_DIR = "C:/opt/x64"
$VCPKG_DIR = "C:/opt/vcpkg/installed/x64-windows"
$SWIG_DIR = "C:/swigwin-4.0.2"

$env:PATH = "$PY_PLATFORM_DIR;$SWIG_DIR;$VCPKG_DIR/bin;$OPT_DIR/lib;$env:PATH"
```

If CMake cannot find headers or libraries, check that
`C:/opt/x64/include`, `C:/opt/x64/lib`, and the vcpkg prefix are covered by the
`CMAKE_PREFIX_PATH` used below.

### Configure

Open a PowerShell with the Visual Studio x64 build environment loaded. One way
is to use Visual Studio's *x64 Native Tools* shell. The CI does the equivalent
with `vswhere` and `Enter-VsDevShell`.

Set the local paths:

```powershell
$PY_PLATFORM_DIR = "C:/Users/admin/.pyenv/pyenv-win/versions/3.12.0/"
$OPT_DIR = "C:/opt/x64"
$VCPKG_DIR = "C:/opt/vcpkg/installed/x64-windows"
$BUILD_DIR = "build"
```

Create and enter the build directory:

```powershell
mkdir -Force "$BUILD_DIR"
cd "$BUILD_DIR"
```

Configure with Ninja:

```powershell
cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Release `
  -DCMAKE_PREFIX_PATH="$OPT_DIR;$VCPKG_DIR" `
  -DPython3_ROOT_DIR="$PY_PLATFORM_DIR" `
  -DBA_PY_PACK=ON `
  -DCMAKE_C_COMPILER_LAUNCHER="buildcache.exe" `
  -DCMAKE_CXX_COMPILER_LAUNCHER="buildcache.exe"
```

### Build and test

```powershell
cmake --build . --config Release --parallel 20
cmake --build . --config Release --target ba_wheel
```

Before running tests, make the freshly built Python package and DLLs visible:

```powershell
$env:PYTHONHOME = "$PY_PLATFORM_DIR"
$env:PYTHONPATH = "$BUILD_DIR/py/src/"
$env:PATH = "$PY_PLATFORM_DIR;$VCPKG_DIR/bin;$OPT_DIR/lib;$env:PATH"
```

Then run:

```powershell
ctest -C Release --parallel 20 --output-on-failure
```

The wheel is placed under `build/py/wheel/`.
