Skip to content

MS Build and Plugins

Dirkster99 edited this page May 8, 2020 · 8 revisions

Overview

The initial build process based on MS Build is due to a contribution from Jason

The file ".build/Edi.targets" consumes the resulting files from the Edi.sln solution and builds the final output directory structure. The final build process of the Edi.exe application ensures that:

  • required binary files for the Edi Application are stored in the application's target folder and

  • every required plug-in file is stored in the "Plugins" sub-folder.

    The ".build/Edi.targets" is included in the solution file Edi.sln for display purposes:

  Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", "{2A4570D1-7926-4ED0-9D06-C4005887577F}"
    ProjectSection(SolutionItems) = preProject
      .build\Edi.targets = .build\Edi.targets
    EndProjectSection
  EndProject

This Edi.targets file is evaluated for a project (only), if there is a corresponding <import ...> tag in a *.csproj file.

The project that defines the main executable Edi\Edi\Edi.csproj contains a:

  • <Import Project="$(SolutionDir).build\Edi.targets" /> statement and the PropertyGroup and **Target **tag below the import statement copy the contents of these targets into the Debug/Release output folder.
  <PropertyGroup>
    <StartAction>Program</StartAction>
    <StartProgram>$(SolutionDir)$(Configuration)\$(TargetFileName)</StartProgram>
    <StartWorkingDirectory>$(SolutionDir)$(Configuration)</StartWorkingDirectory>
  </PropertyGroup>
  <Target Name="AfterBuild">
    <ItemGroup>
      <!-- Specify locally dependent binaries -->
      <!-- EdiProjectFiles Include="$(SolutionDir)02_Libs\00_bin\AvalonDock\AvalonDock.Themes.Expression.dll" / -->
    </ItemGroup>
    <!-- Copy binaries not yet avalabile as nuget but as local binary only -->
    <Copy SourceFiles="@(EdiProjectFiles)" DestinationFolder="$(TargetDir)" SkipUnchangedFiles="false" />
  </Target>
  • defines the variable: <DeployApplication>true</DeployApplication>

The projects:

  • MiniUML\Plugins\src\MiniUML.Plugins.UmlClassDiagram\MiniUML.Plugins.UmlClassDiagram.csproj
  • Tools\Log4NetTools\Log4NetTools.csproj

that define a Plugin contain a:

  • <Import Project="$(SolutionDir).build\Edi.targets" /> statement and
  • define the variable: <DeployPlugin>true</DeployPlugin>

Details of the .build/Edi.targets file

The '.build/Edi.targets' file defines the directories:

  • $(ApplicationTargetDir)
  • $(PluginsTargetDir)

to define the target location of the application's binaries and Plugin files.

The variables:

  • $(DeployPlugin)
  • $(DeployApplication)

are defined with the default value false to ensure that only projects that set these to true are handled as plugin or main application.

  • The BuildDependsOn tags ensure that the corresponding projects are build when either variable $(DeployPlugin) or $(DeployApplication) is set to true.

  • The statements at <Target Name="..."> ...</Target> copies the resulting binary files from each project's build process into the corresponding target (application or plugin) folder

Future Changes

This section explains the required changes to build the resulting application with additional plugin projects.

Adjusting the *.csproj file

Adding or removing a plugin requires 2 items in the corresponding *.csproj file:

The definition of the DeployPlugin variable:

  <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    ...
    <DeployPlugin>true</DeployPlugin>
  </PropertyGroup>
  ...

  - and an additional import of the `Edi.targets` file at
  ...
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(SolutionDir).build\Edi.targets" />
  ...

Adjusting the Code to have MEF load the required Plugin

The PluginCatalog via its InnerModuleInfoLoader is responsible for loading any class decorated with the [ModuleExport(typeof(MEFLoadSomeRandomTool))] tag. And the [ImportingConstructor] attribute defines the interface between the Plugin and the services supplied by MEF at run-time.

This class decoration together with the correct service interfaces is responsible for adding any plugin into the existing run-time service infa-structure. Here is an example from the MEFLoadLog4NetTools class:

Class Decoration:

[ModuleExport(typeof(MEFLoadLog4NetTools))]
public class MEFLoadLog4NetTools : IModule
{

Constructor Decoration:

[ImportingConstructor]
public MEFLoadLog4NetTools(IAvalonDockLayoutViewModel avLayout,
                           IToolWindowRegistry toolRegistry,
                           ISettingsManager settingsManager,
                           IDocumentTypeManager documentTypeManager)
{
  this.mAvLayout = avLayout;
  this.mToolRegistry = toolRegistry;
  this.mSettingsManager = settingsManager;
  this.mDocumentTypeManager = documentTypeManager;
}

void IModule.Initialize()
{
   // Initialize new plugin here ...
}

References

This section lists relevant links to understand MS Build details described on this page:

This section lists relevant MEF links: