clj-on-windows

For those interested in making clj on Windows https://dev.clojure.org/jira/browse/TDEPS-67. Also see https://github.com/littleli/scoop-clojure.
2019-12-18T00:44:13.009900Z

i think it turned out that the classpath length i had was too long for clj to launch a jvm on windows in some cases. when the classpath got slightly shorter, clj would manage to launch a jvm, but then clj.native-image would try to launch native-image with the classpath along with other options, causing the total command line length to exceed windows' limit. i'm now checking lengths of classpaths for a variety of projects locally to see typical sizes.

2019-12-18T01:29:26.017300Z

for reference, the limitation on the length of the string for invoking the native-image command executed in cmd.exe (via a .bat file) as observed here is 7126 characters. one more character and i get the error:

The input line is too long.
The syntax of the command is incorrect.
the .cp file i had trouble with had file length 7517 bytes according to the properties dialog. as a crude test, i looked at the lengths of the .cp files i could find on my system. there were 699 of them. of those, 115 had lengths that exceeded 7126 characters. i guess that if the classpaths for those were used to try to launch a jvm on windows (via java's -cp argument as-is), many would end in the error above (native-image command invocation differs a bit from java.exe invocation, but perhaps it's close enough here). assuming that's mostly correct, i think that puts it at about 16% (115 / 699) not able to be launched by clj on windows (due to the windows command line length limitations). i've heard the number 8192 as the limit, so may be there's something off about what i'm doing -- but atm this situation doesn't seem like it's necessarily going to be that rare.

seancorfield 2019-12-18T02:11:48.018500Z

The java invocation in clojure adds not only the .cp file but also the .lib file I think, and several of its own options.

seancorfield 2019-12-18T02:12:21.018800Z

Ah, just the name of the .lib file...

seancorfield 2019-12-18T02:12:55.019300Z

exec "$JAVA_CMD" "${jvm_cache_opts[@]}" "${jvm_opts[@]}" "-Dclojure.libfile=$libs_file" -classpath "$cp" clojure.main "${main_cache_opts[@]}" "$@"
(from the Linux version -- the PS version will be similar)

seancorfield 2019-12-18T02:14:04.020100Z

That total command line can only be 8K but it's going to include the full path to the java.exe file, plus all of the above...

seancorfield 2019-12-18T02:16:13.020700Z

$JavaCmd @JvmCacheOpts @JvmOpts "-Dclojure.libfile=$LibsFile" -classpath $CP clojure.main @MainCacheOpts @ClojureArgs
(from the PS script so it's pretty similar)

👀 1
2019-12-18T03:00:49.022800Z

if it's cheap to test the java version and that's >= 9, one could use the @-file technique and put the classpath in a file instead of on the command line

littleli 2019-12-18T23:35:03.037200Z

I like this solution the most

2019-12-19T01:03:33.037400Z

for the java 8 case, the pathing jar approach appears to be implemented in tdeps 120.

2019-12-18T03:01:27.023300Z

iirc though the last survey suggested that java 8 is still quite prevalent

2019-12-18T04:03:22.024200Z

the pathing.jar approach might work, but apparently there are all sorts of "fun" limitations for the manifest file

2019-12-18T16:17:24.027100Z

i've looked at the code by timgilbert in TDEPS-120 (and lein-classpath-jar). as near as i can tell, the value it uses for the Class-Path: field in the manifest is a space-separate string of classpath elements. i am slightly surprised there are no problems with this, as i have read that there are a variety of constraints regarding lengths and formatting of values in a manifest file: https://stackoverflow.com/questions/3057841/too-long-line-in-manifest-file-while-trying-to-create-jar/3057862

2019-12-18T16:18:23.028300Z

it would be great if the current code works well as it certainly seems simpler than having to jump through the extra hoops that people seem to have (cf. the stackoverflow link).

2019-12-18T16:21:24.029500Z

perhaps the Attribute class' put method "does the right thing". that would be great.

2019-12-18T16:22:23.030100Z

i guess i can try generating a pathing jar with timgilbert's code and look at the content of the manifest file :)

1
2019-12-18T16:24:48.030700Z

(i guess it's more likely that it's a different method that "does the right thing")

dominicm 2019-12-18T18:12:46.031100Z

What if the jar has a space in the path?

2019-12-18T18:18:23.031800Z

perhaps i can test to find out

2019-12-18T20:24:22.033Z

ok, i haven't tested the space in path thing yet, but i have examined a created pathing-jar's manifest.mf: https://pastebin.com/GkppSCnw

2019-12-18T20:24:46.033500Z

file: uris are used, so may be spaces will end up as %20

2019-12-18T20:25:45.034300Z

line lengths do appear to be about 72 chars as the jar spec says

2019-12-18T20:26:07.034800Z

the leading space on the subsequent lines is for continuation afaict

2019-12-18T20:42:32.035600Z

i tried putting a space in an element of the classpath and generating the pathing jar. as expected, a %20 showed up in the Class-Path: field's value.

2019-12-18T21:10:34.036700Z

when the pathing jar code is run on a linux box with windows file paths, the resulting file: uris are a bit wonky, but when run on a windows box, they seem ok: https://pastebin.com/qUEW7xYL

2019-12-18T21:11:54.036900Z

here's the wonky stuff: https://pastebin.com/EZs47wNU

2019-12-18T21:12:20.037100Z

may be that's not too surprising