I write a lot of hobby projects in C++. I work on Linux, but most of the end users of my tools waill be Windows users, so this necessitates setting up methods for producing windows binaries on Linux.
There are tools I've used for this before, including mingw-w64 and MXE. These work, but they have downsides:
- They aren't binary compatible with MSVC's runtime libraries, so you're forced to bundle a separate runtime somehow.
- With mingw-w64, you can get stuck in dependency hell as you're usually on the hook for building your dependencies manually.
- MXE can help with the dependency issue, but it doesn't have scripts for everything. And you're still stuck waiting for your dependencies to build.
Recently I've found a solution that works much better for my needs: Using Conan to install MSVC-compiled dependencies and link against them and the MSVC toolchain with a CMake toolchain.
This setup works for my needs, which is mainly producing binaries for release.
It probably doesn't cover a lot of other use cases, and I can't promise to help figure those out. Caveat emptor.
This also assumes you have dependencies with pre-built MSVC binaries available from a Conan remote somewhere.
If you haven't already, you'll need to install CMake and Conan.
- CMake should be available in your system's package manager.
- Conan can be installed via pip.
Next, you'll need to setup the MSVC toolchain.
The best way I've found is provided as part of msvc-wine.
- Follow only the first two steps of installation instructions in the repo. i.e. just these:
- Run
./vsdownload.py --dest ${path_where_you_want_msvc}
. - Run
./install.sh ${path_where_you_want_msvc}
.
- Run
Make note of the VC version and the Windows SDK version that was installed.
- The VC version will be the name of a folder in
${path_where_you_installed_msvc}/VC/Tools/MSVC/
. - The Windows SDK version will be the name of a folder in
${path_where_you_installed_msvc}/Windows Kits/10/Include/
.
Now your MSVC toolchian is ready to use.
You'll need a CMake toolchain to enable linking against your VC toolchain.
LLVM provides just such a toolchain file.
- I also use the ClangClCMakeCompileRules file, but it should only be required on Mac based on the comments.
- I opted to set the required parameters in my copy of the toolchian,
which may or may not fit with your workflow:
set(HOST_ARCH "x86_64") set(LLVM_WINSYSROOT "${path_where_you_installed_msvc}") set(MSVC_VER "${VC_version_from_msvc_wine}") set(WINSDK_VER "${windows_SDK_version_from_msvc_wine}") set(LLVM_NATIVE_TOOLCHAIN "/usr")
I'm assuming your have a ConanFile which uses CMakeToolchain and CMakeDeps, similar to:
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake, cmake_layout
class YourConanPackage(ConanFile):
...
requires = {your requirements}
def layout(self):
cmake_layout(self)
def generate(self):
cmake = CMakeDeps(self)
cmake.generate()
tc = CMakeToolchain(self)
tc.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
cmake = CMake(self)
cmake.install()
In order to get Conan to download MSVC compiled dependencies, we need a profile similar to this:
[settings]
os=Windows
arch=x86_64
compiler=msvc
build_type=Release
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.version=192
compiler.cppstd=17
You might need to set compiler.runtime to something else.
You can change compiler.cppstd to something else, but a value is required.
You'll also need to add the following CMake settings. I use the [conf] section of my profile, but it could probably also go in your Conanfile.
tools.cmake.cmaketoolchain:user_toolchain=\["/path/to/your/WinMsvc.cmake"\]
- This will import our toolchain alongside Conan's generated toolchain.
tools.cmake.cmaketoolchain:generator="Unix Makefiles"
- Ninja or other generators probably work. The important part is to change it from the default Visual Studio generator, which would otherwise cause Conan to add some variables that causes CMake to fail.
tools.microsoft.msbuild:installation_path=
- This disables Conan from trying to check for an MSVC toolchain.
At this point, you can run:
conan install -pr:h ${your-MSVC-profile} ${your_project_folder}
And all your dependencies should get downloaded and can be linked against
using find_package in CMake.
Now you can run CMake and the remaining steps to build, i.e:
cd build
cmake ../ -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ...(ther cmake options)...
make
Be sure to specify -DCMAKE_BUILD_TYPE=Release
, otherwise your program will
link against the debug MSVC libraries rather than the release versions.
Assuming everything finished and you didn't find any MSVC incompatibles in your code to fix, you should now a have binary of your program which can be run in Windows (or Wine) with only some version of the MSVC runtime installed.