- 1. About
picocli-codegen
- 2. Generate GraalVM Configurations with the Annotation Processor
- 3. Generate GraalVM Configurations Manually
- 4. Generate Documentation
The picocli-codegen
(Picocli Code Generation) module contains tools for generating configuration files and documentation for picocli-based applications.
This module also includes an annotation processor that can build a model from the picocli annotations at compile time rather than at runtime.
The annotation processor allows many of the tools to be invoked automatically as part of the build without configuration. If a tool does not have an annotation processor wrapper (yet), it can be invoked on the command line, and can be scripted to be invoked automatically as part of building your project.
As of picocli version 4.2, this module has three major use cases:
-
Compile time error checking. The annotation processor shows errors for invalid annotations and attributes immediately when you compile, instead of during testing at runtime, resulting in shorter feedback cycles.
-
GraalVm native images. To create a GraalVM native image for a picocli application, configuration is needed. The
ReflectionConfigGenerator
,ResourceConfigGenerator
andDynamicProxyGenerator
tools can generate configuration files for reflection, resources and dynamic proxies, respectively.The annotation processor embeds these three tools and generates the configuration files under
META-INF/native-image/picocli-generated/$project
during compilation, to be included in the application jar. By embedding these configuration files, your jar is instantly GraalVM-enabled. In most cases no further configuration is needed when generating a native image. -
Generate Documentation. The
ManPageGenerator
tool can generate AsciiDoc documentation for picocli applications. AsciiDoc is a lightweight markup language that can easily can be converted to unix man pages, HTML and PDF with the wonderful asciidoctor tool.
To build a GraalVM native image for a picocli-based application, configuration files are needed to tell the GraalVM native-image
generator tool which classes, methods and fields will be accessed reflectively, and which resources and dynamic proxies the application will use.
The picocli-codegen
module has tools that generate these configuration files for a picocli-based application.
The annotation processor in the picocli-codegen
jar wraps these tools so they are executed automatically during compilation.
The annotation processor generates and updates GraalVM configuration
files under META-INF/native-image/picocli-generated/$project
during compilation,
to be included in the application jar.
This includes configuration files for reflection, resources and dynamic proxies.
By embedding these configuration files, your jar is instantly GraalVM-enabled.
In most cases no further configuration is needed when generating a native image.
💡
|
It is recommended that you configure the $project location for your project to ensure the configuration files are in a unique location when jars are shaded into an uberjar, see processor options below.
|
Since Java 6, annotation processing is part of the standard javac
compiler, but many IDEs and build tools require something extra to enable annotation processing.
This page shows the steps to configure Eclipse and IntelliJ IDEA to enable annotation processing.
In Maven, use annotationProcessorPaths
in the configuration
of the maven-compiler-plugin
.
This requires maven-compiler-plugin
plugin version 3.5 or higher.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- annotationProcessorPaths requires maven-compiler-plugin version 3.5 or higher -->
<version>${maven-compiler-plugin-version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
An alternative that works with older versions of the maven-compiler-plugin
is to specify the picocli-codegen
module on the classpath as a provided
dependency. This also prevents the picocli-codegen
module from being included in the artifact the module produces as a transitive dependency.
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
<scope>provided</scope>
</dependency>
See processor options below.
Use the annotationProcessor
path in Gradle 4.6 and higher:
dependencies {
implementation 'info.picocli:picocli:4.6.3'
annotationProcessor 'info.picocli:picocli-codegen:4.6.3'
}
For Gradle versions prior to 4.6, use compileOnly
, to prevent the picocli-codegen
jar from being a transitive dependency included in the artifact the module produces.
dependencies {
implementation 'info.picocli:picocli:4.6.3'
compileOnly 'info.picocli:picocli-codegen:4.6.3'
}
Add an execution of the kapt
goal from kotlin-maven-plugin
before compile
:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
<execution>
<id>compile</id>
<!-- ... details omitted... -->
</execution>
</executions>
</plugin>
JetBrains' Kotlin repository has a complete sample project showing the use of Kotlin, Maven and Dagger.
Kotlin projects should add the kotlin-kapt
plugin to enable the Kotlin Annotation processing tool (kapt),
then replace annotationProcessor
with kapt
:
apply plugin: 'kotlin-kapt' // required
dependencies {
// ...
kapt 'info.picocli:picocli-codegen:4.6.3'
}
And replace compileJava.options.compilerArgs
with kapt.arguments
:
kapt {
arguments {
arg("project", "${project.group}/${project.name}")
}
}
The picocli annotation processor supports the options below.
-
project
- output subdirectory
The generated files are written to META-INF/native-image/picocli-generated/${project}
.
The project
option can be omitted, but it is a good idea to specify the project
option with a unique value for your project (e.g. ${project.groupId}/${project.artifactId}
) if your jar may be shaded with other jars into an uberjar.
-
verbose
- (from picocli 4.3) print NOTE-level diagnostic messages to the console -
other.resource.patterns
- comma-separated list of regular expressions matching additional resources to include in the image -
other.resource.bundles
- comma-separated list of the base names of additional resource bundles to include in the image -
other.proxy.interfaces
- comma-separated list of the fully qualified class names of additional interfaces for which to generate proxy classes when building the image -
disable.proxy.config
- disable the DynamicProxyConfigGenerator tool so noproxy-config.json
file is generated -
disable.reflect.config
- disable the ReflectionConfigGenerator tool so noreflect-config.json
file is generated -
disable.resource.config
- disable the ResourceConfigGenerator tool so noresources-config.json
file is generated
To pass an annotation processor option with javac
, specify the -A
command line option:
javac -Aproject=org.myorg.myproject/myapp -cp ...
The -A
option lets you pass options to annotation processors. See the javac documentation for details.
To set an annotation processor option in Maven, you need to use the maven-compiler-plugin
and configure the compilerArgs
section.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- annotationProcessorPaths requires maven-compiler-plugin version 3.5 or higher -->
<version>${maven-compiler-plugin-version}</version>
<configuration>
<compilerArgs>
<arg>-Aproject=${project.groupId}/${project.artifactId}</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
To set an annotation processor option in Gradle, add these options to the options.compilerArgs
list in the compileJava
block.
compileJava {
// minimum 1.6
sourceCompatibility = ${java-version}
targetCompatibility = ${java-version}
options.compilerArgs += ["-Aproject=${project.group}/${project.name}"]
}
See the Gradle documentation for details.
In Kotlin projects using Gradle, replace compileJava.options.compilerArgs
with kapt.arguments
:
kapt {
arguments {
arg("project", "${project.group}/${project.name}")
}
}
See the Kotlin Annotation Processing documentation for details.
The annotation processor is the recommended way to generate configuration files for GraalVM native images, but there may be cases where you want to generate these configuration files manually. For example, if your commands are written in Groovy, the picocli annotation processor will not be able to auto-generate configuration files for your commands, and you need to do some work to invoke the commands in your build.
The sections below give details on how to do this.
The picocli-codegen
module contains the following tools to assist with AOT compilation to GraalVM native image builds:
-
ReflectionConfigGenerator
-
ResourceConfigGenerator
-
DynamicProxyConfigGenerator
The generated configuration files can be supplied to the native-image
tool via command line options like -H:ReflectionConfigurationFiles=/path/to/reflect-config.json
,
or alternatively by placing them in a META-INF/native-image/
directory on the class path, for example, in a JAR file used in the image build.
This directory (or any of its subdirectories) is searched for files with the names reflect-config.json
, proxy-config.json
and resource-config.json
,
which are then automatically included in the build. Not all of those files must be present.
When multiple files with the same name are found, all of them are included.
See also the SubstrateVM configuration documentation.
GraalVM has limited support for Java reflection and it needs to know ahead of time the reflectively accessed program elements.
ReflectionConfigGenerator
generates a JSON String with the program elements that will be accessed reflectively in a picocli-based application, in order to compile this application ahead-of-time into a native executable with GraalVM.
The output of ReflectionConfigGenerator
is intended to be passed to the -H:ReflectionConfigurationFiles=/path/to/reflect-config.json
option of the native-image
GraalVM utility,
or placed in a META-INF/native-image/
subdirectory of the JAR.
This allows picocli-based applications to be compiled to a native image.
See Picocli on GraalVM: Blazingly Fast Command Line Apps for details.
Note that the annotation processor does this automatically. The below is only of interest if you cannot use the annotation processor for some reason.
The --output
option can be used to specify the path of the file to write the configuration to.
When this option is omitted, the output is sent to standard out.
The ReflectionConfigGenerator
tool accepts any number of fully qualified class names of command classes
(classes with picocli annotations like @Command
, @Option
and @Parameters
).
The resulting configuration file will contain entries for the reflected elements of all specified classes.
For Maven, add an exec:java
goal to generate a Graal reflection configuration file with the ReflectionConfigGenerator
tool.
This example uses the process-classes
phase of the build, there are alternatives.
Note that the picocli-codegen
module is only added as a dependency for the exec
plugin, so it does not need to be added to the project dependencies.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>generateGraalReflectionConfig</id>
<phase>process-classes</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>true</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>picocli.codegen.aot.graalvm.ReflectionConfigGenerator</mainClass>
<arguments>
<argument>--output=target/classes/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json</argument>
<argument>com.your.package.YourCommand1</argument>
<argument>com.your.package.YourCommand2</argument>
</arguments>
</configuration>
<dependencies>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
For Gradle, add a custom configuration for the picocli-codegen
module to your gradle.build
.
This allows us to add this module to the classpath of our custom task without adding it as a dependency to the "standard" build.
configurations {
generateConfig
}
dependencies {
implementation 'info.picocli:picocli:4.6.3'
generateConfig 'info.picocli:picocli-codegen:4.6.3'
}
Then, add a custom task to run the ReflectionConfigGenerator
tool.
This example generates the file during the assemble
lifecycle task, there are alternatives.
task(generateGraalReflectionConfig, dependsOn: 'classes', type: JavaExec) {
main = 'picocli.codegen.aot.graalvm.ReflectionConfigGenerator'
classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath
def outputFile = "${buildDir}/resources/main/META-INF/native-image/${project.group}/${project.name}/reflect-config.json"
args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2']
}
assemble.dependsOn generateGraalReflectionConfig
The GraalVM native-image builder by default will not integrate any of the classpath resources into the image it creates.
ResourceConfigGenerator
generates a JSON String with the resource bundles and other classpath resources
that should be included in the Substrate VM native image.
The output of ResourceConfigGenerator
is intended to be passed to the -H:ResourceConfigurationFiles=/path/to/reflect-config.json
option of the native-image
GraalVM utility,
or placed in a META-INF/native-image/
subdirectory of the JAR.
This allows picocli-based native image applications to access these resources.
Note that the annotation processor does this automatically. The below is only of interest if you cannot use the annotation processor for some reason.
The --output
option can be used to specify the path of the file to write the configuration to.
When this option is omitted, the output is sent to standard out.
The ResourceConfigGenerator
tool accepts any number of fully qualified class names of command classes
(classes with picocli annotations like @Command
, @Option
and @Parameters
).
The resulting configuration file will contain entries for the resource bundles used in any of the specified commands or their subcommands.
The --bundle
option can be used to specify the base name of additional resource bundle(s) to be included in the image.
The --pattern
option can be used to specify Java regular expressions that match additional resource(s) to be included in the image.
For Maven, add an exec:java
goal to generate a Graal resource configuration file with the ResourceConfigGenerator
tool.
This example uses the process-classes
phase of the build, there are alternatives.
Note that the picocli-codegen
module is only added as a dependency for the exec
plugin, so it does not need to be added to the project dependencies.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>generateGraalResourceConfig</id>
<phase>process-classes</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>true</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>picocli.codegen.aot.graalvm.ResourceConfigGenerator</mainClass>
<arguments>
<argument>--output=target/classes/META-INF/native-image/${project.groupId}/${project.artifactId}/resource-config.json</argument>
<argument>com.your.package.YourCommand1</argument>
<argument>com.your.package.YourCommand2</argument>
</arguments>
</configuration>
<dependencies>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
For Gradle, add a custom configuration for the picocli-codegen
module to your gradle.build
.
This allows us to add this module to the classpath of our custom task without adding it as a dependency to the "standard" build.
configurations {
generateConfig
}
dependencies {
implementation 'info.picocli:picocli:4.6.3'
generateConfig 'info.picocli:picocli-codegen:4.6.3'
}
Then, add a custom task to run the ResourceConfigGenerator
tool.
This example generates the file during the assemble
lifecycle task, there are alternatives.
task(generateGraalResourceConfig, dependsOn: 'classes', type: JavaExec) {
main = 'picocli.codegen.aot.graalvm.ResourceConfigGenerator'
classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath
def outputFile = "${buildDir}/resources/main/META-INF/native-image/${project.group}/${project.name}/resource-config.json"
args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2']
}
assemble.dependsOn generateGraalResourceConfig
Substrate VM doesn’t provide machinery for generating and interpreting bytecodes at run time. Therefore all dynamic proxy classes need to be generated at native image build time.
DynamicProxyConfigGenerator
generates a JSON String with the fully qualified interface names for which
dynamic proxy classes should be generated at native image build time.
The output of DynamicProxyConfigGenerator
is intended to be passed to the -H:DynamicProxyConfigurationFiles=/path/to/proxy-config.json
option of the native-image
GraalVM utility,
or placed in a META-INF/native-image/
subdirectory of the JAR.
This allows picocli-based native image applications that use @Command
-annotated interfaces with
@Option
and @Parameters
-annotated methods.
Note that the annotation processor does this automatically. The below is only of interest if you cannot use the annotation processor for some reason.
The --output
option can be used to specify the path of the file to write the configuration to.
When this option is omitted, the output is sent to standard out.
The DynamicProxyConfigGenerator
tool accepts any number of fully qualified class names of command classes
(classes with picocli annotations like @Command
, @Option
and @Parameters
).
The resulting configuration file will contain entries for the resource bundles used in any of the specified commands or their subcommands.
The --interface
option can be used to specify the fully qualified class names of additional interfaces to generate dynamic proxy classes for in the native image.
For Maven, add an exec:java
goal to generate a Graal proxy configuration file with the DynamicProxyConfigGenerator
tool.
This example uses the process-classes
phase of the build, there are alternatives.
Note that the picocli-codegen
module is only added as a dependency for the exec
plugin, so it does not need to be added to the project dependencies.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>generateGraalDynamicProxyConfig</id>
<phase>process-classes</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>true</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>picocli.codegen.aot.graalvm.DynamicProxyConfigGenerator</mainClass>
<arguments>
<argument>--output=target/classes/META-INF/native-image/${project.groupId}/${project.artifactId}/proxy-config.json</argument>
<argument>com.your.package.YourCommand1</argument>
<argument>com.your.package.YourCommand2</argument>
</arguments>
</configuration>
<dependencies>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
For Gradle, add a custom configuration for the picocli-codegen
module to your gradle.build
.
This allows us to add this module to the classpath of our custom task without adding it as a dependency to the "standard" build.
configurations {
generateConfig
}
dependencies {
implementation 'info.picocli:picocli:4.6.3'
generateConfig 'info.picocli:picocli-codegen:4.6.3'
}
Then, add a custom task to run the DynamicProxyConfigGenerator
tool.
This example generates the file during the assemble
lifecycle task, there are alternatives.
task(generateGraalDynamicProxyConfig, dependsOn: 'classes', type: JavaExec) {
main = 'picocli.codegen.aot.graalvm.DynamicProxyConfigGenerator'
classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath
def outputFile = "${buildDir}/resources/main/META-INF/native-image/${project.group}/${project.name}/proxy-config.json"
args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2']
}
assemble.dependsOn generateGraalDynamicProxyConfig
The picocli.codegen.docgen.manpage.ManPageGenerator
tool introduced in picocli 4.2 generates AsciiDoc documentation using the manpage
doctype and manpage document structure.
The generated AsciiDoc files can be converted to HTML, PDF and unix man pages with the asciidoctor tool.
The generated manual page for the ManPageGenerator
tool itself is here.
Example gradle build.gradle snippet:
You will also need the AsciiDoctor Gradle Plugin.
dependencies {
implementation "info.picocli:picocli:4.6.3"
annotationProcessor "info.picocli:picocli-codegen:4.6.3"
}
mainClassName = "my.pkg.MyCommand"
task generateManpageAsciiDoc(type: JavaExec) {
dependsOn(classes)
group = "Documentation"
description = "Generate AsciiDoc manpage"
classpath(configurations.compile, configurations.annotationProcessor, sourceSets.main.runtimeClasspath)
main 'picocli.codegen.docgen.manpage.ManPageGenerator'
args mainClassName, "--outdir=${project.buildDir}/generated-picocli-docs", "-v" //, "--template-dir=src/docs/mantemplates"
}
apply plugin: 'org.asciidoctor.jvm.convert'
asciidoctor {
dependsOn(generateManpageAsciiDoc)
sourceDir = file("${project.buildDir}/generated-picocli-docs")
outputDir = file("${project.buildDir}/docs")
logDocuments = true
outputOptions {
backends = ['manpage', 'html5']
}
}
The generateManpageAsciiDoc
task generates $COMMANDNAME.adoc
files with doctype manpage
in build/generated-picocli-docs
for each command and subcommand.
The asciidoctor
task converts the generated $COMMANDNAME.adoc
files in build/generated-picocli-docs
to $COMMANDNAME.1
manpage files in build/docs/manpage/
, and to $COMMANDNAME.html
HTML files in build/docs/html5/
.
See the example-gradle-project in the picocli-examples
module for a full working example.
You will also need the AsciiDoctor Maven Plugin.
For Maven, add an exec:java
goal to generate a Graal proxy configuration file with the ManPageGenerator
tool.
This example uses the process-classes
phase of the build, there are alternatives.
Note that the picocli-codegen
module is only added as a dependency for the exec
plugin, so it does not need to be added to the project dependencies.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>generateManPages</id>
<phase>process-classes</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>true</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>picocli.codegen.docgen.manpage.ManPageGenerator</mainClass>
<arguments>
<argument>--outdir=${project.build.directory}/generated-picocli-docs</argument>
<argument>com.your.package.YourCommand1</argument>
<argument>com.your.package.YourCommand2</argument>
</arguments>
</configuration>
<dependencies>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>output-html</id>
<phase>process-classes</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceHighlighter>coderay</sourceHighlighter>
<backend>html5</backend>
</configuration>
</execution>
<execution>
<id>output-manpage</id>
<phase>process-classes</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceHighlighter>coderay</sourceHighlighter>
<backend>manpage</backend>
</configuration>
</execution>
</executions>
<configuration>
<sourceDirectory>${project.build.directory}/generated-picocli-docs</sourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
See the example-maven-project in the picocli-examples
module for a full working example.
The generated man page is very similar to the online help generated by the command itself when a user specifies the --help
option.
You may want to add more details or extra sections to the man page.
To achieve this, the ManPageGenerator
tool has an option to create an additional "template" file for each generated manpage AsciiDoc file.
The generated manpage AsciiDoc files will be regenerated every build. We don’t want to edit these files because we would lose our changes every time the files are regenerated.
Instead, we will edit "template" files. Template files leverage AsciiDoctor’s include mechanism to import the contents of the generated manpage AsciiDoc files into a separate file.
The template page initially just contains a number of include::path/to/some.adoc[tag=xxx]
statements.
Each include
statement imports part of a generated manpage AsciiDoc file.
You can rearrange these includes and add text after each include to customize the resulting man page.
Once we created the template files, we will need to tell the asciidoctor
tool to take these template files as input instead of the generated manpage AsciiDoc files.
The resulting man page will be a mixture of generated and manually edited text.
The ManPageGenerator
tool can generate template files, but template files should not be generated multiple times.
They are intended to be generated only once, and afterwards be manually updated and maintained.
Changes in the generated manpage AsciiDoc files will then be reflected in the final output via the includes, without impacting the additions or modifications you made to the template files.
To create template pages, specify the --template-dir
option when invoking the picocli.codegen.docgen.manpage.ManPageGenerator
tool. For example:
java -cp $CLASSPATH picocli.codegen.docgen.manpage.ManPageGenerator \ -v --outdir=${project.buildDir}/generated/docs \ --template-dir=src/docs/man-templates \ my.pkg.MyCommand
This generates AsciiDoc files with the 'manpage' doctype in build/generated/docs
, and template files in src/docs/man-templates
.
🔥
|
Do this only once, then remove the --template-dir option, so that subsequent ManPageGenerator invocations will only update the generated manpage AsciiDoc files and will not overwrite the template files.
|
🔥
|
If the ManPageGenerator tool detects an existing template file, it will abort with an error (and exit code 4).
The existing template will not be overwritten unless the --force option is specified.
|
We can now edit the files in src/docs/man-templates
and tell the asciidoctor
tool to generate HTML and man page files in troff format from the files in src/docs/man-templates
.
In its simplest form a template file can include the full generated page with the picocli-generated-full-manpage
tag.
This allows us to add some sections to the end of the page.
For example:
// src/docs/man-templates/xxx.adoc :includedir: ../../../build/generated/docs include::{includedir}/xxx.adoc[tag=picocli-generated-full-manpage] == Authors My, myself and I.
It is also possible to include the picocli-generated sections individually, so that the generated sections can be customized with additional text that follows the generated text for the section. For example:
// src/docs/man-templates/yyy.adoc :includedir: ../../../build/generated/docs include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-header] include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-name] This is a very good tool that will serve you well. include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-synopsis] *mycommand* [-hVv] [a=VERY] [--different=synopsis] include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-description] Here is one additional description line. Here is another additional description line. include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-options] include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-arguments] include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-commands] include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-exit-status] include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-footer] == More Examples [%hardbreaks] Here are some extra examples: abc def ghi jkl mno pq abc def ghi jkl mno pq abc def ghi jkl mno pq == Authors All of us. == Copyright Just hand it out, it's fine.
Then, when invoking the asciidoctor
tool, specify the directory containing the template files as the source directory. For example:
# generate man pages in troff format in build/docs/manpage
asciidoctor --backend=manpage --source-dir=src/docs/man-templates --destination-dir=build/docs *.adoc
# generate man pages in HTML format in build/docs/html5
asciidoctor --backend=html5 --source-dir=src/docs/man-templates --destination-dir=build/docs *.adoc