You will turn a Mono licenses.licx file into the .licenses resource your target assembly needs before it will embed licensed controls. This guide uses lc from Mono 6.8.0.105, installed here as package version 6.8.0.105+dfsg-3.6ubuntu2.
Allow about fifteen minutes. You need a shell, Mono's development tools, a license list, and the assemblies for the licensed controls named in that list. The examples only write under an explicit output directory. They do not install anything, modify a system service, or need root.
Confirm which executable will run and read its local usage text:
$ command -v lc
/usr/bin/lc
$ dpkg-query -W -f='${Package} ${Version}\n' mono-devel
mono-devel 6.8.0.105+dfsg-3.6ubuntu2
$ lc --help
Mono License Compiler
Copyright (c) 2009 by RemObjects Software
lc -c filename -t targetassembly [-i references] [-v] [-o] [-nologo]
Options:
-v, --verbose Verbose output
-t, --target=VALUE Target assembly name
-c, --complist=VALUE licx file to compile
-i, --load=VALUE Reference to load
-o, --outdir=VALUE Output directory for the .licenses file
--nologo Do not display logo
-h, -?, --help Show help
Checkpoint: The important inputs are an existing license list, a target assembly name, and an output directory that already exists. The compiler does not create a missing output directory.
Create or locate the file normally called licenses.licx. Each non-comment line names a licensed type and its assembly. The installed manual documents two forms:
# comment
Vendor.Controls.PremiumGrid, Vendor.Controls
Vendor.Controls.PremiumGrid, Vendor.Controls, Version=1.2.3.4, Culture=neutral, PublicKeyToken=0123456789abcdef
Lines beginning with # are ignored. The short assembly form needs the assembly to be loaded with -i or --load. The full form includes the locale, version and public key token, so it must match the assembly identity exactly. Do not guess these values: obtain them from the vendor assembly or the build that already succeeds.
A license list is executable build input in the broad sense: lc tries to load the named types. Treat it as reviewed source. If the file came from elsewhere, inspect it before running the command.
Run the compiler with the target assembly name that your build will eventually contain. Replace the capitalised placeholders with real paths and names:
$ mkdir -p build/licenses
$ lc --nologo \
--complist path/to/licenses.licx \
--target MyApplication.exe \
--load path/to/Vendor.Controls.dll \
--outdir build/licenses
-c, -t, -i and -o are the short equivalents. Pass every non-GAC assembly needed to resolve the types with a separate -i option. The target is the full assembly name with its file extension, not the path to the output directory.
The output filename is fixed by that target: MyApplication.exe.licenses in build/licenses. It is not the same as the input filename. --nologo suppresses the normal logo; it does not change the generated resource.
Checkpoint: Verify the expected file before handing it to the next build step:
$ test -f build/licenses/MyApplication.exe.licenses
$ printf 'resource ready: %s\n' build/licenses/MyApplication.exe.licenses
resource ready: build/licenses/MyApplication.exe.licenses
When you are checking paths or CI wiring, an empty input is a safe smoke test. It produces a valid resource container without trying to resolve a licensed type:
$ mkdir -p /tmp/lc-smoke
$ lc --nologo -c /dev/null -t SmokeTest.exe -o /tmp/lc-smoke
$ test -f /tmp/lc-smoke/SmokeTest.exe.licenses
$ printf 'resource exists: %s\n' /tmp/lc-smoke/SmokeTest.exe.licenses
resource exists: /tmp/lc-smoke/SmokeTest.exe.licenses
A zero exit status and the presence of SmokeTest.exe.licenses are the useful checks. This does not prove that a real vendor type can be resolved or that the resource is embedded by your compiler.
For more detail, add --verbose. On the installed version it reports the input, output filename and a saved message, then returns status 0 for the empty-input test:
$ lc --verbose --nologo -c /dev/null -t SmokeTest.exe -o /tmp/lc-smoke
Input file: /dev/null
Output filename: /tmp/lc-smoke/SmokeTest.exe.licenses
Saved to: /tmp/lc-smoke/SmokeTest.exe.licenses
If the output directory does not exist, lc fails while opening the resource. Create the directory first, then rerun the same command. Do not redirect the output to a path that happens to be a file.
If a type cannot be loaded, check the spelling of the namespace and type, then check its assembly identity. Add the containing DLL with --load when the assembly is not in the Global Assembly Cache. Multiple references are allowed:
$ lc --nologo \
--complist path/to/licenses.licx \
--target MyApplication.exe \
--load path/to/Vendor.Controls.dll \
--load path/to/Vendor.Common.dll \
--outdir build/licenses
$ printf 'lc exit status: %s\n' "$?"
lc exit status: 0
Capture the status immediately. A later printf or test would replace lc's status. If the command fails, keep the diagnostic output and fix the input or reference rather than ignoring the failure and embedding an old resource.
A missing reference can also be caused by a short assembly name in the license list when the runtime needs the full identity. In that case use the full line supplied by the component vendor, or make sure the exact assembly is the one loaded with --load. Do not edit a public key token or version merely to make a line look plausible.
The .licenses file is an intermediate resource. Your subsequent compiler step must embed MyApplication.exe.licenses into the assembly whose name was supplied to lc. Keep those names aligned: if the final assembly is renamed, regenerate the resource with the new target name.
The example has changed only the chosen output directory. To undo it, remove the generated file from that build directory using your normal build-clean command, or delete the disposable smoke-test directory after checking its contents. Do not remove a shared build directory without confirming that no other artefacts are stored there.
lc --help shows the expected installed compiler and options.licenses.licx names real licensed types and matching assemblies.--load.--target exactly matches the assembly that will receive the resource.<target>.licenses file exists in the selected output directory and lc returned status 0.