Skip to content
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

windows: find out what is needed to run binary on clean system (visual studio c++ 2010 redist?) #276

Closed
borkdude opened this issue Jun 19, 2019 · 30 comments
Labels
help wanted Extra attention is needed windows
Projects

Comments

@borkdude
Copy link
Member

borkdude commented Jun 19, 2019

platform

Windows

problem

clj-kondo.exe starts and quits immediately without showing output

@sogaiu reported this here: #145 (comment)

I think this is because GraalVM requires the Windows 7.1 SDK and/or may require specific versions of .dlls to be present in the system, but I'm not sure.

@borkdude borkdude added the bug Something isn't working label Jun 19, 2019
@borkdude borkdude added the help wanted Extra attention is needed label Jun 19, 2019
@borkdude
Copy link
Member Author

borkdude commented Jun 19, 2019

It seems you have to install the Windows 7.1 SDK first:

https://www.microsoft.com/en-us/download/details.aspx?id=8442

For x64 choose:

GRMSDKX_EN_DVD.iso

This is tested on Windows 10.

@sogaiu
Copy link
Contributor

sogaiu commented Jun 19, 2019

In a VM with Windows 10 that has installed on it:

  • Microsoft Visual C++ 2010 x64 Redistributable (10.0.30319)

two clj-kondo.exe versions behave more normally (usage info is output upon execution with no arguments) from cmd.exe.

The two versions I tested for clj-kondo were:

  • 2019.06.16-alpha
  • 2019.06.07-alpha

This system has (to my current recollection) never had Windows SDK for Windows 7 (version 7.1) installed on it.

It also happens to have on it:

  • Microsoft Visual C++ 2013 Redistributable (x64) (12.0.30501.0)
  • Microsoft Visual C++ 2015 Redistributable (x64) (14.0.23026.0)

@borkdude
Copy link
Member Author

@sogaiu Does more normally also mean that it works correctly? E.g. echo "(inc)" | clj-kondo --lint -?

@sogaiu
Copy link
Contributor

sogaiu commented Jun 19, 2019

@borkdude Yes, for both versions of clj-kondo installed, I got output about 0 errors and 0 warnings for the sample code you mentioned.

@borkdude
Copy link
Member Author

borkdude commented Jun 19, 2019

I can confirm that on a fresh Win10 VM with Microsoft Visual C++ 2010 x64 Redistributable (version 10.0.30319) installed, clj-kondo outputs at least something, but doesn't function correctly:

echo "{:a 1 :a 2}" | clj-kondo --lint -
linting took 8ms, errors: 0, warnings: 0

Here it should give a warning about a duplicate key...

@sogaiu
Copy link
Contributor

sogaiu commented Jun 19, 2019

@borkdude similar results here -- no warnings and no errors.

Out of curiosity, have you verified that clj-kondo is actually receiving the form?

@borkdude
Copy link
Member Author

@sogaiu My bad, it turns out it worked perfectly.

echo (inc) | clj-kondo --lint -
<stdin>:1:1: error: wrong number of args (0) passed to clojure.core/inc
linting took 18ms, errors: 1, warnings: 0

You have to omit the quotes, else it's passed as a string literal apparently.

@sogaiu
Copy link
Contributor

sogaiu commented Jun 19, 2019

@borkdude Nice that it works :) Keep hearing about quoting issues recently...

Oddly enough, on the Windows 7 SP1 machine (where the execution is not normal), I have:

  • Microsoft Visual C++ 2010 x64 Redistributable (10.0.30319)
  • Microsoft Visual C++ 2013 Redistributable (x64) (12.0.21005)
  • Microsoft Visual C++ 2013 Redistributable (x64) (12.0.30501)

But there is no:

  • Microsoft Visual C++ 2015 Redistributable (x64) (14.0.23026.0)

@borkdude
Copy link
Member Author

borkdude commented Jun 19, 2019

@sogaiu I compiled that version of clj-kondo.exe on a Windows 10 VM. @lispyclouds informed me that

the msvc runtime (glibc for windows) is different

on Windows 7 and Windows 10, so that might be the issue. I think it makes sense to only support Windows 10 going forward, since Windows 7 is reaching end of life soon?

@sogaiu
Copy link
Contributor

sogaiu commented Jun 19, 2019

@borkdude Interesting, thanks for that.

Sure, I suppose not supporting Windows 7 makes sense. Windows 10 support makes sense...but isn't there something between those two?

@borkdude
Copy link
Member Author

@sogaiu We'll see what we can do when we automate building Windows versions. See #274.

Another option, if you really need to support specific Windows versions, is to build from source.

@sogaiu
Copy link
Contributor

sogaiu commented Jun 19, 2019

@borkdude Sounds sensible.

Do I understand it correctly that something apart from the clj-kondo executable is necessary for appropriate execution then?

If so, does that suggest something extra (e.g. an installer, some dependency info expressed in scoop -- though I don't know if there is support for the redistributables there, etc.) would be helpful?

@borkdude borkdude changed the title Windows executables exit without doing anything windows: find out what is needed to run binary (visual studio c++ 2010 redist?) Jun 20, 2019
@borkdude borkdude changed the title windows: find out what is needed to run binary (visual studio c++ 2010 redist?) windows: find out what is needed to run binary on clean system (visual studio c++ 2010 redist?) Jun 20, 2019
@borkdude borkdude removed the bug Something isn't working label Jun 20, 2019
@borkdude
Copy link
Member Author

Also see oracle/graal#1407

@scottdw
Copy link

scottdw commented Jun 20, 2019

Another data point...

Windows 10, clj-kondo.exe (v2019. 06.16-alpha) in PATH.

Running "clj-kondo --lint -"
Powershell (v5.1):
works as expected, reads input until EOF and prints results.

cmd.exe:
Just prints

-:0:0: error: could not process file
lining took 3ms, errors: 1, warnings: 0

GNU Emacs 26.2.90:
Process exits silently

@borkdude
Copy link
Member Author

borkdude commented Jun 20, 2019

@scottdw Thanks for reporting! The more data we have on this, the better it is.

In cmd.exe I'm seeing this:

C:\Windows\system32>clj-kondo --lint -
(inc)
^Z
<stdin>:1:1: error: wrong number of args (0) passed to clojure.core/inc
linting took 3471ms, errors: 1, warnings: 0

which seems correct.

I can't reproduce the problem you posted where - is handled as a file name. Can you post the exact command you used including the prompt and output? (e.g. you typed lining instead of linting which probably means you didn't copy/pasted the output?)

In Emacs: could this be a path problem? I'm not sure. How did you install clj-kondo? Via scoop or manual download? Are you using other linters, that do work in Emacs?

About this issue: did you have to install any extra dependencies to make clj-kondo run? What Visual Studio C++ redistributables do you have installed?

@borkdude
Copy link
Member Author

@scottdw Additional comment. I just found out that with flycheck-compile you can see how the command is invoked. E.g. I'm seeing this:

-*- mode: compilation; default-directory: "~/dre/DocSearch/app/src-cljs/dre/components/" -*-
Compilation started at Thu Jun 20 18:23:41

clj-kondo --lint - --lang cljs --cache < /Users/Borkdude/dre/DocSearch/app/src-cljs/dre/components/document.cljs
�AnSiTu Borkdude
�AnSiTc /Users/Borkdude/dre/DocSearch/app/src-cljs/dre/components
<stdin>:9:14: warning: namespace clojure.walk is required but never used
<stdin>:11:14: warning: namespace dre.components.widget is required but never used
<stdin>:15:14: warning: namespace reagent.core is required but never used
<stdin>:16:14: warning: namespace re-frame.core is required but never used
<stdin>:17:14: warning: namespace dre.components.widget.subs is required but never used
<stdin>:18:14: warning: namespace dre.components.widget.events is required but never used
<stdin>:107:12: warning: unused binding meta
<stdin>:244:31: warning: unused binding doc
linting took 39ms, errors: 0, warnings: 8

Compilation exited abnormally with code 2 at Thu Jun 20 18:23:42

Can you post your output from this command in Emacs?

@scottdw
Copy link

scottdw commented Jun 21, 2019

C:\Users\scottdw>clj-kondo --lint -
-:0:0: error: could not process file
linting took 2ms, errors: 1, warnings: 0

I'm pretty sure it's not a path issue, or at least not an issue finding the binary. Comparing the output in the scratch buffer between the following calls:

(call-process "java" nil t)
(call-process "clj-kondo" nil t)
(call-process "notfound" nil t)

seems to indicate that it finds the binary, it just doesn't produce any output.
Used the manual download install method without installing additional dependencies and the flycheck-joker linter works with the joker binary in the same location as clj-kondo.

-*- mode: compilation; default-directory: "~/prj/workbench/src/clj/scottdw/workbench/" -*-
Compilation started at Fri Jun 21 12:04:38

"clj-kondo" "--lint" "-" "--lang" "clj" "--cache" < "c:/Users/scottdw/prj/workbench/src/clj/scottdw/workbench/web.clj"

Compilation exited abnormally with code 3 at Fri Jun 21 12:04:39

Perhaps running through Emacs is affecting which dynamic libraries are used when running clj-kondo. Running through the "Git Bash" shell (mingw based, like Emacs) produces similar results.

scottdw@work MINGW64 ~
$ clj-kondo

scottdw@work MINGW64 ~
$

@borkdude
Copy link
Member Author

@scottdw Thanks for the feedback! I think I'll mark Windows as 'experimental' or 'unsupported' although I will keep providing the binaries built from Appveyor in the future. Until we've sorted this out. It seems the binary depends on external .dll and it's hard to say which, unless GraalVM clarifies this. See oracle/graal#1407.

@borkdude
Copy link
Member Author

borkdude commented Jun 23, 2019

@borkdude
Copy link
Member Author

This might help in appveyor: https://lucasg.github.io/2018/04/29/Dependencies-command-line/

@sogaiu
Copy link
Contributor

sogaiu commented Jun 25, 2019

Based on recent experiments, I think it's likely that some of the supposed inconsistent behaviors may be the result of PATH variations. On Windows, apparently PATH may influence what DLLs get loaded.

The following has lots more detail:

https://docs.microsoft.com/en-us/windows/desktop/Dlls/dynamic-link-library-search-order

I'm not sure, but my guess is that the section titled "Search Order for Desktop Applications" may be the relevant one for native-image programs. I looked for info on console programs, but so far haven't found anything relevant.

Also found the following:

https://github.com/numpy/numpy/wiki/windows-dll-notes

It references the former (as well as other) documents and contains observations. Intend to digest it a bit. Possibly it's a better starting point.

@sogaiu
Copy link
Contributor

sogaiu commented Jun 28, 2019

The most recent experiments I've done in a Windows 10 VM suggest that putting clj-kondo.exe and mscvr100.dll in the same directory often leads to a working situation (see below for why this may not always work).

May be other folks can verify whether this works for them.


My current impression is that it may be even safer / stabler if redirection / SxS is implemented as described here:

https://github.com/numpy/numpy/wiki/windows-dll-notes#user-content-side-by-side-assemblies

One of the issues this method appears to address is the one of "already-loaded" (previous loading) dll as described in the section:

https://github.com/numpy/numpy/wiki/windows-dll-notes#user-content-which-dll

If a DLL with the same module name is already loaded in memory, the system uses the loaded DLL, no matter which directory it is in. The system does not search for the DLL.

This is an issue because it may affect stability of execution as well as security and as a consequence related support issues may be more likely to arise as well.

Another approach would be to have a statically compiled clj-kondo.exe, but this doesn't look practical yet. IIUC, this would require changes upstream from the Graal / native-image folks.

@timgilbert
Copy link

timgilbert commented Aug 2, 2019

As another data point, I've got Win 10 Pro and the C++ redistributable 2010 installed (10.0.4.40219 according to add/remove programs), and I can't get clj-kondo.exe to launch at all - it seems to just exit without reading anything from stdin. I tried the latest version on scoop and the 2019.07.31-alpha version from the releases. I've tried it from cmd.exe and powershell.exe.

I looked for mscvr100.dll to see about testing clj-kondo with the DLL in the same directory, but couldn't find it anywhere on my system.

@borkdude
Copy link
Member Author

borkdude commented Aug 2, 2019

Maybe related: oracle/graal#1469

@sogaiu
Copy link
Contributor

sogaiu commented Aug 3, 2019

@timgilbert IIUC, currently, even if clj-kondo.exe is run with the appropriate DLLs (ATM, I still think this is some appropriate version of mscvr100.dll), due to issues with native-image, I don't think it's likely to work on Windows.

At one point I tested a private assembly situation for clj-kondo so it would use a mscvr100.dll that lived in the same directory as clj-kondo.exe, but that wasn't sufficient to get it to behave correctly. As far as we understand, there is at least one issue on the Graal side -- it's hard to say it's a Clojure issue, because native-image binaries for Linux and macos work appropriately. The link borkdude posted gives some details on our findings.

I have tested an ugly work-around for a similar native-image project, but I'm not sure if it's worth implementing just yet. I am waiting on the Graal folks for a response. If it looks like it's going to be a long time before they address this issue (it's not clear yet whether they will want to or even if they wanted to, how long that might take), perhaps the work-around will be worth it for some cases. That's up to borkdude to decide for clj-kondo :)

The work-around consists of using an additional program that can handle stdin / stdout communications properly to have it act as an intermediary / wrapper around Windows native-image programs generated from Clojure source.

From testing, it looks like writing to / reading from files on secondary storage is something Windows native-image programs generated from Clojure source can handle.

The intermediary would take what it receives on stdin, write it to a file and then invoke the native-image program with two file paths, one for the native-image program to read from and the other to write to. The native-image program would then read content from one of the files, perform its processing and write to the second file path provided to it. Subsequently, the wrapper program would read the content of the second file and send that out of its stdout.

Not great, but it appears to work in my limited testing.

@remkop
Copy link

remkop commented Oct 28, 2019

Related: oracle/graal#1762

To avoid the dependency on a separate msvcr100.dll (which is often missing in Windows systems), one idea is to use a different compiler flag to statically link libraries. Currently native images are built with the /MD flag, while we need the /MT flag to statically link.

@bobvandette is looking into building the JDK static libraries for Windows with /MT (they are currently all built with /MD, which prevents native images from being built with /MT). He notes that this would likely increase the generated native image size - it is currently unknown by how much.

@borkdude
Copy link
Member Author

Thanks @remkop! I subscribed to that issue. In my opinion, a larger native binary size is less of a problem than the .dll errors.

@mbbee
Copy link

mbbee commented Oct 28, 2019

It is msvcr100.dll not mscvr100.dll i think ...

@remkop
Copy link

remkop commented Oct 28, 2019

@mbbee Thanks! I fixed the typo in my previous comment.

@borkdude
Copy link
Member Author

Fixed with GraalVM 19.3.0

clj-kondo automation moved this from Low priority to Done Nov 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed windows
Projects
clj-kondo
  
Done
Development

No branches or pull requests

6 participants