Closed JLedelay closed 1 year ago
I suspect that:
bin/vct
script (this is fine, but unfortunately occasionally brittle);bin/.classpath
exists, but is empty or only contains whitespace.VerCors is invoked from this script like:
java %MORE_JAVA_OPTS% -Xss128M -cp "%CLASSPATH%" %*
This ends up being:
java -Xss128M -cp vct.main.Main C.java
Sure enough:
$ java -Xss128M -cp vct.main.Main examples/private/joel15.java
error: can't find main(String[]) method in class: C
Deleting the bin/.classpath
file should regenerate the classpath, resolving the problem - let me know.
Edit: to be clear: this invokes the java compiler - not vercors. We are using the nonsense classpath "vct.main.Main". Apparently you can pass a source file directly to java
to run it.
I indeed run vercors via the bin/vct
script.
The file bin/.classpath
is not empty.
I renamed bin/.classpath
to bin/.classpath_temp
. Running bin/vct C.java
again, the classpath is extracted from sbt. The contents of the newly generated bin/.classpath
are identical to bin/.classpath_temp
, and I get the same error as before.
Edit: I do indeed get the same result when running with an empty bin/.classpath file. I'm wondering if there's something obviously missing in mine?
Ah okay, next guess: you have the correct classpath, but it's too long: I believe 8192 characters is some type of limit on windows. I would not expect it to entirely drop an argument that is too long, but I don't know how else to explain it...
At least a workaround for now: compile vercors with sbt stage
instead (or just type stage
in the sbt shell in IntelliJ). This generates the files for the release, without actually bundling them in a deb
or zip
etc. You should find a working run script in target/universal/stage/bin
. The reason this works is because in the release all our jars are in one directory, so we can directly pass lib/*
to java (this does not expand to all the files in the shell script, it remains the literal string *
, apparently supported by java)
I vaguely remember there being a character limit on (environment?) variables on windows... This might impact the run script?
Also: putting the root of your project in C:\ might help
Edit: as for cause analysis: I added some dependencies in that PR; that might've pushed the classpath length over the limit.
It indeed seemed like the classpath (or the complete command including the classpath) was indeed too long.
I did a few things to work around this issue:
sbt stage
as Pieter recommended. I did have some trouble getting the script to work, and it seemed that the classpath still wasn't being loaded properly. Because of this, I moved on to some suggestions that Bob mentioned.COURSIER_CACHE
to C:\COURSIER_CACHE
. This replaced the default value C:\Users\joell\AppData\Local\Coursier\v1\
with C:\COURSIER_CACHE
. Instructions can be found here. This path occurred more than 50 times in bin/.classpath
, so this shortened it considerably to around 8100 characters (under the 8192 character limit, but not by a lot). This allowed me to run VerCors, but when the command became too long, I got an error "error: The syntax of this command is incorrect" in cmd (and powershell), which indicated to me that the classpath needed to be shortened further. C:\vercors-dblock
. Since the previous path C:\Universiteit\Master\Afstuderen\vercors-dblock\
occurred 9 times in the bin/.classpath
file, this shortened it by a further ~300 characters. This didn't seem to change anything in the number of files I could provide as arguments and seemed like a brittle solution anyway, so I moved on to the final suggestion from Bob, which was to run VerCors from IntelliJ.The plugin can be found here. No guarantees are given on the quality of the plugin. As the reviews state, the default sounds are not ideal. I replaced the sounds with the default Windows notification sound.
In conclusion: Running VerCors from the IntelliJ environment (as described on the wiki) is the workaround I'm using. This solves the problem, at least for now.
VerCors is also usable from the command line, if the COURSIER_CACHE
environment variable is set to a short path and not too many files are provided as arguments.
Thanks for the help!
Joel's problems look consistent with the classpath being too long for the windows command line to handle, and with the symptoms described in the question of this stack overflow post: https://stackoverflow.com/a/54270831/2078414 Maybe we can consider the file-argument (where the java
command expands the contents of a file to arguments) approach. I think you can combine this approach with regular arguments, e.g. java @classPathArgs vct.main.Main MyInputFile.java
, so there's a good chance we can make it work.
@JLedelay For now you can use the following workaround:
sbt
there and leaving it opensbt --client run ...your args...
. I think for this to work you need to be in the vercors project directory, though, so you might need to change your arguments a bit.The --client
flag causes sbt to look for an sbt server that's running on the current project. On my laptop this takes a second or so, but since your verification time is (sadly :( ) often > 30s, that might be acceptable for now
The only downside is that flags like --help
don't work properly anymore. But you were just passing files to vercors, right? So that shouldn't be a problem. This way you can probably also integrate it with the original script you had.
@niomaster I remember you suggesting this method a year ago or so. Maybe we should move to this method officially? The bin script has been annoying since... Forever. We can replace the bin scripts to just use "sbt run", and people who want a faster script can then use the server mode of sbt somehow, maybe?
EDIT: We do need to do something about that --help
problem, though. That's annoying.
No, sbt run
fiddles with e.g. the logging configuration, so I prefer not to recommend that method in general.
The classpath file does seems promising, though.
As of switching to mill we use a classpath argument file. Additionally, the classpath is always updated before running VerCors (with mill this is very efficient)
On the
dev
branch since PR #735, I'm encountering some issues with verification of Java files:Each of these have an example below. I've combined them into one issue because I'm assuming they are strongly related.
The following input:
yields the following output:
error: can't find main(String[]) method in class: C
The following input:
with the following input:
vercors\bin\vct C.java D.java
yields the following output:Changing the order to
vercors\bin\vct D.java C.java
yieldserror: can't find main(String[]) method in class: D
.Adding a main class to D.java as such:
and running
vercors\bin\vct D.java C.java
yields no output (also no[INFO] Starting verification
), and terminates in ~0.6 seconds.In comparison, running the same command with an older version of vercors (hash 4f3663596290352668f94c5d91998a33505cf2f3, just prior to the merger of PR #735 in 9e9305fa2e4d633534294567ad7e8526e1f0cf02) takes 18 seconds and gives the following output: