MSVC compatible compiling and testing on Linux - cheatsheet

Introduction

TalTech offers some courses on C++, one of which is ICS0017 (at the time of writing). This course features coursework projects which require the use of a custom made DLL, compiled with the Microsoft Visual C++ toolchain. Linux does not support DLLs and MSVC compiled C++ code is largely incompatible with such code compiled with GCC, which is common on Linux. This page describes steps to be able to compile C++ code using this DLL on Linux and running it through wine. In doing so some details on the setup on Windows are also presented.

While the advise here is specific to that course, it can probably be adapted for other projects.

Setup on Windows

We start by setting up the project as described in the Course instructions on Windows, including installing Visual Studio. Make sure to install the tools for Desktop C++ development from the Visual Studio Installer.

Any basic C++ Console application template should be fine.

Next to the the toggle for Release and Debug builds the architecture can be selected, choose 32 bit / x86, as this is what the DLL targets.

Lastly you'll want to add some text output to the main function, such as std::cout << "output" << std::endl; . This will allow you to test whether your setup is working.

If you want to stay on Windows for the coding, you should be good to go.

Setup on Linux

Firstly, make sure that you have completed the previous section, this is required, both for the tools and libraries that will be needed and so you know that you have functional code to test with.

Additionally, make sure that your Linux machine has installed:

This page features instructions for cross compiling some large project, the General setup has a list of directories that should be present on your Windows machine and should be made available to your Linux machine. Set up a vc directory as instructed there. You might have to look in Program Files instead of Program Files (x86) to find the directories asked for. We are particularly interested in vc/include/, vc/sdk/include/ucrt/, vc/lib/x86/, vc/lib/ucrt/x86/ and vc/sdk/lib/um/x86.

Also make sure you have a nice directory with the files specific to the project, in this case the header files provided, the cpp code file, the DLL release build (debug would probably work too but the linker seems to want to link it to debug versions of other DLLs, meaning more work for you.) and any files the DLL wants to have.

Building and linking

In order to build this you can use a command similar to this one:
clang-cl -imsvc /path/to/vc/include -imsvc /path/to/vc/sdk/include/ucrt -fuse-ld=lld -EHa -m32 Coursework1.cpp ICS0017DataSource.lib -link -libpath:/path/to/vc/lib/x86 -libpath:/path/to/vc/sdk/lib/um/x86 -libpath:/path/to/vc/sdk/lib/ucrt/x86

-imsvc points the linker to the places where include files live.
-fuse-ld=lld makes clang invoke the lld linker instead of looking for linker.exe.
-EHa enables exception handling in this case all of it (a).
-m32 specifies that we want a 32 bit build.
-link passes all the following input to the linker.
-libpath: specifies places where already built code to link against resides.

The command will likely complain about some files not being found which you know are within the directories specified. This is due to Windows being case-insensitive and some of the filenames containing upper case letters. You can just create sensibly named (all lowercase) links the badly named files.

Now you should have a .exe file that can be executed with wine. If you want to get rid of the detailed output by wine you can use the WINEDEBUG variable: WINEDEBUG=-all wine Coursework1.exe.

KDevelop

If you want to integrate this into KDevelop the following bits might prove useful. First, direct KDevelop to open a project and point it to the directory with your code. Make sure "Custom Build System" is selected.

Once the project itself is imported you can navigate to "Custom Build System" in the project configuration. There specify clang-cl as the executable and the rest of the command as arguments. This should be enough to build your code using the fancy build button. In order to get the execute button to work as well create a new launch configuration for scripts (odd, but it works). Specify wine as the interpreter and your exe as the script file. If you want to silence the debug output you can create a new environment and specify the WINEDEBUG variable there.

Further reading

Disclaimer

I do not guarantee these instructions to be safe, best-practice or even working at all or the information given to be true. I just tried to backtrack the steps I took to get to a working setup.

Other versions of this page

Index

Contact

If you find something that doesn't work, have an idea on how to improve this cheatsheet, or just need further help (although I am not an expert), feel free to let me know:
e-mail: ah@qvxb.de
Matrix: @gaboversta:matrix2.andressing.eu
If you are in the TalTech bachelor programme Cyber Security Engineering you can probably find me on Discord as well.

Licensing

This work is published under the CC0 1.0 license:
CC0
To the extent possible under law, Andreas Hurka has waived all copyright and related or neighboring rights to MSVC compatible compiling and testing on Linux - cheatsheet. This work is published from: Estonia.