Building ITensor using MSYS2 and MinGW-x64 toolchain on Windows

In this guide I explain how to build ITensor library on Windows. Unfortunately, the current version of ITensor (2.1.1) cannot be built by the lastest version of Microsoft Visual Studio C++ compiler (2017), because the compiler is not fully C++11 compliant (namely, its lack of support for Expression SFINAE). We therefore need to use either Cygwin or MinGW compilers on Windows to build ITensor instead. Here I explain how to build ITensor using MinGW-w64 toolchain.

Install Toolchain

MSYS2 provides a convinent environment for the MinGW-w64 toolchain. Go to and download x86_64 version. Follow instructions on the MSYS2 webpage. After the updates, restart MSYS2 MinGW 64-bit and install the MinGW-w64 toolchain, git, msys-make and vim:

$ pacman -S mingw-w64-x86_64-toolchain git make vim

Install OpenBLAS

ITensor uses BLAS and LAPACK routines. OpenBLAS is an open source implementation of the BLAS, bundled with the reference LAPACK implementation from netlib by default. Binary packages of OpenBLAS for Windows can normally be downloaded from However, the binary package for the most recent version v0.2.20 is not available for some reason. Binary package of a previous version v0.2.19 is available. But it uses an older version of gfortran, so I recommend building OpenBLAS yourself.

To clone the OpenBLAS repository:

$ git clone ~/.local/src/OpenBLAS

This creates a directory named OpenBLAS under ~/.local/src. After cloning, you can list all the previous releases by the following commands:

$ cd ~/.local/src/OpenBLAS
$ git tag

Checkout the latest release:

$ git checkout v0.2.20

To build the library, you simply need to make:

$ make -j4

After the compilation, you can install the files to ~/.local/pkg/OpenBLAS-v0.2.20-Win64-int32 (or any directory of your choice) by the following command:

$ make PREFIX=~/.local/pkg/OpenBLAS-v0.2.20-Win64-int32 install

This creates directory ~/.local/pkg/OpenBLAS-v0.2.20-Win64-int32 with subdirectories include, lib, and bin, respectively containing the header files, .a files, and a .dll file.

Install ITensor

Now we are ready to build ITensor. First clone the ITensor repository by

$ git clone ~/.local/src/ITensor

Again, we checkout the most recent release by

$ cd ~/.local/src/ITensor
$ git tag
$ git checkout v2.1.1

ITensor uses for configuration. A sample configuration file is included in the ITensor repository. Copy it to by

$ cp

Edit using vim (or your favorite text editor)

$ vim

Make sure you have the following lines uncommented and correct:

CCCOM=g++ -std=c++11 -Wa,-mbig-obj -O2 -fPIC
	-L$(HOME)/.local/pkg/OpenBLAS-v0.2.20-Win64-int32/lib \
	-lpthread \
	-I$(HOME)/.local/pkg/OpenBLAS-v0.2.20-Win64-int32/include \
       -fpermissive \

The compiler flags -Wa,-mbig-obj -O2 are a workaround for Windows’s limitation on binary files. Because of the -O2 flag, even the debug build will be optimized. This will unfortunately interfere with a debugger if you are using one, making debugging difficult. ITENSOR_MAKE_DYLIB=1 is for building dynamic library files libitensor.dll and libitensor-g.dll. Currently, the sample configuration included in ITensor does not support building of .dll files. Therefore, you need to add the following lines to

DYLIB_FLAGS=-shared \
            -Wl,--export-all-symbols \
            -Wl,--enable-auto-import \

After you’ve changed, you can build ITensor by

$ make -j4

Once the build is finished, you can install the files to ~/.local/pkg/ITensor/ by

$ mkdir -p ~/.local/pkg/ITensor/include
$ mkdir -p ~/.local/pkg/ITensor/lib
$ mkdir -p ~/.local/pkg/ITensor/bin
$ cp -r itensor ~/.local/pkg/ITensor/include/
$ cp -r lib/*.a ~/.local/pkg/ITensor/lib/
$ cp -r lib/*.dll ~/.local/pkg/ITensor/bin/

We’re done.

Example Program

Let me now show you how to use the ITensor library (which you just built) in your application. Let’s say that you have a file with a main function which uses ITensor library.

#include <iostream>
#include <itensor/all.h>

int main(int argc, char** argv)
    using namespace itensor;
    Index i("index i", 2);
    Index j("index j", 2);
    ITensor T(i,j), U(i), S, V;
    svd(T, U, S, V);
    return 0;

To compile, use the following Makefile:


OPENBLAS_ROOT = $(HOME)/.local/pkg/OpenBLAS-v0.2.20-Win64-int32
ITENSOR_ROOT = $(HOME)/.local/pkg/ITensor
LIBS = 	-static-libgcc -static-libstdc++ \
	-Wl,-Bstatic \
		-litensor \
		-lopenblas \
		-lpthread \
		-lgfortran \
	-std=c++11 -O3 -Wall \
	-I$(ITENSOR_ROOT)/include \
	-L$(ITENSOR_ROOT)/lib \
	$(CXX) $< -o $@ $(CXXFLAGS) $(LDFLAGS) $(LIBS)

Typing make will create ex.exe.


Because of the “static” flags, the resulting binary ex.exe has all the dependent libraries (itensor, openblas, pthread, …) statically linked to it. This will increase the size of the binary file and also the build time. To dynamically link the libraries instead, you can remove the flags -static-libgcc, -static-libstdc++, and -Wl,-Bstatic:

LIBS = 	-litensor \
	-lopenblas \
	-lpthread \
	-lgfortran \

The ex.exe built by this new Makefile is smaller than before. When you try to run it, however, it will complain about the missing DLL files:


The simplest way to solve this problem is to copy all the dependent DLL files to the same directory as the executable. The DLL files for ITensor and OpenBLAS can be found in the bin subdirectory of ~/.local/pkg/ITensor and ~/.local/pkg/OpenBLAS-v0.2.20-Win64-int32 (You just installed them there). Other DLL files can be found in /mingw64/bin:

$ cp /mingw64/bin/libgcc_s_seh-1.dll \
     /mingw64/bin/libstdc++-6.dll \
     /mingw64/bin/libgfortran-4.dll \
     /mingw64/bin/libwinpthread-1.dll \
     /mingw64/bin/libquadmath-0.dll \
     ~/.local/pkg/ITensor/bin/libitensor*.dll \
     ~/.local/pkg/OpenBLAS-v0.2.20-Win64-int32/bin/libopenblas.dll \

Now ex.exe runs without complaining.



You might be thinking, “Why isn’t it printing the data? The norms seem correct…” This is because of how static variables defined in header are handled differently in Linux (and Mac OS X) and in Windows; the current version of ITensor is not compatible with how Windows handles it. I won’t go into detail, but this breaks the PrintData macro. Hopefully this will be fixed soon. If you want, you can print individual elements of the tensors and check whether the rest of the code works properly.