ILRepack: merging .NET assemblies with ILMerge syntax
Open-source alternative to ILMerge
At a glance
- What is it?
- ILRepack combines multiple .NET assemblies into one, including symbols, configuration, resources, attributes, and XML documentation. It is aimed at maintainers of .NET Framework applications who want ILMerge-compatible command syntax, but several documented compatibility options remain unimplemented.
- Who is it for?
- ILRepack suits maintainers of .NET assemblies that can be delivered as one combined output and who can account for its Cecil-based rewriting and unimplemented compatibility switches. It is a poor fit for projects that require the documented `/closed` or `/align` behavior, need unsupported Zero PeKind handling beyond IL, or cannot tolerate changing dependency resolution and assembly identity.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 52 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why gluck/il-repack replaces ILMerge
ILRepack addresses a specific packaging problem: several .NET assemblies have to become one assembly without changing the source project's normal compilation model. Its intended users are maintainers of .NET libraries and applications that need a consolidated binary, compatible command syntax, or a migration path away from discontinued ILMerge and deprecated Mono.Merge. The primary assembly supplies the output name and version, while additional assemblies are incorporated into that output.
The project positions itself as an open-source alternative rather than a new assembly format or deployment runtime. It follows ILMerge-style syntax and accepts options with `/`, `-`, or `--` prefixes. Options are case insensitive, which helps existing scripts remain readable, and response files can supply additional arguments.
Combining assemblies is not equivalent to removing every dependency from a deployment. ILRepack still needs to resolve referenced assemblies, and the help text explicitly directs users to `/lib:<path>` when an `unable to resolve assembly` error occurs. Resources, attributes, configuration files, and debug information have separate rules. A successful merge therefore depends on the inputs being compatible and on the resolver finding the assemblies needed to rewrite them.
The Cecil-based merge and output flow
ILRepack uses a slightly modified Cecil source tree, identified in the README as version 0.11.5. Based on the repository layout, the work is split between the core `ILRepack` project, the `ILRepackTool` console application, tests, integration tests, and `Mono.Cecil.overrides`. That structure points to a tool that reads .NET assemblies, rewrites their metadata through Cecil, resolves imports and references, and writes a new primary assembly.
The first input is not interchangeable with the other assemblies. The README calls it the primary assembly and says it gives the merged assembly its name and version. Output kind defaults to the primary assembly's kind, although `/target:kind` can select `library`, `exe`, or `winexe`. The output version can be replaced with `/ver:M.X.Y.Z`, and signing can be controlled through `/keyfile:<path>`, `/keycontainer:<c>`, or `/delaysign`.
Assembly visibility is another important part of the process. `/internalize` makes types from assemblies other than the primary assembly internal, except for types in the transitive closure of the public API. Narrower behavior is available through `/internalizeassembly` and exclusion files passed to `/internalize`. Adding `/renameinternalized` assigns unique names to internalized types.
The tool also defines policies for duplicate types and resources. `/allowdup` can permit all duplicate types, while `/allowdup:Type` names individual cases. `/union` merges identically named types. Resources are normally not duplicated, but `/allowduplicateresources` changes that policy. The README also lists `/selfcontainedresources` for `System.Resources.Extensions` resources that should work without that DLL beside the output.
Installing ilrepack and checking the command
The README offers NuGet and a global dotnet tool installation. For command-line use, the documented installation is the shortest route. Run this in PowerShell:
PS C:\> dotnet tool install -g dotnet-ilrepackThe README states that the installation places `ilrepack` on the dotnet tools path. Do not prefix it with `dotnet`; the documented invocation is `ilrepack`.
A sensible first operation is to inspect the interface supplied by the installed package:
PS C:\> ilrepack /helpThe help output should begin with the syntax pattern and list available switches. This does not merge any assemblies, so it does not require choosing an output or checking references. It does confirm that the tool can start and that the syntax is available on the current machine.
Users who prefer packages rather than global command-line installation are directed to NuGet. The README also exposes a direct `nupkg` download through the NuGet v2 endpoint and notes that the package can be opened as a zip file. It does not document a separate GUI installer or a standalone MSI, so those should not be assumed.
Preparing ILRepack inputs without a documented worked example
The README documents the command grammar but does not provide a complete merge command with concrete input files. That omission matters. A first merge depends on the application's own assembly paths, its target kind, signing requirements, and the directory containing referenced assemblies. Copying an invented example could also imply a layout that the project has not documented.
Before invoking a merge, identify the primary assembly and make sure its intended name and version are acceptable for the combined output. Decide which dependent assemblies belong in the result. Then locate the assemblies used during reference resolution. If the input set cannot be resolved, add the relevant search directory through the documented `/lib:<path>` option, which may be specified more than once.
Choose an output path that does not overlap carelessly with the inputs. The help text says that symbol, configuration, and documentation files will be written at the output location when those files are merged. This makes `/out:<path>` more than the destination for the binary. It defines a group of generated files.
The help also supports `@<path>.rsp` for arguments stored one per line. This is relevant for a repeatable build pipeline, but the README does not document response-file precedence or quoting rules. A build should therefore keep the response file small and reviewable rather than assuming undocumented parsing behavior.
Debug, resource, and assembly-policy trade-offs
ILRepack handles more than assembly names. The README says PDBs and MDBs can be merged, XML documentation can be included with `/xmldocs`, and configuration files can be combined unless `/skipconfig` is set. Symbols are generated by default and can be disabled with `/ndebug`. For file and line debug information stored as type or method attributes, `/index` requires a PDB.
These defaults can change build outputs. Omitting `/ndebug` may create a symbol file, while adding `/xmldocs` or allowing duplicate resources adds files or metadata. `/copyattrs` changes assembly attributes so that they are collected beyond the primary assembly. `/attr:<path>` introduces attributes from a specified assembly file, and `/allowMultiple` permits multiple attributes when the target type allows them.
The tool includes `/parallel` to use as many CPUs as possible. That option does not change the merge model documented in the README, but it is an explicit scheduling choice. `/verbose` enables more detailed output, `/log:<logfile>` enables file logging, and `/pause` stops after completion for debugging. These controls are useful when diagnosing reference or output differences, although the README provides no example log format.
`/preservetimestamp` retains the original PE timestamp. This may matter for build pipelines that inspect that value, but it is separate from reproducibility. The documentation does not claim byte-for-byte deterministic output or describe how timestamps are handled under every option.
Where ILRepack fails or is the wrong tool
The clearest limitation is explicit compatibility coverage. The syntax lists `/usefullpublickeyforreferences`, `/align`, and `/closed` as `NOT IMPLEMENTED`. The TODO section also names `/closed` and `/align` as remaining ILMerge features. A migration that depends on any of these switches cannot assume that ILRepack reproduces ILMerge behavior.
`/zeropekind` is also qualified. It allows assemblies with Zero PeKind, but the help text says that only IL will be merged. That is a narrow compatibility path rather than general support for every input associated with that metadata kind.
The README does not document automatic NuGet dependency closure, deployment probing, assembly load testing, or rollback. Those omissions matter when comparing ILRepack with ordinary .NET deployment. A single file may satisfy packaging requirements, but it does not automatically remove runtime files such as `System.Resources.Extensions` unless the relevant resource option is used.
Another risk is conflict handling. Duplicate types are denied by default, while `/allowdup`, `/allowdup:Type`, and `/union` change how conflicts are resolved. These options can produce a merged assembly that compiles without duplicate metadata errors while still changing type visibility or identity. The project provides unit and integration test projects, but the README does not state that every possible assembly combination is covered.
ILRepack versus retaining separate .NET assemblies
The practical alternative is to keep the output assemblies separate and ship each required DLL alongside the application. This approach differs from ILRepack in a fundamental way: dependencies retain their own assembly identities, file boundaries, and versions. It avoids Cecil-based merging and the associated conflict policies, at the cost of a distributed directory containing multiple binaries.
ILRepack is preferable when the requirement is specifically one combined assembly, when existing scripts already use ILMerge syntax, or when deployment policy disallows a collection of dependency DLLs. Its response files, target-kind control, signing options, symbol handling, and assembly reference search can support that packaging workflow.
Keeping assemblies separate is preferable when consumers need independent versioning, when type identity must remain stable across binaries, or when `/closed`, `/align`, and full public-key reference behavior are required. It also avoids questions about internalized types, renamed internalized types, merged configuration, and duplicate resource decisions.
A third path is migrating the build to a packaging tool designed for the application's deployment model, but the repository does not identify a specific alternative workflow or explain compatibility with ILMerge. The supported comparison here is therefore between ILRepack's combined output and conventional multi-assembly .NET deployment.
Release cadence, license, and upgrade exposure
The repository is not archived, and its last push was on 2026-09-01. Recent releases include 2.0.48 on 2026-09-01, 2.0.46 on 2026-07-10, and 2.0.45 on 2026-05-12. Those dates show recent repository activity and multiple releases within the documented period. They do not establish compatibility with every existing ILMerge command or command-line script.
ILRepack is licensed under Apache-2.0, and the repository includes a `LICENSE` file. That identifier matters when reviewing redistribution terms for a combined assembly, notices, and modifications. This is not legal advice, and the license file should govern the actual obligations.
Upgrade cost depends on the build integration. The global dotnet tool gives one command, while NuGet can fit package-based automation. Response files can preserve many arguments, but any pipeline that depends on an unimplemented switch has a known gap. Build output comparisons should include the binary, symbols, configuration, documentation, attributes, resources, and signing state. The README's changelog file and release history are the first project-specific records to inspect before changing a pinned tool version.
Editorial conclusion
ILRepack suits maintainers of .NET assemblies that can be delivered as one combined output and who can account for its Cecil-based rewriting and unimplemented compatibility switches. It is a poor fit for projects that require the documented `/closed` or `/align` behavior, need unsupported Zero PeKind handling beyond IL, or cannot tolerate changing dependency resolution and assembly identity. Before adoption, verify a representative build with `ilrepack /help`, inspect assembly resolution, compare generated symbols and configuration files, and confirm that the Apache-2.0 terms fit the distribution model.
Frequently asked questions
How do I install ILRepack as a dotnet tool?
The README documents global installation with `dotnet tool install -g dotnet-ilrepack`. After installation, invoke the tool as `ilrepack`, not `dotnet ilrepack`.
Does ILRepack support the same command syntax as ILMerge?
ILRepack uses ILMerge-style syntax and accepts options with `/`, `-`, or `--` prefixes. Options are case insensitive, but `/usefullpublickeyforreferences`, `/align`, and `/closed` are explicitly marked as not implemented.
What should I check if ILRepack cannot resolve an assembly?
The help text says to specify a directory containing the unresolved assembly with `/lib:<path>`. That option can be provided more than once when references must be resolved from several directories.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gluck-il-repack)Was this useful?