On my machine I have two versions of visual studio installed: VS2019 and VS2022. They differ in the compilers and also in the libraries they link to. Now I want to compile the wasmer (Webassembly Virtual machine) c-api into a library that can be consumed by a C++ project. The thing is that I need to specifically control which version of the VS library versions the resulting wasmer.lib is being linked against. So I was looking how the toolchain of rustup can be modified. I also tried to modify the path but I do not have any executables of Visual studio in my path.
How can I specify the visual studio version that is used by cargo?
Dangerous half-knowledge here, but I used to cross compile to windows a while back. I remember that you can set the linker in cargo in the
[target] table. Maybe for you, this would look something like:
linker = "path/to/your/link.exe"
Thanks jofas, as far as I understand this the new path to the link executable should also use a different version of the c runtime? If this is the case then this could work. I have assumed to set the toolset somewhere.
When using your key in the projects cargo.toml file I get this
warning: C:\USRTMP\dev\OpenSource\01_Scripting\wasmer\lib\c-api\Cargo.toml: unused manifest key: target.x86_64-pc-windows-msvc.linker
And after testing I got the same linker errors in my C++ project
Sounds like I used the wrong toolchain triple as an example. You can run
rustup toolchain list to get the toolchain you are using. My output currently looks like this:
so if I wanted to change to a different linker than
cc (i.e. use
clang instead of
gcc), I'd write the following inside my
linker = "/usr/bin/clang"
I assumed you'd have two
linker.exe executables on your computer, one for VS2019 and one for VS2022. Your problem is that your toolchain uses the wrong linker per default. I think if you change the
target.<your-toolchain>.linker field in your
, you should be able to link to the right ABI.
EDIT: So sorry, wanted to try it out on my own machine and realized that I don't have to change my
Cargo.toml file, but my cargo configuration file. In my case, I added the above code snippet to my
$HOME/.cargo/config.toml file and it did the trick
Now I think the config key in config.toml works, but still when I open the resulting lib file and search for e.g. winrt, I get this
-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.22000.0\\cppwinrt, other dependencies are similar
So the Windows SDK version is 10.0.22000.0, but what I need is 10.0.18362.0. The expected platform toolset should be v142
How can I achieve this?
Hmm, sorry that my suggestion didn't help. I hoped that explicitly setting the linker to the one shipped as part of the VS environment you need would solve the problem. I guess there are system variables involved which have an impact on the linker and how it chooses which ABIs to link to. Here is a link to the MSVC linker reference, maybe you can find the right options to link to the ABI you need? I don't know enough about linkers in general and msvc in particular to be of any help.
Having two versions of the same toolchain installed is a complete hassle in my experience. Tried that once with two minor versions of Python3 without setting a virtual environment and it completely backfired on me . Have you considered building your application in a Docker container? According to the documentation, you can install VS build tools inside a Windows Docker container.
I totally agree that two toolchains are a mess. I would stop it if this would be possible, but I need them for two different projects.
I tried to first execute the batch "developer prompt 2019" and hoped that the relevant environment options are picked up by cargo, but it didn't.
Also setting the linker dir to the specific sdk version did not help
rustflags = [ "-Clink-args=-LibDir=C:/Program Files (x86)/Windows Kits/10/Lib/10.0.18362.0/ucrt/x64"]
If I understand the problem correctly, you shouldn't have any executables like
cl.exe on your PATH; nor should you try to pass absolute paths to VS executables to rust. Instead you should use
vcvarsall.bat to load the appropriate environment into your current shell, then build your rust project as normal (you may still need set e.g.
linker = "link.exe").
vcvarsall.bat accepts arguments both for a version of Windows SDK and for a version of the toolset.
@yuriy0 you are correct. My process now is that I first start the Developer Command Prompt for Visual Studio 2019. When I then check the path of link.exe it is correctly located in
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\bin\Hostx86\x86\link.exe
For a long time I thought that the presence of the string
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.22000.0\\ucrt"
means, that this version is required as a dependency is not correct since I do not have this path on my system.
When I use the resulting lib in a windows c++ program, I can correctly execute it. But for my use case I want to replace the kernel32.lib by a replacement that is provided by my realtime operating system supplier (Intervalzero RTX). Therefore, the symbols required by wasmer.lib should exactly match the provided symbols of this replacement kernel32.lib. This is not the case, since I get these linker errors:
Error LNK2001 unresolved external symbol __imp_ReleaseSRWLockExclusive WasmerTest C:\Users\schoetbi\source\repos\WasmerTest\WasmerTest\wasmer.lib(dynasmrt-a7e4b265862ce86a.dynasmrt.83b58e04-cgu.14.rcgu.o) 1
.. many more
Error LNK2001 unresolved external symbol GetFileInformationByHandle WasmerTest C:\Users\schoetbi\source\repos\WasmerTest\WasmerTest\wasmer.lib(same_file-45198a06d190a74d.same_file.397d7d37-cgu.6.rcgu.o) 1
So as I understand this, the problem is not what link.exe is used but what version of the kernel32.lib is used in the linker step.
I checked where kernrel32.libs are located on my system:
C:\Program Files (x86)\Windows Kits>rg --files | rg -i kernel32.lib
Then I renamed
10.0.19041.0_ in both the lib and the include folder and made
to regenerate wasmer.lib. But still the symbol requirements and the linker errors stayed the same.
I'm afraid this is where my knowledge ends - I've never found myself hacking on the windows kernel. My suggestion would be to contact your supplier, surely they have a process for building applications for their runtime.
You might also look at the implementation of vcvarsall.bat and see how it handles setting up the environment for the windows SDK, then try to replicate that logic with the paths to your own libs.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.