In this week's build of Elements, we've shipped a very first tentative part of what, eventually, will become the/an official package manager for EBuild in general, and for Elements in particular.

What's the Goal of a Package Manager?

The main idea of a package manager is that your project can seamlessly reference existing Elements libraries, whether created by you yourself, or open source projects created by others. With a single entry in your project, as simple as a regular or project reference, you can tell EBuild to automatically pull down the dependency(ies) you need, and make them available to your project.

In the first phase, we're focusing on this. We're not worrying about discovery of available packages (yet), or about a fancy UI to add new dependencies to your project; we're focusing on the build side, and getting the stricture and infrastructure for that sorted out.

What's an EBuild Package Reference

An EBuild Package Reference works like a mixture of Project References and the existing NuGet or Gradle Package References we already support for .NET and Android/Java – with a few differences.

A reference is specified using the <RemoteProjectReference> tag, and like the other package references, it includes a name, and an (optional) version/branch.

The name of the package is the complete URL to a .elements project file in a remote git repository, currently limited to GitHub. The version can be "*", or a valid branch name, tag name or commit ID for the repository. "*" or lack of version will refer to the master branch of the repository.

EBuild Packages are stored in source, and will be cloned/pulled and compiled locally as part of your projects build (an important difference to NuGet and Gradle references, which ship as binaries). The resolving of this happens in a pre-built step that runs as part of each EBuild build – the same step that also verifies local project references and determines the build order for a solution based on the project reference tree.

In fact, you can think of an EBuild Package Reference as a project reference – to a project that doesn't exist on your local hard-drive but only in git, until the build pulls it down. And in fact, once pulled, the reference will look like a Project Reference to the rest of the build process, and handled the exact same way.

An Example

Let's say in your project you want to make use of the small cross-platform SQLite wrapper we've created, available at https://github.com/remobjects/ElementsSQLite. Right now, this wrapper supports .NET and Cocoa/macOS (because we created it for internal use in Fire and Water). Note that this is a project and repository that pre-dates any thought about EBuild Packages – and it still 'just works' with it!

Adding this to your project is dead easy: Simply add the following project item to your project file, next to the other references:

<RemoteProjectReference Include="github.com/remobjects/ElementsSQLite/SQLite.elements:*">
    <Private>True>
</RemoteProjectReference>

Next time you build your project, you will see that EBuild automatically goes out amd clones the project to a location shared/cached between all projects on your system, injects a Project Reference into your actual project, and then builds both projects in the proper order.

It's that easy.

Platforms

EBuild Package References can work for any platform (or combination of platforms) supported by the referenced project. This can be by using separate projects for each platform and referencing the correct .elements file from the repo, or (as in the example above) having as single multi-target project file that supports two or more platforms.

If you are planning to make multi-platform libraries available to users, you should strongly consider using the second option, as a single multi-target project will make it easier to use the package from projects that themselves are multi-target.

And of course EBuild Package References can be seamlessly mixed with regular references, local project references and NuGet/Gradle package references.