diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml
index ce8da1c3adc548003d568a4f3b531090217691e9..55089cb89fa456b167f08644af701acb7a199fbd 100644
--- a/.azure/pipelines/ci.yml
+++ b/.azure/pipelines/ci.yml
@@ -293,7 +293,9 @@ stages:
         path: artifacts/bin/ANCMv2
       - name: Windows_ANCMIISExpress_Msi
         path: artifacts/bin/AncmIISExpressV2
-        
+      - name: Windows_CompositeImages
+        path: artifacts/bin/Microsoft.AspNetCore.App.Runtime/**/Composite
+
   # Build Windows ARM
   - template: jobs/default-build.yml
     parameters:
diff --git a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj
index 5d7e9f89a0d1548cd7cf68ee50df596af886e975..fc62f8ce771f92083972ac9086f8d4a9318d7327 100644
--- a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj
+++ b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj
@@ -222,6 +222,7 @@ This package is an internal implementation of the .NET Core SDK and is not meant
     <CrossGenDependsOn Condition=" '$(CrossgenOutput)' == 'true' ">
       $(CrossGenDependsOn);
       _BatchCrossGenAssemblies;
+      _GenerateComposites;
     </CrossGenDependsOn>
     <!-- _GetBuildOutputFilesWithTfm executes in a separate context from Build, GenerateNuspec, and so on. -->
     <TargetsForTfmSpecificBuildOutput>
@@ -461,6 +462,36 @@ This package is an internal implementation of the .NET Core SDK and is not meant
           StandardOutputImportance="High" />
   </Target>
 
+  <Target Name="_GenerateComposites"
+    DependsOnTargets="_ExpandRuntimePackageRoot">
+
+    <PropertyGroup>
+      <CompositeTargetDir>$(TargetDir)Composite\</CompositeTargetDir>
+      <ManagedAssetsFullPath>$(RuntimePackageRoot)$(ManagedAssetsPackagePath)</ManagedAssetsFullPath>
+      <NativeAssetsFullPath>$(RuntimePackageRoot)$(NativeAssetsPackagePath)</NativeAssetsFullPath>
+
+      <BaseAssemblies>$(ManagedAssetsFullPath)\*.dll</BaseAssemblies>
+      <BaseAssemblies Condition="Exists('$(ManagedAssetsFullPath)') and '$(TargetOsName)' == 'win'">$(BaseAssemblies) $(NativeAssetsFullPath)\*.dll</BaseAssemblies>
+
+      <CompositeArgs>--composite</CompositeArgs>
+      <CompositeArgs>$(CompositeArgs) --targetarch:$(TargetArchitecture)</CompositeArgs>
+      <CompositeArgs>$(CompositeArgs) --targetos:$(Crossgen2TargetOs)</CompositeArgs>
+      <CompositeArgs>$(CompositeArgs) $(BaseAssemblies)</CompositeArgs>
+      <CompositeArgs>$(CompositeArgs) $(TargetDir)*.dll</CompositeArgs>
+      <CompositeArgs>$(CompositeArgs) --out:&quot;$(CompositeTargetDir)full-composite.r2r.dll&quot;</CompositeArgs>
+    </PropertyGroup>
+
+    <RemoveDir Directories="$(CompositeTargetDir)" />
+    <MakeDir Directories="$(CompositeTargetDir)" />
+
+    <ItemGroup>
+      <NativeSharedObjects Include="$(NativeAssetsFullPath)\*.so" Condition="Exists('$(NativeAssetsFullPath)') and '$(TargetOsName)' != 'win'" />
+    </ItemGroup>
+
+    <Exec Command="&quot;$(CrossgenToolPath)&quot; $(CompositeArgs)" />
+    <Copy SourceFiles="@(NativeSharedObjects)" DestinationFolder="$(CompositeTargetDir)" Condition="'$(TargetOsName)' != 'win'" />
+  </Target>
+
   <!--
   #########################################
   Targets related to creating .zip/.tar.gz