View Source mix compile.avro_code_generator (avrogen v0.8.5)
Compiler task to generate elixir code from avro schemas.
Usage
Use this task by adding it to the list of compilers in your mix.exs for your project, and add
configuration options using the avro_code_generator_opts
key in your project options.
Example configuration:
def project do
[
...
compilers: [:avro_code_generator | Mix.compilers()],
...
avro_code_generator_opts: [
paths: ["priv/schema/*.avsc"],
dest: "generated/",
scoped_embed_paths: ["priv/schema/events*.avsc"],
schema_root: "priv/schema",
module_prefix: "Avro.Generated"
]
...
]
end
Where:
paths: A list of wildcards used to locate schema files to generate code for. Each path is evaluated with Path.wildcard().
dest: Where to put the generated elixir files.
schema_root: Where to find external schema files (see notes on schema file naming below)
module_prefix: A common prefix prepended to the front of all module names.
scoped_embed_paths: the glob patterns of the files where any embedded scopes should have the generated module path contain the encompasing types.
For example, for the following schema
{ "name": "Event", "namespace": "events", "type": "record", "fields": [ { "name": "details", "type": { "name": "Subtype", "type": "record", "fields": [ ... ] } } ] }
If this file is included in the scoped_embed_paths, then the generated module for
Subtype
would be calledEvents.Event.Subtype
otherwise it would beEvents.Subtype
. This option is useful when you have naming clashes in embedded schema subtypes, or if you simply want to namespace subtypes to avoid potential future clashes
Schema File Naming
This task requires schema files to contain one schema only (nested schemas are allowed). Where
references are made to external schemas, it must be able to be found by looking for the schema by
name in the directory supplied by the schema_root
option, and the name of the schema files must
follow the specific pattern:
<schema_root>/<schemanamespace>.<SchemaName>.avsc
E.g. root/foo.bar/Baz.avsc
Generated file naming
Generated files are named like so:
<dest>/<namespace>/<SchemaName>.ex
E.g. `dest/foo/bar/baz.ex Note, the namespace is split on periods into directories, and the schema name is converted from camel case into snake case. ## Dependency Tracking In order to make the build as fast as possible, this task only generates files when it needs to, i.e. when the schemas have changed, or when the code of the avro_compiler app has changed. Each avsc file will generate one or more elixir source code file, but the content of the generated code may depend on other avsc files if the schema references external schemas from other files. For example, the dependency tree of the generated file foo/Bar.ex might look like this: foo.Bar.avsc <─┬── foo/Bar.ex foo.Baz.avsc <─┤ foo.Qux.avsc <─┘ Arrows point in the direction of the dependency, e.g. foo/Bar.ex depends on foo.Bar.avsc, foo.Baz.avsc, and foo.Qux.avsc. This means that the content of foo/Bar.ex depends on the content all three avsc files, so it must be re-generated if any of the avsc files are modified. ## Cleaning the Destination Directory In order to keep a clean dest directory, each time the task is run, the dest dir (supplied in the options) is wiped clean. The generated files are generated into a directory somewhere inside the _build directory, and then the relevant files are copied over to the dest dir. This ensures no files are left behind in the dest dir which could be picked up by the elixir compiler. Thus, it's important that this dest dir does not contain other important files as these will be wiped out. ## Manifest File This task writes a manifest file containing a the config options and a list of generated files each time it's run. The task then uses this manifest file to work out when the options have changed so it can trigger a full re-build. This manifest could also used to know which files to delete when running a clean operation, but unfortunately running mix clean when this app is in an umbrella doesn't work. This is because the code for this task is removed before the clean operation has a chance to run, which eems like a major flaw in the way tasks work). Hopefully one day the Mix devs will fix this, or we could move this app into a separate repo and make it an external dependency of stonehenge at which point the clean operation would work as mix clean does not clean external deps.