Windows Subsystems

On Windows, you can run different subsystems that enhance the operating system with UNIX capabilities.

Conan supports MSYS2, CYGWIN, WSL and in general any subsystem that is able to run a bash shell.

Many libraries use these subsystems in order to use the Unix tools like the Autoconf suite that generates Makefiles.

The difference between MSYS2 and CYGWIN is that MSYS2 is oriented to the development of native Windows packages, while CYGWIN tries to provide a complete POSIX-like system to run any Unix application on it.

For that reason, we recommend the use of MSYS2 as a subsystem to be used with Conan.

Operation Modes

The MSYS2 and CYGWIN can be used with different operation modes:

  • You can use them together with MinGW to build Windows-native software.

  • You can use them together with any other compiler to build Windows-native software, even with Visual Studio.

  • You can use them with MinGW to build specific software for the subsystem, with a dependency to a runtime DLL (msys-2.0.dll and cygwin1.dll)

If you are building specific software for the subsystem, you have to specify a value for the setting os.subsystem, if you are only using the subsystem for taking benefit of the UNIX tools but generating native Windows software, you shouldn’t specify it.

Running commands inside the subsystem

self.run()

In a Conan recipe, you can use the self.run method specifying the parameter win_bash=True that will call automatically to the tool tools.run_in_windows_bash.

It will use the bash in the path or the bash specified for the environment variable CONAN_BASH_PATH to run the specified command.

Conan will automatically escape the command to match the detected subsystem. If you also specify the msys_mingw parameter to False, and the subsystem is MSYS2 it will run in Windows-native mode, the compiler won’t link against the msys-2.0.dll.

AutoToolsBuildEnvironment

In the constructor of the build helper, you have the win_bash parameter. Set it to True to run the configure and make commands inside a bash.

Controlling the build environment

Building software in a Windows subsystem for a different compiler than MinGW can sometimes be painful. The reason is how the subsystem finds your compiler/tools in your system.

For example, the icu library requires Visual Studio to be built in Windows, but also a subsystem able to build the Makefile. A very common problem and example of the pain is the link.exe program. In the Visual Studio suite, link.exe is the linker, but in the MSYS2 environment the link.exe is a tool to manage symbolic links.

Conan is able to prioritize the tools when you use build_requires, and put the tools in the PATH in the right order.

There are some packages you can use as build_requires:

  • From Conan-center:

    • mingw_installer/1.0@conan/stable: MinGW compiler installer as a Conan package.

    • msys2/20190524@: MSYS2 subsystem as a Conan package (Conan Center Index).

    • cygwin_installer/2.9.0@bincrafters/stable: Cygwin subsystem as a Conan package.

For example, create a profile and name it msys2_mingw with the following contents:

[build_requires]
mingw_installer/1.0@conan/stable
msys2/20190524

[settings]
os_build=Windows
os=Windows
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=4.9
compiler.exception=seh
compiler.libcxx=libstdc++11
compiler.threads=posix
build_type=Release

Then you can have a conanfile.py that can use self.run() with win_bash=True to run any command in a bash terminal or use the AutoToolsBuildEnvironment to invoke configure/make in the subsystem:

from conans import ConanFile
import os


class MyToolchainXXXConan(ConanFile):
    name = "mylib"
    version = "0.1"
    ...

    def build(self):
        self.run("some_command", win_bash=True)

        env_build = AutoToolsBuildEnvironment(self, win_bash=True)
        env_build.configure()
        env_build.make()

     ...

Apply the profile in your recipe to create a package using the MSYS2 and MINGW:

$ conan create . user/testing --profile msys2_mingw

As we included in the profile the MinGW and then the MSYS2 build_require, when we run a command, the PATH will contain first the MinGW tools and finally the MSYS2.

What could we do with the Visual Studio issue with link.exe? You can pass an additional parameter to run_in_windows_bash with a dictionary of environment variables to have more priority than the others:

def build(self):
    # ...
    vs_path = tools.vcvars_dict(self.settings)["PATH"] # Extract the path from the vcvars_dict tool
    tools.run_in_windows_bash(self, command, env={"PATH": vs_path})

So you will get first the link.exe from the Visual Studio.

Also, Conan has a tool tools.remove_from_path that you can use in a recipe to temporarily remove a tool from the path if you know that it can interfere with your build script:

class MyToolchainXXXConan(ConanFile):
    name = "mylib"
    version = "0.1"
    ...

    def build(self):
        with tools.remove_from_path("link"):
            # Call something
            self.run("some_command", win_bash=True)

     ...