Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/Dataverse/PDPackage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ All `ProjectReference` items default to `ReferenceOutputAssembly=false` via `Ite

### ILRepack

`DataverseILRepack` (runs after `Build`) merges all non-Microsoft DLLs (excluding reference assemblies and `Newtonsoft.Json`) into the main output assembly using ILRepack.exe. Can be disabled with `DataversePackageRunILRepack=false` or `SkipPackageILRepack=true`.
`MergePackageAssemblyDependencies` (runs after `Build`) merges all non-Microsoft DLLs (excluding reference assemblies and `Newtonsoft.Json`) into the main output assembly using ILRepack.exe. Can be disabled with `<TalxisSkipAssemblyMerge>true</TalxisSkipAssemblyMerge>`.

### CMT package discovery

Expand Down Expand Up @@ -70,12 +70,18 @@ All `ProjectReference` items default to `ReferenceOutputAssembly=false` via `Ite

| Property | Default | Description |
|----------|---------|-------------|
| `DataversePackageRunILRepack` | `true` | Runs ILRepack after build. |
| `SkipPackageILRepack` | _(none)_ | Set to `true` to skip ILRepack. |
| `TalxisSkipAssemblyMerge` | _(unset)_ | When `true`, skips the post-build `MergePackageAssemblyDependencies` ILRepack step. |
| `ILRepackVersion` | `2.0.18` | ILRepack NuGet package version. |
| `ILRepackExe` | `$(NuGetPackageRoot)ilrepack\$(ILRepackVersion)\tools\ILRepack.exe` | Path to ILRepack.exe. |
| `ReferencedAssembliesDir` | `$(TargetDir)` | Directory scanned for assemblies to merge. |
| `DataversePackageILRepackKeyFile` | _(none)_ | Strong-name key file passed to ILRepack `/keyfile`. |
| `ILRepackKeyFile` | _(none)_ | Strong-name key file passed to ILRepack `/keyfile`. |

### Validation

| Property | Default | Description |
|----------|---------|-------------|
| `TalxisSkipPcfDependencyValidation` | _(unset)_ | When `true`, skips the `TalxisValidatePcfDependencies` check after publish. |
| `TalxisIgnoredPcfPrefixes` | _(unset)_ | Semicolon-separated PCF control prefixes to exclude from dependency validation. |

### CMT packages

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
<PropertyGroup>
<ILRepackVersion Condition="'$(ILRepackVersion)'==''">2.0.18</ILRepackVersion>
<ILRepackExe Condition="'$(ILRepackExe)'==''">$(NuGetPackageRoot)ilrepack\$(ILRepackVersion)\tools\ILRepack.exe</ILRepackExe>
<DataversePackageRunILRepack Condition="'$(DataversePackageRunILRepack)'==''">true</DataversePackageRunILRepack>
<ReferencedAssembliesDir Condition="'$(ReferencedAssembliesDir)'==''">$(TargetDir)</ReferencedAssembliesDir>
<ReferencedAssembliesDir>$([System.Text.RegularExpressions.Regex]::Replace('$(ReferencedAssembliesDir)', '[\\/]+$', ''))</ReferencedAssembliesDir>
</PropertyGroup>

<Target Name="DataverseILRepack" AfterTargets="Build" Condition="'$(SkipPackageILRepack)' != 'true' and '$(DataversePackageRunILRepack)'!='false'">
<!-- Worker target: merges non-Microsoft DLLs into the main assembly via
ILRepack CLI. Excludes reference assemblies and Newtonsoft.Json. -->
<Target Name="MergePackageAssemblyDependencies">
<PropertyGroup>
<BuildedAssembly>$(TargetPath)</BuildedAssembly>
<_KeyFileSwitch Condition="Exists('$(DataversePackageILRepackKeyFile)')">/keyfile:"$(DataversePackageILRepackKeyFile)"</_KeyFileSwitch>
<_KeyFileSwitch Condition="Exists('$(ILRepackKeyFile)')">/keyfile:"$(ILRepackKeyFile)"</_KeyFileSwitch>
<_ILRepackCommand Condition="$([MSBuild]::IsOSPlatform('Windows'))">"$(ILRepackExe)"</_ILRepackCommand>
<_ILRepackCommand Condition="!$([MSBuild]::IsOSPlatform('Windows'))">mono "$(ILRepackExe)"</_ILRepackCommand>
</PropertyGroup>
Expand All @@ -31,12 +32,19 @@
<OtherAssemblies Include="$(TargetDir)*.dll" Exclude="@(AssembliesToExclude)" />
</ItemGroup>

<Message Text="ILRepack command: $(_ILRepackCommand)" Importance="High" />
<Message Text="Merging into: $(BuildedAssembly)" Importance="High" />
<Message Text="OtherAssemblies: @(OtherAssemblies)" Importance="High" />
<Message Text="MergePackageAssemblyDependencies: $(_ILRepackCommand)" Importance="High" />
<Message Text="MergePackageAssemblyDependencies: merging into $(BuildedAssembly)" Importance="High" />
<Message Text="MergePackageAssemblyDependencies: @(OtherAssemblies)" Importance="High" />

<Message Text="ILRepack skipped: no additional assemblies to merge." Importance="High" Condition="'@(OtherAssemblies)'==''" />
<Message Text="MergePackageAssemblyDependencies: no additional assemblies to merge." Importance="High" Condition="'@(OtherAssemblies)'==''" />

<Exec Command="$(_ILRepackCommand) /lib:&quot;$(ReferencedAssembliesDir)&quot; /target:library /parallel $(_KeyFileSwitch) /out:&quot;$(BuildedAssembly)&quot; &quot;$(BuildedAssembly)&quot; @(OtherAssemblies,' ')" Condition="'@(OtherAssemblies)'!=''" />
</Target>

<!-- Lifecycle hook: auto-wires the worker after Build.
Opt out: <TalxisSkipAssemblyMerge>true</TalxisSkipAssemblyMerge>. -->
<Target Name="_TalxisPdPackageAutoMergeHook"
AfterTargets="Build"
Condition="'$(TalxisSkipAssemblyMerge)' != 'true'"
DependsOnTargets="MergePackageAssemblyDependencies" />
</Project>
6 changes: 4 additions & 2 deletions src/Dataverse/Plugin/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TALXIS.DevKit.Build.Dataverse.Plugin

MSBuild integration for Dataverse plugin assembly projects. Configures Visual Studio project type GUIDs for CRM plugin development, brings in `Microsoft.CrmSdk.CoreAssemblies` and `Microsoft.PowerApps.MSBuild.Plugin`, applies automatic Git-based versioning, and exposes metadata targets that allow Solution projects to discover and integrate plugin assemblies during build.
MSBuild integration for Dataverse plugin assembly projects. Configures Visual Studio project type GUIDs for CRM plugin development, brings in `Microsoft.CrmSdk.CoreAssemblies` and `Microsoft.PowerApps.MSBuild.Plugin`, applies automatic Git-based versioning, merges referenced managed dependencies into the output DLL via ILRepack so the Dataverse sandbox can load all required types from a single assembly, and exposes metadata targets that allow Solution projects to discover and integrate plugin assemblies during build.

## Installation

Expand All @@ -25,6 +25,7 @@ The package sets `ProjectType` to `Plugin` and configures `ProjectTypeGuids` for
### Build-time targets

- **TalxisBeforeBuild** (runs before `BeforeBuild`) -- executes `GenerateVersionNumber` followed by `ApplyPluginVersionNumber` to set `AssemblyVersion`, `FileVersion`, `Version`, and `PackageVersion` from Git.
- **MergeAssemblyDependencies** (runs after `Build`) -- uses [ILRepack](https://github.com/gluck/il-repack) to merge every managed DLL that landed in `$(OutDir)` into the main plugin assembly, so the Dataverse sandbox (which loads a single assembly) can resolve all referenced types without sibling DLLs. Sandbox-provided assemblies are skipped: `Microsoft.Xrm.Sdk*`, `Microsoft.Crm.Sdk.Proxy`, `Newtonsoft.Json`, `System.*`, `mscorlib`, `netstandard`. Idempotent — always reads the raw compiler output from `$(IntermediateOutputPath)` so the target can safely re-run within the same Solution build. Merged types keep their original public names (`Internalize=false`) to preserve Dataverse's reflection-based plugin type detection. Disable per-project with `<TalxisSkipAssemblyMerge>true</TalxisSkipAssemblyMerge>`.

### Integration targets

Expand All @@ -44,10 +45,11 @@ These targets are called by `TALXIS.DevKit.Build.Dataverse.Solution` when it dis
| `PluginTargetFramework` | `$(TargetFramework)` or `net462` | Target framework used to locate the compiled plugin DLL. |
| `PluginPublishFolderName` | `publish` | Publish folder name under `bin\<Configuration>\<TFM>\`. |
| `PluginAssemblyId` | _(auto-generated)_ | Explicit GUID for the plugin assembly metadata; a new GUID is generated if empty. |
| `TalxisSkipAssemblyMerge` | _(unset)_ | When `true`, skips the post-build `MergeAssemblyDependencies` ILRepack step. |

## Related Packages

- **Depends on**: `TALXIS.DevKit.Build.Dataverse.Tasks`, `Microsoft.PowerApps.MSBuild.Plugin`, `Microsoft.CrmSdk.CoreAssemblies`
- **Depends on**: `TALXIS.DevKit.Build.Dataverse.Tasks`, `Microsoft.PowerApps.MSBuild.Plugin`, `Microsoft.CrmSdk.CoreAssemblies`, `ILRepack.Lib.MSBuild.Task`
- **Consumed by**: `TALXIS.DevKit.Build.Dataverse.Solution` projects via `ProjectReference`


Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<dependency id="Microsoft.PowerApps.MSBuild.Plugin" version="$MicrosoftPowerAppsTargetsVersion$" />
<dependency id="Microsoft.CrmSdk.CoreAssemblies" version="[9.0.2.60]" />
<dependency id="Microsoft.NETFramework.ReferenceAssemblies" version="[1.0.3]" />
<dependency id="ILRepack.Lib.MSBuild.Task" version="[2.0.44.2]" />
<dependency id="TALXIS.DevKit.Build.Dataverse.Tasks" version="$Version$" />
</dependencies>
</metadata>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- No-op. Plugin.targets sets $(ILRepackTargetsFile) to this file to
suppress ILRepack.Lib.MSBuild.Task's own AfterTargets="Build" target. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
<PackageReference Include="Microsoft.CrmSdk.CoreAssemblies" Version="9.0.2.*" PrivateAssets="All" />
<PackageReference Include="Microsoft.PowerApps.MSBuild.Plugin" Version="1.*" PrivateAssets="All" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.*" PrivateAssets="All" />
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="[2.0.44.2]" PrivateAssets="All" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@
</ItemGroup>
</Target>

<!-- Auto-wire the MergeAssemblyDependencies worker target (defined in Tasks).
Opt out: <TalxisSkipAssemblyMerge>true</TalxisSkipAssemblyMerge>. -->
<PropertyGroup>
<!-- Override unconditionally: ILRepack.Lib.MSBuild.Task loads earlier in
alphabetical import order and pre-sets this to its own default, so a
Condition="==''" guard would never fire. -->
<ILRepackTargetsFile>$(MSBuildThisFileDirectory)DisableILRepackAutoMerge.targets</ILRepackTargetsFile>
</PropertyGroup>

<Target Name="_TalxisPluginAutoMergeHook"
AfterTargets="Build"
Condition="'$(TalxisSkipAssemblyMerge)' != 'true'"
DependsOnTargets="MergeAssemblyDependencies" />

<Target Name="GetPluginAssemblyInfo"
Returns="@(_PluginAssemblyInfo)"
Condition="'$(ProjectType)'=='Plugin'">
Expand Down
5 changes: 5 additions & 0 deletions src/Dataverse/Solution/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ The package sets `ProjectType` to `Solution` and imports `Microsoft.PowerApps.MS

### Validation

| Property | Default | Description |
|----------|---------|-------------|
| `TalxisSkipDuplicateGuidValidation` | _(unset)_ | When `true`, skips the `TalxisValidateDuplicateGuids` check during build. |
| `TalxisSkipQuickFindValidation` | _(unset)_ | When `true`, skips the `TalxisValidateQuickFindViews` check during build. |

Schema validation via `ValidateSolutionComponentSchema` is **not wired automatically** -- invoke it manually (e.g. `dotnet build -t:ValidateSolutionComponentSchema`). No skip property is needed.

## Related Packages
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<!-- Pure callable worker: merges $(OutDir)*.dll into $(AssemblyName).dll
via ILRepack, skipping sandbox-provided assemblies. Reads raw output
from $(IntermediateOutputPath) so it's safe to re-run.
No AfterTargets — Plugin/WorkflowActivity packages wire it up. -->
<Target Name="MergeAssemblyDependencies">
<PropertyGroup>
<_TalxisMergePrimaryRaw>$(IntermediateOutputPath)$(AssemblyName).dll</_TalxisMergePrimaryRaw>
<_TalxisMergeOutputDll>$(OutDir)$(AssemblyName).dll</_TalxisMergeOutputDll>
</PropertyGroup>
<ItemGroup>
<_TalxisMergeAll Include="$(OutDir)*.dll" />
<_TalxisMergePrimary Include="@(_TalxisMergeAll)"
Condition=" '%(Filename)%(Extension)' == '$(AssemblyName).dll' " />
<_TalxisMergeDeps Include="@(_TalxisMergeAll)" Exclude="@(_TalxisMergePrimary)" />
<!-- Drop sandbox-provided assemblies — merging would clash with platform versions at runtime. -->
<_TalxisMergeDeps Remove="@(_TalxisMergeDeps)"
Condition=" '%(Filename)' == 'mscorlib'
Or '%(Filename)' == 'netstandard'
Or '%(Filename)' == 'Newtonsoft.Json'
Or '%(Filename)' == 'Microsoft.Xrm.Sdk'
Or $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Xrm.Sdk.'))
Or '%(Filename)' == 'Microsoft.Crm.Sdk.Proxy'
Or $([System.String]::Copy('%(Filename)').StartsWith('System.')) " />
</ItemGroup>

<Message Importance="high"
Text="MergeAssemblyDependencies: merging into $(AssemblyName).dll -> @(_TalxisMergeDeps->'%(Filename)', ', ')"
Condition=" '@(_TalxisMergeDeps)' != '' " />
<Message Importance="high"
Text="MergeAssemblyDependencies: nothing to merge"
Condition=" '@(_TalxisMergeDeps)' == '' " />

<!-- Internalize=false: keep public type names so Dataverse reflection
still finds IPlugin / CodeActivity types. -->
<!-- LibraryPath needs the absolute path to OutDir so Mono.Cecil's
resolver finds referenced assemblies regardless of CWD. -->
<ILRepack Condition=" '@(_TalxisMergeDeps)' != '' "
Parallel="true"
Internalize="false"
InputAssemblies="$(_TalxisMergePrimaryRaw);@(_TalxisMergeDeps)"
OutputFile="$(_TalxisMergeOutputDll)"
KeyFile="$(AssemblyOriginatorKeyFile)"
LibraryPath="$([System.IO.Path]::GetFullPath('$(OutDir)'))" />
</Target>

</Project>
6 changes: 4 additions & 2 deletions src/Dataverse/WorkflowActivity/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TALXIS.DevKit.Build.Dataverse.WorkflowActivity

MSBuild integration for Dynamics 365 custom workflow activity assembly projects. Mirrors the Plugin package pattern: configures Visual Studio project type GUIDs, applies automatic Git-based versioning, and exposes metadata targets that allow Solution projects to discover and integrate workflow activity assemblies during build.
MSBuild integration for Dynamics 365 custom workflow activity assembly projects. Mirrors the Plugin package pattern: configures Visual Studio project type GUIDs, applies automatic Git-based versioning, merges referenced managed dependencies into the output DLL via ILRepack so the Dataverse sandbox can load all required types from a single assembly, and exposes metadata targets that allow Solution projects to discover and integrate workflow activity assemblies during build.

## Installation

Expand All @@ -25,6 +25,7 @@ The package sets `ProjectType` to `WorkflowActivity` and configures `ProjectType
### Build-time targets

- **TalxisBeforeBuild** (runs before `BeforeBuild`) -- executes `GenerateVersionNumber` followed by `ApplyPluginVersionNumber` to set `AssemblyVersion`, `FileVersion`, `Version`, and `PackageVersion` from Git.
- **MergeAssemblyDependencies** (runs after `Build`) -- uses [ILRepack](https://github.com/gluck/il-repack) to merge every managed DLL that landed in `$(OutDir)` into the main workflow activity assembly, so the Dataverse sandbox (which loads a single assembly) can resolve all referenced types without sibling DLLs. Sandbox-provided assemblies are skipped: `Microsoft.Xrm.Sdk*`, `Microsoft.Crm.Sdk.Proxy`, `Newtonsoft.Json`, `System.*`, `mscorlib`, `netstandard`. Idempotent — always reads the raw compiler output from `$(IntermediateOutputPath)` so the target can safely re-run within the same Solution build. Merged types keep their original public names (`Internalize=false`) to preserve Dataverse's reflection-based detection of `CodeActivity` subclasses. Disable per-project with `<TalxisSkipAssemblyMerge>true</TalxisSkipAssemblyMerge>`.

### Integration targets

Expand All @@ -44,10 +45,11 @@ These targets are called by `TALXIS.DevKit.Build.Dataverse.Solution` when it dis
| `WorkflowActivityTargetFramework` | `$(TargetFramework)` or `net462` | Target framework used to locate the compiled workflow activity DLL. |
| `WorkflowActivityPublishFolderName` | `publish` | Publish folder name under `bin\<Configuration>\<TFM>\`. |
| `WorkflowActivityAssemblyId` | _(auto-generated)_ | Explicit GUID for the workflow activity assembly metadata; a new GUID is generated if empty. |
| `TalxisSkipAssemblyMerge` | _(unset)_ | When `true`, skips the post-build `MergeAssemblyDependencies` ILRepack step. |

## Related Packages

- **Depends on**: `TALXIS.DevKit.Build.Dataverse.Tasks`, `Microsoft.PowerApps.MSBuild.Plugin`, `Microsoft.CrmSdk.CoreAssemblies`
- **Depends on**: `TALXIS.DevKit.Build.Dataverse.Tasks`, `Microsoft.PowerApps.MSBuild.Plugin`, `Microsoft.CrmSdk.CoreAssemblies`, `ILRepack.Lib.MSBuild.Task`
- **Consumed by**: `TALXIS.DevKit.Build.Dataverse.Solution` projects via `ProjectReference`


Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<dependency id="Microsoft.PowerApps.MSBuild.Plugin" version="$MicrosoftPowerAppsTargetsVersion$" />
<dependency id="Microsoft.CrmSdk.CoreAssemblies" version="[9.0.2.60]" />
<dependency id="Microsoft.NETFramework.ReferenceAssemblies" version="[1.0.3]" />
<dependency id="ILRepack.Lib.MSBuild.Task" version="[2.0.44.2]" />
<dependency id="TALXIS.DevKit.Build.Dataverse.Tasks" version="$Version$" />
</dependencies>
</metadata>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- No-op. WorkflowActivity.targets sets $(ILRepackTargetsFile) to this file
to suppress ILRepack.Lib.MSBuild.Task's own AfterTargets="Build" target. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.WorkflowActivity.props" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.WorkflowActivity.props')" />

<ItemGroup>
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="[2.0.44.2]" PrivateAssets="All" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@
</ItemGroup>
</Target>

<!-- Auto-wire the MergeAssemblyDependencies worker target (defined in Tasks).
Opt out: <TalxisSkipAssemblyMerge>true</TalxisSkipAssemblyMerge>. -->
<PropertyGroup>
<!-- Override unconditionally: ILRepack.Lib.MSBuild.Task loads earlier in
alphabetical import order and pre-sets this to its own default, so a
Condition="==''" guard would never fire. -->
<ILRepackTargetsFile>$(MSBuildThisFileDirectory)DisableILRepackAutoMerge.targets</ILRepackTargetsFile>
</PropertyGroup>

<Target Name="_TalxisWorkflowActivityAutoMergeHook"
AfterTargets="Build"
Condition="'$(TalxisSkipAssemblyMerge)' != 'true'"
DependsOnTargets="MergeAssemblyDependencies" />

<Target Name="GetWorkflowActivityAssemblyInfo"
Returns="@(_WorkflowActivityAssemblyInfo)"
Condition="'$(ProjectType)'=='WorkflowActivity'">
Expand Down