-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to include msvcr100.dll in Windows native image #1762
Comments
Steps to reproduce:
Test on clean machine:
|
GraalVM must use /MT compiler flag to static CRT link. But it use /MD flag. |
@webfolderio Thanks for the link! I understand now that a module compiled with MT will have the runtime "inside it", while a module compiled with MD will link with a DLL at the moment of execution. When compiled with MD the DLL must exist on the target machine, which is the problem because MSVCR100.dll is often missing. The comment in the source says:
I found that MD compiled DLLs should not be mixed with MT compiled DLLs. This is probably what the comment is referring to. So, in order to fix this, we need to get MT compiled versions of some JDK native libraries? Does anyone know which JDK native libraries the comment refers to? |
As most of jdk native libraries are provided as static lib and already included in compiled exe, I think we can use /MT mode at most time. But if --enable-all-security-service is enabled and so sunec.dll must be present, /MT maybe cause crash.Maybe you can use some third party crypto libraries instead of jce in this case. |
@bobvandette Would it be possible to use |
The JDK static libraries for Windows are all built with /MD. I would have to experiment with building them with /MT to see if this could work. I would expect your generated native images to increase in size if we did this. |
That makes sense. The msvcr100.dll file is ~810 KB but I suppose other libraries may be pulled in too. It would be good to better understand the trade-offs. For many CLI applications, the ability to distribute apps as a single executable is a big part of the value of native images. It's a pity that we cannot rely on msvcr100.dll always being present. Thank you for spending time on this! |
@bobvandette Have you had a chance to try this? Is it feasible to remove the dependency on an external msvcr100.dll? |
Any chance of getting this in GraalVM 19.3? |
I did look into this and came to the conclusion that this wasn't something we should do since you cannot mix executables and libraries that were built with /MD and /MT. There are use cases where we generate DLL's that are used with the JDK and other cases where .DLL's from the JDK are used to augment a generated native-image. The only way around this would be to build your own JDK and native-image binaries with some minor modifications to the sources. Sorry. |
@bobvandette I am aware that /MD and /MT cannot be mixed, and I understand there are use cases where /MD is unavoidable. What I was hoping was that the |
@shelajev I finally had a chance to try this with GraalVM 19.3 for Java 11. The issue remains with a different error (because
@bobvandette raises a good point that executables and libraries that were built with /MD and /MT cannot be mixed, so this needs to be done with care. However, I expect a similar request will be raised to allow statically linking I propose adding a new option to |
Minor point -- I think the message actually refers to VCRUNTIME140.dll. |
@sogaiu Thank you! I fixed the typo in my previous comment. |
This sounds nice if doable! |
The suggestion of implementing -H:+StaticallyLinkAll sounds useful but has a few challenges associated with its implementation. GraalVM 19.3 switched to using JDK native code instead of the manual substitutions that were used for earlier versions of GraalVM. The JDK native code is delivered in GraalVM in the form of static libraries. These static libraries (zip.a, net.a, java.a, nio.a, etc) are built on Windows using /MD. The reason for this is that it allows the use of other JDK DLLs or third party DLL with native-image generated .exe's. If -H+StaticallyLinkAll were implemented, we would have to provide another set of these static libraries that are compiled using /MT and find a way of prohibiting the use of other DLLs or static libraries that were not properly compiled. The mac/linux example described above is not the same problem since Linux and Mac do not have a problem mixing shared libraries and static libraries in a single executable. The solution to the libstdc++ problem is to optionally add the static version of that library on the link line in order to eliminate the runtime dependency on the shared library. This of course assumes that this static version is available in the toolchain. I don't see this library in my Xcode installation. |
No, sorry. That fix is about avoiding adding export symbols from the JDK static libraries to native-image generated DLLs. |
Is there any plans to solve this issue? It prevents providing an autocontained binary for windows. |
Workaround: Use pefrmdllembed. Syntax: pefrmdllembed -impinj VCRUNTIME140.DLL your-native-image.exe your-native-image-fixed.exe Worked for me. |
@mmellon Awesome, thank you so much! I will include your workaround in the picocli documentation. 👍 |
Caveat for the above workaround: If you embed MSVCR100.DLL or VCRUNTIME140.DLL in your exe rather than create an installer that installs a dependency, you will probably lose the ability of Windows to apply updates for vulnerabilities in the shared runtime that might impact the security of your application. Windows installer has magic to keep you from downgrading the DLL in %System32%, and, once it is installed, I believe Windows Update keeps it up-to-date. |
You don't have to statically link to the CRT to get rid of the "VCruntime140.dll" error. Windows has had "universal CRT" deployed as part of Windows for a decade now. Code should simply link with that dynamically and it will work with anything Windows 10 and later. Prior versions of Windows can install the Universal CRT separately. See https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment |
@kasajian Thank you for pointing that out, I was not aware of that!
Is that something that application authors (using the |
@remkop In my opinion, the Graal code that creates the Windows executable is currently configured to some settings (looks like very old settings) to like the C-Runtime in a certain way that requires additional distribution by the end-user (the person creating the install. It's unnecessary. Today, and for a long time, when you create an EXE on Windows, it will built in such as way that it will link to the version of CRT that ships with Windows, and kept up-to-date by Microsoft. More info from Microsoft: https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment?view=msvc-170 Is this absolutely needed? no. This is a feature request, not a bug. But it would be good if Graal attempted build the Windows image the way Windows images are typically built these days. |
bumping this up - would be super helpful to remove this dependency, if all that is required is to change the link process to rely on UCRT |
For the record, when targeting Windows this issue makes GraalVM Native Image much less attractive compared to a jlink image/jpackage installer. |
@kasajian this sound like a useful feature. Please create a new Feature request with a proper title so that we can close this issue here. Btw, we also accept pull requests ;-) cc @pejovica |
Related to #1407: I'm trying to create an instruction manual for creating native image command line applications using the picocli library.
On Windows 10, the generated native image cannot be executed on a clean machine; it fails with an error like the following:
Note that this problem does not manifest on the machine where the native image was built. The DLL will be present on machines that have the toolchain set up to build the native image (Microsoft Windows SDK for Windows 7 and .NET Framework 4 and the C compilers from KB2519277). The problem only manifests when you try to execute the generated native image on a "clean" Windows 10 machine. (I used a VirtualBox VM with a 64-bit Windows 10 guest OS to reproduce the issue.)
It turns out that msvcr100.dll from VS C++ Redistributable 2010 must be present or the application will fail to start. I would like to include msvcr100.dll in the native image so my application can be distributed as a single executable.
Will this DLL be included automatically in the native image in future releases? If not, is there a way for me ensure it is included?
The text was updated successfully, but these errors were encountered: