Search code examples
javapicocli

Unable to compile using Picocli


I'm a dev student I would love to use Picocli in my project, unfortunately I doesn't understand how to compile using Picocli I trie to follow the instruction given here https://picocli.info/ or here https://picocli.info/quick-guide.html but the step to compile aren't detailed. I'm not using Gradle nor Maven but they aren't really listed as required.

This is how it tried to compile the Checksum example given in the picocli.info webpage :

jar cf checksum.jar Checksum.java ; jar cf picocli-4.6.1.jar CommandLine.java && echo "hello" >  hello

Then I simply copy paste this gived command : https://picocli.info/#_running_the_application

java -cp "picocli-4.6.1.jar:checksum.jar" CheckSum --algorithm SHA-1 hello

And get the following result :

Error: Could not find or load main class CheckSum
Caused by: java.lang.ClassNotFoundException: CheckSum

I tried to compile everything myself and then add the .jar like this :

java CheckSum -jar picocli-4.6.1.jar

But then the error output looks like this:

Exception in thread "main" java.lang.NoClassDefFoundError: picocli/CommandLine
at CheckSum.main(Checksum.java:33)
Caused by: java.lang.ClassNotFoundException: picocli.CommandLine
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more

Witch I don't understand since I added the dependency.

What am I missing ?

Thanks in advance


Solution

  • The problem is that the command jar cf checksum.jar Checksum.java only creates a jar file (jar files are very similar to zip files) that contains the Checksum.java source file.

    What you want to do instead is compile the source code first. After that, we can put the resulting Checksum.class file (note the .class extension instead of the .java extension) in the checksum.jar. The Java SDK includes the javac tool that can be used to compile the source code. Detailed steps follow below.

    First, open a terminal window and navigate to a directory that contains both the Checksum.java source file and the picocli-4.6.1.jar library.

    Now, the command to compile (on Windows) is:

    javac -cp .;picocli-4.6.1.jar Checksum.java
    

    Linux uses : as path separator instead of ;, so on Linux, the command to compile is:

    javac -cp .:picocli-4.6.1.jar Checksum.java
    

    The -cp option allows you to specify the classpath, which should contain the directories and jar/zip files containing any other class files that your project uses/depends on. Since Checksum.java uses the picocli classes, we put the picocli jar in the classpath. Also add the current directory . to the classpath when the current directory contains any classes. I just add . habitually now.

    Now, if you list the files in the current directory, you should see that a file Checksum.class has been created in this directory.

    Our Checksum class has a main method, so we can now run the program with the java tool:

    On Windows:

    java -cp .;picocli-4.6.1.jar Checksum
    

    On Linux:

    java -cp .:picocli-4.6.1.jar Checksum
    

    Note that when running the program with java you specify the class name Checksum, not the file name Checksum.class.

    You can pass arguments to the Checksum program by passing them on the command line immediately following the class name:

    java -cp .:picocli-4.6.1.jar Checksum --algorithm=SHA-1 /path/to/hello
    

    When your project grows, you may want to keep the source code and the compiled class files in separate directories. The javac compile utility has a -d option where you can specify the destination for the compiled class files. For example:

    javac -cp picocli-4.6.1.jar:otherlib.jar -d /destination/path /path/to/source/*.java 
    

    This should generate .class files for the specified source files in the specified destination directory (/destination/path in the example above).

    When you have many class files, you may want to bundle them in a single jar file. You can use the jar command for that. I often use the options -v (verbose) -c (create) -f (jar file name) when creating a jar for the compiled class files. For example:

    jar -cvf MyJar.jar /destination/path/*.class /destination/path2/*.class
    

    Enjoy!