How to set up a baseline

TL;DR

This is a quick introduction to baselines with some how-tos. Not a substitute for reading the manual, but will get you going.

What is Metacello?

Metacello is a package management system for Pharo and Squeak.

For details read chapter 9 of Deep Into Pharo, especially section 3 on baselines.

For more information, take a look at Pharo’s documentation on Baselines.

What is a baseline?

A baseline is a method that specifies the packages to be loaded in a project, and the packages the project’s packages depend on.

A baseline method is usually called baseline:, has a <baseline> pragma, and belongs to a class called BaselineOf<package name> that inherits from BaselineOf ConfigurationOf subclass: #BaselineOf instanceVariableNames: '' classVariableNames: '' package: 'Metacello-Base' .

By specifying a baseline, you can automate the loading of your project with a short Metacello script.

For example, to load the gtoolkit-shorts repo and its package, you just need to run this script:

Metacello new
	baseline: 'GtoolkitShorts';
	repository: 'github://feenkcom/gtoolkit-shorts:main/src';
	load
  

How do I specify a baseline?

When you initialize a new GitHub project repository, GT's Git tool can create the baseline automatically for you. For a repository called X, it will add a package X and a package BaselineOfX, with a class BaselineOfX and a baseline: method.

Initially your package won't have any dependencies, so it will look like this example: BaselineOfGToolkitMemoryDemo>>#baseline: baseline: spec <baseline> spec for: #common do: [ spec package: 'GToolkit-Demo-Memory' ]

What do I do when I make more packages in my project?

The most important part of adding more packages to your project’s baseline is to specify the order in which they should be loaded.

You can specify this by adding a spec package: statement to the baseline for each package, and additionally specifying which packages require which others.

Here’s an example: BaselineOfGToolkitExamplesEngine>>#baseline: baseline: spec <baseline> spec for: #common do: [ spec package: 'GToolkit-Examples' ].

In this case both packages will be loaded, but GToolkit-Examples will be loaded before GToolkit-Examples-Calypso.

How do I add external dependencies to the baseline?

For each external package that you depend on, indicate the URL of the git repository it comes from.

Here’s an example showing how a package SmaCC_YAML depends on the SmaCCRuntime package, an external dependency provided by the baseline of SmaCCRuntime: BaselineOfYAMLParser>>#baseline: baseline: spec <baseline> spec for: #common do: [ spec baseline: 'SmaCCRuntime' with: [ spec repository: 'github://j-brant/SmaCC' ]; package: 'SmaCC_YAML' with: [ spec requires: 'SmaCCRuntime' ] ]

How can I find out what dependencies are missing from my baseline?

Go to the package and select the Dependencies view. Here we have the GToolkit-Demo-Memory package . Click on Dependencies to see what's missing from the baseline.

In this particular case, all the dependencies are unimportant, because they are already present in the GT build, but we'll see below how to fix that. Let's suppose these are dependencies we want to add.

First, click on one of the dependencies, say the second one, Bloc-animation. The next view will show the classes or traits used, for example BlTransformAnimation BlAnimation subclass: #BlTransformAnimation uses: TBlTransformable instanceVariableNames: 'transformation fromMatrix toMatrix isAbsolute' classVariableNames: '' package: 'Bloc-Animation-Animation' . Follow that to its package, Bloc-Animation, and then select the References view.

This will show you the baseline: method and its class and package BaselineOfBloc. Now we know that we depend on Bloc. To find the repository, we just click on the class name of the method, BaselineOfBloc BaselineOf subclass: #BaselineOfBloc instanceVariableNames: '' classVariableNames: 'PostLoaded' package: 'BaselineOfBloc' , and click on the Go to repository button.

This now shows us that the repo is git@github.com:feenkcom/Bloc.git, so we can specify spec repository: 'github://feenkcom/Bloc' in the baseline method.

But, as we said, in this case the package is already there, so we need to do something else to avoid loading it again.

How do we suppress warnings about packages that are already loaded?

The Dependencies view was designed to discover which dependencies need to be specified to load GT itself. In our case, we are creating projects within GT, so many of those packages are already there, and we don't want to load them again.

To avoid getting warnings for uninteresting depenencies, we can simply override BaselineOf>>#gtDependencyAnalysisPreloadedBaselines gtDependencyAnalysisPreloadedBaselines "Return collection of preloaded baselines. It is used by ${class:GtDependencyAnalyzerForBaseline}$, see ${method:GtDependencyAnalyzerEasy class>>#analyzeBaseline:}$" <return: #Collection> ^ GtDependencyAnalyzerEasy preloadedBaselines in our baseline.

This is done, for example, in BaselineOfGToolkitLudoDemo BaselineOf subclass: #BaselineOfGToolkitLudoDemo instanceVariableNames: '' classVariableNames: '' package: 'BaselineOfGToolkitLudoDemo' .

The baseline is simple:

BaselineOfGToolkitLudoDemo>>#baseline: baseline: spec <baseline> spec for: #common do: [ spec package: 'GToolkit-Demo-Ludo' ]

But we specify that GT is already there: BaselineOfGToolkitLudoDemo>>#gtDependencyAnalysisPreloadedBaselines gtDependencyAnalysisPreloadedBaselines ^ super gtDependencyAnalysisPreloadedBaselines copyWith: BaselineOfGToolkit

As a result, the Dependencies view is clean. (Click on Dependencies to check. It may take a few moments to compute.)