Home / Alt manpages / sgen(1)

  • sgen(1)
  • User command
  • linux

Generate Faster Mono XML Serializers with sgen

sgen pre-generates the XML serializer that XmlSerializer would otherwise build at runtime, trading a slow first request for a build-time step. You will finish with a generated Assembly.XmlSerializers.dll sitting beside your Mono assembly, ready to load. This guide uses sgen from Mono 6.8.0.105 on the local system, whose tool reports runtime version 4.0.30319.42000. Allow about fifteen minutes if your assembly is already built. You need a readable .NET assembly, a shell, and the mono-devel package. The commands write files to a chosen directory; nothing here installs or registers anything system-wide.

Checkpoint

Keep the original assembly and pick an empty output directory before generating. Do not point the command at a directory holding a serializer you have not backed up. Without the force option, sgen refuses to overwrite existing output, which is the safe default.

1. Confirm the installed tool

Check the command is available and note the package version:

$ command -v sgen
/usr/bin/sgen
$ dpkg-query -W -f='${Package} ${Version}\n' mono-devel
mono-devel 6.8.0.105+dfsg-3.6ubuntu2
$ sgen --help
Mono Xml Serializer Generator Tool
Mono version 4.0.30319.42000

The installed help output is brief, so lean on the manpage for what the options actually mean. The relevant inputs are an assembly and, where needed, its referenced assemblies. The tool writes a separate serializer assembly rather than touching the input DLL.

2. Build or locate the input assembly

sgen needs a compiled assembly, not a C# source file. For a quick self-contained test, build a small library in a working directory:

$ mkdir -p ~/sgen-demo
$ cd ~/sgen-demo
$ mcs -target:library -out:Widget.dll Widget.cs

Use your own existing DLL if you have one. A minimal Widget class with a public Name property is enough to demonstrate the command, but the case that actually matters in production is an assembly containing the serializable types your application uses. Check the path before continuing:

$ test -r Widget.dll && file Widget.dll
Widget.dll: PE32 executable (DLL) ...

If that check fails, stop and fix the path or read permission. Do not run the generator as root just to force a badly located file to work.

3. Generate the serializer in a separate directory

Create a destination and pass the assembly with the long option form: the colon sits between the option and its value here, not a space.

$ mkdir generated
$ sgen --nologo --assembly:Widget.dll --out:generated
Generated assembly: Widget.XmlSerializers.dll
$ find generated -maxdepth 1 -type f -printf '%f\n'
Widget.XmlSerializers.dll

The default output directory is the current one, but an explicit --out keeps generated artefacts away from source and build files. The output name comes from the input assembly, so Orders.dll gets you Orders.XmlSerializers.dll.

Checkpoint

Verify the output exists and is non-empty:

$ test -s generated/Widget.XmlSerializers.dll && echo 'serializer generated'
serializer generated

A success message only tells you generation completed. Keep this DLL paired with the matching input assembly and test it through the application that will actually load it.

4. Select a type only when you need to

By default, sgen processes the whole assembly. Use --type when you need one runtime type named explicitly:

$ mkdir selected
$ sgen --nologo --assembly:Widget.dll --type:Widget --out:selected
Generated assembly: Widget.XmlSerializers.dll

The value is the runtime type name, not a source filename. For a namespaced class, use its fully qualified name, such as Example.Models.Order. If the type cannot be resolved or the assembly cannot be loaded, fix the assembly and dependency paths first; do not assume a generated DLL is valid just because a file landed on disk.

5. Handle references and compiler options carefully

If the target assembly refers to another assembly the generator cannot resolve, supply that dependency with --reference:

$ sgen --nologo \
    --assembly:Orders.dll \
    --reference:Contracts.dll \
    --out:generated
  • Repeat the option for each referenced assembly your build actually needs.
  • Match build versions. Keep dependency files from the same build as the target; mixing versions can produce a serializer that compiles but does not match the application at runtime.
  • --compiler passes options through to the generation step. Treat it as a build-system setting, not a place for shell syntax, and quote values by the command's own argument rules.
  • --debug asks the compiler for debug information.
  • --keep keeps temporary generated source for inspection, handy when diagnosing a failed build but liable to leave extra files behind.

6. Avoid accidental replacement

Running the same generation command twice does not silently replace the serializer. It errors out instead:

$ sgen --nologo --assembly:Widget.dll --out:generated
Cannot generate assembly '.../generated/Widget.XmlSerializers.dll' because it already exist. Use /force option to overwrite the existing assembly

That protection earns its keep: overwriting a known-good serializer can break a build or leave you unsure which generated file was actually tested. Generate to a new directory first, compare or test the result, then update the build output the normal way.

Use --force only when replacement is deliberate:

$ sgen --nologo --force \
    --assembly:Widget.dll \
    --out:generated

Warning

Force overwrites the existing generated assembly. Back it up or generate into a new directory if you might need to roll back. If a forced run produces a bad result, restore the backup or replace the destination with the previously verified file from version control: sgen has no undo command.

7. Keep scripts quiet without hiding failures

--silent suppresses normal progress output; --verbose asks for more. Neither changes the generated serializer. In a script, preserve and check the exit status:

if sgen --silent --assembly:Widget.dll --out:generated; then
    test -s generated/Widget.XmlSerializers.dll
else
    status=$?
    printf 'sgen failed with status %s\n' "$status" &2
    exit "$status"
fi

Do not treat silence as success, and do not ignore a non-zero exit status. Add a separate file check too, since a later build step can remove or replace the generated file.

8. Know the boundary of this tool

--proxytypes is listed in the installed manpage but marked not supported yet, so do not build a workflow around it. The tool generates serializer classes for the older Mono 2.0 profile family the manual describes; exact runtime and compiler compatibility still depends on the target assembly and the rest of your build. Test the generated DLL with the actual application and framework profile that will load it.

Nothing here needs elevated privileges. Avoid sudo: it can leave generated files root-owned and mask an ordinary path or permission mistake. If your build directory is not writable, pick a writable working directory or fix ownership through your normal administration process.

Done means

  • Versions identified: sgen and the mono-devel package.
  • Input assembly untouched and readable by the invoking user.
  • Matching output generated: a *.XmlSerializers.dll in a deliberate output directory.
  • Existing output protected unless --force was an explicit, backed-up decision.
  • Extras used only when needed: references, type selection and compiler settings supplied only when the assembly required them.
  • Generated file tested for existence, then run through the actual application build.