-generate srcs ‘;output=’ DIR ( ‘;’ ( system generate classpath))* … | bnd
Description: Virtually all the work bnd is concerned about happens in generating the JAR file. The key idea is to pull resources in the JAR, instead of the more traditional push model of other builders. This works well, except for generating source code. This generating step must happen before the compiler is called, and the compiler is generally called before bnd becomes active.

- # -generate srcs ';output=' DIR ( ';' ( system | generate | classpath))* ...
  Project

  Virtually all the work bnd is concerned about happens in generating the JAR file. The key idea is to pull resources in the JAR, instead of the more traditional push model of other builders. This works well, except for generating source code. This generating step must happen before the compiler is called, and the compiler is generally called before bnd becomes active.

  This `-generate` instruction specifies the code generating steps that must be executed. Source code can be generated by system commands or the bnd external plugins.

      -generate	::= 	clause ( ',' clause )*
      clause		::= 	FILESET ';' 'output=' DIR (';' option )*
      src		::=	FILESET
      option		::= 	'system=' STRING
      		|   'generate=' STRING
              |   'classpath=' PATH
              |   'workingdir=' FILE

  For each clause, the key of the clause is used to establish an Ant File Set, e.g. `foo/**.in`. This a glob expression with the exception that the double wildcard (‘**’) indicates to any depth of directories. The `output` attribute must specify a directory. If the output must be compiled this directory must be on the bnd source path.

  If any file in the source is older than any file in the target (to any depth), or the target is empty, the clause is considered stale. If the clause is not stale, it is further ignored. If no further options are set on the clause, a warning is generated that some files are out of date.

  If either a warning or error option is given, these will be executed on the project.

  If a command `STRING` is given it is executed as in the `${system}` macro. If the command `STRING` starts with a minus sign (`-`) then a failure is not an error, it is reported as warning.

  The generate option will execute an external plugin or plain JAR with a `Main-Class` manifest header. The choice is made by looking at the first word in the `generate` attribute.

  If this name has a dot in it, like in a fully qualified class name, it is assume that species a class name. (If the name starts with a dot, it will be assume to be a name in the default package.) In this case, the `classpath` attribute of the instruction can be used to provide additional JARs on the command’s classpath. The format of PATH is the standard format for instructions like -buildpath. In this case, you can also set the `workingdir` to a directory. This directory is specified relative to the project.

  Without a dot in the name, the name is assumes to be an external plugin name, with the `objectClass` (service type) of `Generator<? extends Options>`. External , or Main-Class jars, can come from an external repository or a local workspace project.

  The `generate` value is a command line. It can use the standard unix like way of specifying a command. It supports flags (boolean parameters) and parameter that take a value. When this external plugin is executed, it is expected to create files fall within the target, if not, an error is reported. These changed or created files are refreshed in Eclipse.

  The command line can be broken in different commands with the semicolon (`';'`), like a unix shell. Redirection of stdin (`'<'`), stdout (`'>'`, or `'1>'`), and stderr (`'2>'`) are supported. The path for redirection is relative to the project directory, even if `workingdir` has been specified.

  ## Example with an External Plugin

  Include in the bnd build is a javagen external plugin that is useful to generate Java code based on build information. It uses a template directory with Java files. When the external plugin runs, it will use all these files to write matching Java files in the output directory, in a matching package directory. The input Java files can be prefixed with a properties header:

      ---
      foo: 1
      ---
      package foo.bar;
      class Foo {
          int foo = ${foo};
      }

  The optional header is removed and then the remainder of the file is ran through the bnd macro processor.

  If this example is used, it is necessary to add a new source folder. In Eclipse, this requires adding an entry in the `.classpath` file, in bnd it requires the modification of the `src` property.

      src=${^src},src-gen

  Assuming that the input files are in the `gen` directory, the following can be used to automatically generate the output files based on the input files.

      -generate:   \
          gen/**.java; \
              output='src-gen/' ; \
              generate='javagen -o src-gen gen/'

  ## Example with a Main Class JAR

  JFlex and CUP are popular tools to create lexers and parsers. The JARs are on Maven Central with Main-Class manifest attribute. The JFlex JAR, however, requires the `cup_runtime` JAR on the classpath.

  We can directly use these executable JARs with the `-generate` instruction.

      -generate: \
          lex/Foo.lex; \
              output      = gen-src/ \
              generate    = `jflex.Main -d lex-gen/ lex/Foo.lex'; \
              classpath   = 'de.jflex:cup_runtime;version=11b-20160615'

  Notice that we use the `maven` GAV format here to find the `cup_runtime` because these JARs are unfortunately not bundles.

  ## Writing a Command

  It is possible to create an External Plugin or a Main Class command your in the same workspace as where you apply the command. This makes it easy to develop commands interactively. The easiest way is to make an External Plugin. The support for Main-Class is mostly to support existing JAR.

  The following is an Generate external plugin that outputs “hello”:

      @ExternalPlugin(name = "hello", objectClass = Generator.class)
      public class Hello implements Generator<HelloOptions> {

          public interface HelloOptions extends Options {
              boolean upper();
              String name(String defaultName)
          }

          public Optional<String> generate(
              BuildContext context,
              HelloOptions options) throws Exception {
              String hello = "Hello " + options.name("World");
              if ( options.upper() )
                  hello = hello.toUpperCase();

              System.out.println( hello );
              return Optional.empty();
          }
      }

  The ` @ExternalPlugin` annotation creates an external plugin capability in the bundle’s manifest. The name is the name we can use as the command name. Do not use a name that has dots in it, this will then be confused with a main class command.

  The Hello class implements `Generator<HelloOptions>`. This is the type the generate code expects.

  The type parameter specifies a specification interface. This interface is used to specify the command line. A `boolean` method is a flag, and any other type is an option. The first character of the method is the name of the flag or option. For example, `boolean upper()` is a flag and has the `-u` and `--upper`. Flags can be combined. For example, if you have a flag `-a` and `-b` then you can also use `-ab`.

  Options take parameters. For example, a `String name()` option would be set as `-n World`. The method on the spec interface can optionally take an argument, this argument is used as default if the option is not used in the command line. The argument type and the return type can be different. For example, if the return type is `File`, then the parameter type can be `String` so that the returned `File` is resolved against the base directory of the build.

  Options that return `File` will resolve the input against the project directory. A Set will accept an ant file set specification like `gen/**.java`.

  The Options interface specifies a number of additional keys:

  - _arguments – A list with the arguments, flags and options removed
  - _properties – The properties that contains the flags and options

  The actual code is in the `generate(BuildContext,HelloOptions)` method. the Build Context contains useful context information.

  It is ok to write to the System.out and System.err. The output is captured and can be redirected in the command line in the standard Unix way.

  The code is expected to return an `Optional.empty()` when everything is ok. If something is wrong, an actualString can be used to explain the error. Return a non-empty fails the call and the error will be reported.

  If you the plugin source code is in the same workspace as the project using this plugin, you must make sure that the external plugin project is build before the project that uses it. You can achieve this with -dependson.

  You can take a look at the JavaGen project in the bnd build to see how an actual external plugin is made.