How to Build from Source
Requirements
To build Metalama, you’ll need:
- Windows
- PowerShell
- .NET SDK: check the specific version in the
global.json
file of each repository
Ensure that the .NET SDK version matches the minor version specified in the global.json
file of each repository. The rollForward
option is set to patch
, so only patch-level updates are allowed. Using an incorrect SDK version will result in build failures.
Checking out source code
1. Clone the repo with symbolic links
Metalama uses symbolic links for .editorconfig
. Ensure you enable symbolic links when cloning the repo:
git clone --config core.symlinks=true https://github.com/metalama/Metalama.git
If you encounter numerous formatting warnings during the build, it indicates that symbolic links are not properly enabled. To resolve this, enable symbolic links, delete .editorconfig
, and execute git reset --hard
.
2. Check out the right branch
For each YYYY.N
version, there are two branches with different purposes:
The release branch (e.g.,
release/YYYY.N
) corresponds to the last deployed build for this version. This is also the default branch and usually the one you want to check out. In this branch, NuGet dependencies point to the versions that have been pushed to NuGet.org for this specific version.The development branch (e.g.,
develop/YYYY.N
ordev/YYYY.N
) contains work in progress. NuGet dependencies in these branches are inconsistent; they typically point to the previous release branch. These branches must be built using a cross-repo local build, as documented below.
For more details, see our branching strategy.
Performing a local (development) build
To build Metalama, run the following script in PowerShell:
./Build.ps1 build
The packages will be placed in the artifacts/publish/private
directory.
This command creates development builds intended for use on your development machine only. Each time you run ./Build.ps1 build
, a new package version number is generated.
There are three build configurations, which you can specify using the -c
command-line option:
Debug
Release
Public
: A release build with the following differences:- The version is not suffixed with a unique build number; it matches the version specified in
eng/MainVersion.props
. - Binaries are signed. If you do not have access to the signing server, use the
--no-sign
option. - XML documentation files exclude internal APIs.
- The version is not suffixed with a unique build number; it matches the version specified in
Consuming local builds
After successfully creating a local build, you can use it in any project as follows:
Add the following code to your
Directory.Build.props
file:<Import Path="path/to/Metalama/Metalama.Imports.props" />
Use the
$(MetalamaVersion)
property to reference the version number of any package produced by this repository:<PackageReference Include="Metalama.Framework" Version="$(MetalamaVersion)" />
Run
dotnet restore
after completing a new local build.
Each time you run ./Build.ps1 build
, a new version number is generated, so you do not need to clear the cache or restart your IDE.
Running tests
To execute tests, run the following script in PowerShell:
./Build.ps1 test
Performing a local multi-repo build
Metalama consists of several repositories with dependencies between them. When building a repository, you’ll want to build dependent repositories as well.
Metalama uses PostSharp.Engineering, a custom multi-repo build front-end, to manage dependencies to other repos.
By default, dependency artifacts are downloaded from NuGet for the last build of the chosen version. When performing a multi-repo local build, you need to override the dependency source from NuGet to local
.
Here’s how to proceed:
1. Check out all repositories in the same parent directory
For the multi-repo build to work, check out all required Metalama repositories under the same parent directory. For instance:
c:\src\Metalama-2025.1\Metalama.Compiler
c:\src\Metalama-2025.1\Metalama
c:\src\Metalama-2025.1\Metalama.Samples
2. Listing the dependencies
To list the dependencies of a repo, execute:
./Build.ps1 dependencies list
For instance, the Metalama
repo has two dependencies:
PostSharp.Engineering
Metalama.Compiler
3. Change the dependency source to local
Execute the following command:
./Build.ps1 dependencies set local <id>
where <id>
is the name or the ordinal of the dependency.
For example, if you have a custom build of Metalama.Compiler
and want to build the Metalama
repo, do this in the Metalama
repo:
./Build.ps1 dependencies set local Metalama.Compiler
4. Repeat for each repository
You need to repeat this process for all repositories you want to build, starting from the root repository and iterating with the next level of dependencies:
- Configure local dependencies using
./Build.ps1 dependencies set local
. - Build this repo using
./Build.ps1 build
. - Proceed to the next repository.
Specifically, you should process the repositories in the following order:
Metalama.Compiler
Metalama
Metalama.Premium
(requires an enterprise subscription)Metalama.Samples
Metalama.Documentation
Building with Docker
We use Docker as a reference build environment to ensure all dependencies are explicit.
The Metalama build requires .NET Framework, which requires a Windows Server Core image. This is a requirement of ILRepack, one of our dependencies.
Follow these steps:
- Switch to Windows containers.
Create the
artifacts
directory:md artifacts
Create the
build-metalama
image:docker build . -t build-metalama
Run the build:
docker run -v ".\artifacts:c:/src/artifacts" build-metalama pwsh ./Build.ps1 build
- You might want to remove the
build-metalama
image.
The build artifacts are then placed into the artifacts/publish/private
directory. The logs are available under artifacts/logs
.
For details, see also the GitHub workflow .github/workflows/build-on-docker.yml
, which follows these steps in a repeatable way.