diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
index bf473414890f6c..610ae55338e49d 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
@@ -29,7 +29,7 @@
     ============================================================
   -->
   <Target Name="NativeCompile"
-          DependsOnTargets="_ComputeAssembliesToCompileToNative;LinkNative">
+          DependsOnTargets="_ComputeAssembliesToCompileToNative;LinkNative;CreateShimExes">
 
     <ItemGroup>
       <ResolvedFileToPublish Remove="@(_IlcManagedInputAssemblies)" />
@@ -41,6 +41,24 @@
         <RelativePath>$(NativeBinaryPrefix)$(TargetName)$(NativeBinaryExt)</RelativePath>
         <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
       </ResolvedFileToPublish>
+      <ResolvedFileToPublish Include="@(_AggregateExecutableShim)" Condition="'$(_AggregateExecutable)' == 'true'">
+        <RelativePath>%(_AggregateExecutableShim.RelativePath)</RelativePath>
+        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+      </ResolvedFileToPublish>
+      <ResolvedFileToPublish Include="@(_AggregateExecutableShimSymbol)"
+                             Condition="'$(_AggregateExecutable)' == 'true' and '$(CopyOutputSymbolsToPublishDirectory)' == 'true' and '$(NativeSymbolExt)' != '.dSYM' and Exists('%(_AggregateExecutableShimSymbol.Identity)')">
+        <RelativePath>%(_AggregateExecutableShimSymbol.RelativePath)</RelativePath>
+        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+      </ResolvedFileToPublish>
+      <_AggregateExecutableShimSymbolRecursivePath Include="%(_AggregateExecutableReferencePath.ShimSymbol)/**/*"
+                                             Condition="'$(_AggregateExecutable)' == 'true' and '$(CopyOutputSymbolsToPublishDirectory)' == 'true' and '$(NativeSymbolExt)' == '.dSYM' and Exists('%(_AggregateExecutableReferencePath.ShimSymbol)')">
+        <RelativePath>%(_AggregateExecutableReferencePath.AssemblyName)$(NativeSymbolExt)/%(RecursiveDir)%(Filename)%(Extension)</RelativePath>
+      </_AggregateExecutableShimSymbolRecursivePath>
+      <ResolvedFileToPublish Include="@(_AggregateExecutableShimSymbolRecursivePath)"
+                             Condition="'$(_AggregateExecutable)' == 'true' and '$(CopyOutputSymbolsToPublishDirectory)' == 'true'">
+        <RelativePath>%(_AggregateExecutableShimSymbolRecursivePath.RelativePath)</RelativePath>
+        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+      </ResolvedFileToPublish>
     </ItemGroup>
 
     <PropertyGroup Condition="'$(CopyOutputSymbolsToPublishDirectory)' == 'true'">
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
index 6ec997d6c237ae..8c429c993788bb 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
@@ -239,15 +239,15 @@ The .NET Foundation licenses this file to you under the MIT license.
 
     <ItemGroup>
       <LinkerArg Include="-gz=zlib" Condition="'$(CompressSymbols)' != 'false'" />
-      <LinkerArg Include="-fuse-ld=$(LinkerFlavor)" Condition="'$(LinkerFlavor)' != ''" />
+      <LinkerArg Include="-fuse-ld=$(LinkerFlavor)" Condition="'$(LinkerFlavor)' != ''" Shim="true" />
       <LinkerArg Include="@(NativeLibrary)" />
-      <LinkerArg Include="--sysroot=&quot;$(SysRoot)&quot;" Condition="'$(SysRoot)' != '' and '$(_IsApplePlatform)' != 'true'" />
-      <LinkerArg Include="-isysroot &quot;$(SysRoot)&quot;" Condition="'$(SysRoot)' != '' and '$(_IsApplePlatform)' == 'true'" />
-      <LinkerArg Include="--target=$(TargetTriple)" Condition="'$(TargetTriple)' != ''" />
-      <LinkerArg Include="-g" Condition="$(NativeDebugSymbols) == 'true'" />
+      <LinkerArg Include="--sysroot=&quot;$(SysRoot)&quot;" Condition="'$(SysRoot)' != '' and '$(_IsApplePlatform)' != 'true'" Shim="true" />
+      <LinkerArg Include="-isysroot &quot;$(SysRoot)&quot;" Condition="'$(SysRoot)' != '' and '$(_IsApplePlatform)' == 'true'" Shim="true" />
+      <LinkerArg Include="--target=$(TargetTriple)" Condition="'$(TargetTriple)' != ''" Shim="true" />
+      <LinkerArg Include="-g" Condition="$(NativeDebugSymbols) == 'true'" Shim="true" />
       <LinkerArg Include="-Wl,--strip-debug" Condition="$(NativeDebugSymbols) != 'true' and '$(_IsApplePlatform)' != 'true'" />
       <LinkerArg Include="-Wl,-install_name,&quot;$(SharedLibraryInstallName)&quot;" Condition="'$(_IsApplePlatform)' == 'true' and '$(NativeLib)' == 'Shared'" />
-      <LinkerArg Include="-Wl,--build-id=sha1" Condition="'$(_IsApplePlatform)' != 'true'" />
+      <LinkerArg Include="-Wl,--build-id=sha1" Condition="'$(_IsApplePlatform)' != 'true'" Shim="true" />
       <LinkerArg Include="-Wl,--as-needed" Condition="'$(_IsApplePlatform)' != 'true'" />
       <LinkerArg Include="-Wl,-e,0x0" Condition="'$(NativeLib)' == 'Shared' and '$(_IsApplePlatform)' != 'true'" />
       <LinkerArg Include="-pthread" Condition="'$(_IsApplePlatform)' != 'true'" />
@@ -263,10 +263,10 @@ The .NET Foundation licenses this file to you under the MIT license.
       <LinkerArg Include="-pie -Wl,-pie" Condition="'$(_IsApplePlatform)' != 'true' and '$(NativeLib)' == '' and '$(StaticExecutable)' != 'true' and '$(PositionIndependentExecutable)' != 'false'" />
       <LinkerArg Include="-Wl,-no-pie" Condition="'$(_IsApplePlatform)' != 'true' and '$(NativeLib)' == '' and '$(StaticExecutable)' != 'true' and '$(PositionIndependentExecutable)' == 'false'" />
       <!-- binskim warning BA3010 The GNU_RELRO segment is missing -->
-      <LinkerArg Include="-Wl,-z,relro" Condition="'$(_IsApplePlatform)' != 'true'" />
+      <LinkerArg Include="-Wl,-z,relro" Condition="'$(_IsApplePlatform)' != 'true'" Shim="true" />
       <!-- binskim warning BA3011 The BIND_NOW flag is missing -->
-      <LinkerArg Include="-Wl,-z,now" Condition="'$(_IsApplePlatform)' != 'true'" />
-      <LinkerArg Include="-Wl,-z,stack-size=$(IlcDefaultStackSize)" Condition="'$(IlcDefaultStackSize)' != ''" />
+      <LinkerArg Include="-Wl,-z,now" Condition="'$(_IsApplePlatform)' != 'true'" Shim="true" />
+      <LinkerArg Include="-Wl,-z,stack-size=$(IlcDefaultStackSize)" Condition="'$(IlcDefaultStackSize)' != ''" Shim="true" />
       <!-- this workaround can be deleted once the minimum supported glibc version
            (runtime's official build machine's glibc version) is at least 2.33
            see https://github.com/bminor/glibc/commit/99468ed45f5a58f584bab60364af937eb6f8afda -->
@@ -376,4 +376,60 @@ The .NET Foundation licenses this file to you under the MIT license.
       <DsymUtilOptions>$(DsymUtilOptions) --minimize</DsymUtilOptions>
     </PropertyGroup>
   </Target>
+
+  <Target Name="CreateShimExes"
+          Condition="'$(_AggregateExecutable)' == 'true'"
+          DependsOnTargets="LinkNative;WriteAggregateExecutableShimRspFiles"
+          Inputs="$(NativeBinary);@(_AggregateExecutableReferencePath->'%(ShimSource)');@(_AggregateExecutableReferencePath->'%(ShimCompileLinkRspFile)')"
+          Outputs="@(_AggregateExecutableShim);@(_AggregateExecutableShimSymbol)">
+
+    <Exec Command="&quot;$(CppLinker)&quot; @&quot;%(_AggregateExecutableReferencePath.ShimCompileLinkRspFile)&quot;" />
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(NativeDebugSymbols)' == 'true' and '$(_IsApplePlatform)' != 'true'"
+          Command="&quot;$(ObjCopyName)&quot; --only-keep-debug &quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot; &quot;%(_AggregateExecutableReferencePath.ShimBinary)$(NativeSymbolExt)&quot;" />
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(_IsApplePlatform)' != 'true'"
+          Command="&quot;$(ObjCopyName)&quot; --strip-debug --strip-unneeded &quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot;" />
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(NativeDebugSymbols)' == 'true' and '$(_IsApplePlatform)' != 'true'"
+          Command="&quot;$(ObjCopyName)&quot; --add-gnu-debuglink=&quot;%(_AggregateExecutableReferencePath.ShimBinary)$(NativeSymbolExt)&quot; &quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot;" />
+    <Exec Condition="'$(StripSymbols)' == 'true' and '$(_IsApplePlatform)' == 'true'"
+          IgnoreStandardErrorWarningFormat="true"
+          Command="
+            dsymutil $(DsymUtilOptions) &quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot; &amp;&amp;
+            strip -no_code_signature_warning -x &quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot;" />
+  </Target>
+
+  <Target Name="WriteAggregateExecutableShimRspFiles"
+          Condition="'$(_AggregateExecutable)' == 'true'"
+          DependsOnTargets="LinkNative">
+
+    <ItemGroup>
+      <_AggregateExecutableReferencePath>
+        <ShimSourceCode><![CDATA[extern int %(_AggregateExecutableReferencePath.EntryPointSymbol)(int, char**);
+
+int main(int argc, char** argv)
+{
+    return %(_AggregateExecutableReferencePath.EntryPointSymbol)(argc, argv);
+}
+]]></ShimSourceCode>
+      </_AggregateExecutableReferencePath>
+    </ItemGroup>
+
+    <ItemGroup>
+      <_AggregateExecutableShimCompilerAndLinkerArg Include="@(LinkerArg)" Condition="'%(LinkerArg.Shim)' == 'true'" />
+      <_AggregateExecutableShimCompilerAndLinkerArg Include="-Wl,-rpath,'$ORIGIN'" Condition="'$(_IsApplePlatform)' != 'true'" />
+      <_AggregateExecutableShimCompilerAndLinkerArg Include="-Wl,-rpath,@executable_path" Condition="'$(_IsApplePlatform)' == 'true'" />
+
+      <!-- binskim warning BA3001 PIE disabled on executable -->
+      <_AggregateExecutableShimCompilerAndLinkerArg Include="-pie -Wl,-pie" Condition="'$(_IsApplePlatform)' != 'true' and '$(StaticExecutable)' != 'true' and '$(PositionIndependentExecutable)' != 'false'" />
+      <!-- binskim error BA3003: The stack protector was not found -->
+      <_AggregateExecutableShimCompilerAndLinkerArg Include="-fstack-protector-strong" />
+
+      <_AggregateExecutableShimNativeLibraryArg Include="-L&quot;$(NativeOutputPath)&quot;" Condition="'$(_IsApplePlatform)' != 'true'" />
+      <_AggregateExecutableShimNativeLibraryArg Include="-l:$(NativeBinaryPrefix)$(TargetName)$(NativeBinaryExt)" Condition="'$(_IsApplePlatform)' != 'true'" />
+      <_AggregateExecutableShimNativeLibraryArg Include="&quot;$(NativeBinary)&quot;" Condition="'$(_IsApplePlatform)' == 'true'" />
+    </ItemGroup>
+
+    <MakeDir Directories="$(NativeIntermediateOutputPath);$(NativeOutputPath)" />
+    <WriteLinesToFile File="%(_AggregateExecutableReferencePath.ShimSource)" Lines="$([MSBuild]::Escape('%(_AggregateExecutableReferencePath.ShimSourceCode)'))" Overwrite="true" Encoding="utf-8" WriteOnlyWhenDifferent="true" />
+    <WriteLinesToFile File="%(_AggregateExecutableReferencePath.ShimCompileLinkRspFile)" Lines="@(_AggregateExecutableShimCompilerAndLinkerArg);&quot;%(_AggregateExecutableReferencePath.ShimSource)&quot;;@(_AggregateExecutableShimNativeLibraryArg);-o;&quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot;" Overwrite="true" Encoding="utf-8" WriteOnlyWhenDifferent="true" />
+  </Target>
 </Project>
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
index 25fb0b7fae9205..e7cea22fcf0442 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
@@ -15,6 +15,7 @@ The .NET Foundation licenses this file to you under the MIT license.
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <CppLinker>link</CppLinker>
+    <CppCompiler>cl</CppCompiler>
     <CppLibCreator>lib</CppLibCreator>
     <ObjectSuffix>.obj</ObjectSuffix>
     <LibrarySuffix>.lib</LibrarySuffix>
@@ -93,35 +94,35 @@ The .NET Foundation licenses this file to you under the MIT license.
       <LinkerArg Condition="'$(NativeLib)' == 'Shared'" Include="/DLL" />
       <LinkerArg Include="@(NativeLibrary->'&quot;%(Identity)&quot;')" />
       <LinkerArg Include="@(SdkNativeLibrary->'&quot;%(Identity)&quot;')" />
-      <LinkerArg Include="/NOLOGO /MANIFEST:NO" />
+      <LinkerArg Include="/NOLOGO /MANIFEST:NO" Shim="true" />
       <LinkerArg Condition="$(IlcMergeSections) != 'false'" Include="/MERGE:.managedcode=.text /MERGE:hydrated=.bss" />
-      <LinkerArg Condition="$(NativeDebugSymbols) == 'true'" Include="/DEBUG" />
+      <LinkerArg Condition="$(NativeDebugSymbols) == 'true'" Include="/DEBUG" Shim="true" />
       <!-- The runtime is not compatible with jump stubs inserted by incremental linking. -->
       <LinkerArg Include="/INCREMENTAL:NO" />
       <LinkerArg Condition="'$(NativeLib)' == '' and '$(LinkerSubsystem)' != ''" Include="/SUBSYSTEM:$(LinkerSubsystem)" />
       <LinkerArg Condition="'$(NativeLib)' == ''" Include="/ENTRY:$(EntryPointSymbol) /NOEXP /NOIMPLIB /STACK:$(IlcDefaultStackSize)" />
       <LinkerArg Include="/NATVIS:&quot;$(MSBuildThisFileDirectory)NativeAOT.natvis&quot;" />
-      <LinkerArg Condition="'$(ControlFlowGuard)' == 'Guard'" Include="/guard:cf" />
-      <LinkerArg Condition="'$(_targetArchitecture)' == 'x86'" Include="/safeseh" />
+      <LinkerArg Condition="'$(ControlFlowGuard)' == 'Guard'" Include="/guard:cf" Shim="true" />
+      <LinkerArg Condition="'$(_targetArchitecture)' == 'x86'" Include="/safeseh" Shim="true" />
       <!-- Do not warn if someone declares UnmanagedCallersOnly with an entrypoint of 'DllGetClassObject' and similar -->
       <LinkerArg Include="/IGNORE:4104" />
       <!-- Opt into CETCOMPAT by default. -->
-      <LinkerArg Condition="'$(CETCompat)' != 'false' and '$(_targetArchitecture)' == 'x64'" Include="/CETCOMPAT" />
+      <LinkerArg Condition="'$(CETCompat)' != 'false' and '$(_targetArchitecture)' == 'x64'" Include="/CETCOMPAT" Shim="true" />
       <!-- Allow user to opt out. -->
-      <LinkerArg Condition="'$(CETCompat)' == 'false' and '$(_targetArchitecture)' == 'x64'" Include="/CETCOMPAT:NO" />
+      <LinkerArg Condition="'$(CETCompat)' == 'false' and '$(_targetArchitecture)' == 'x64'" Include="/CETCOMPAT:NO" Shim="true" />
       <!-- Enable EHCONT if CET is not disabled and CFG is enabled. -->
-      <LinkerArg Condition="'$(CETCompat)' != 'false' and '$(_targetArchitecture)' == 'x64' and '$(ControlFlowGuard)' == 'Guard'" Include="/guard:ehcont"/>
+      <LinkerArg Condition="'$(CETCompat)' != 'false' and '$(_targetArchitecture)' == 'x64' and '$(ControlFlowGuard)' == 'Guard'" Include="/guard:ehcont" Shim="true" />
     </ItemGroup>
 
     <ItemGroup Condition="!Exists('$(IlcSdkPath)debugucrt.txt')">
       <!-- Force ucrt to be dynamically linked for release runtime -->
-      <LinkerArg Include="/NODEFAULTLIB:libucrt.lib" />
-      <LinkerArg Include="/DEFAULTLIB:ucrt.lib" />
+      <LinkerArg Include="/NODEFAULTLIB:libucrt.lib" Shim="true" />
+      <LinkerArg Include="/DEFAULTLIB:ucrt.lib" Shim="true" />
     </ItemGroup>
 
     <ItemGroup Condition="'$(Configuration)' != 'Debug'">
-      <LinkerArg Include="/OPT:REF" />
-      <LinkerArg Include="/OPT:ICF" />
+      <LinkerArg Include="/OPT:REF" Shim="true" />
+      <LinkerArg Include="/OPT:ICF" Shim="true" />
     </ItemGroup>
 
     <Exec Condition="'$(IlcUseEnvironmentalTools)' != 'true'" Command="&quot;$(MSBuildThisFileDirectory)findvcvarsall.bat&quot; $(_targetArchitecture)"
@@ -136,10 +137,63 @@ The .NET Foundation licenses this file to you under the MIT license.
 
     <PropertyGroup Condition="'$(_VCVarsAllFound)' == '0'">
       <_CppToolsDirectory>$(_FindVCVarsallOutput.Split(`#`)[0])</_CppToolsDirectory>
+      <CppCompiler>$(_CppToolsDirectory)cl.exe</CppCompiler>
       <CppLinker>$(_CppToolsDirectory)link.exe</CppLinker>
       <CppLibCreator>$(_CppToolsDirectory)lib.exe</CppLibCreator>
     </PropertyGroup>
 
     <Error Condition="'$(_VCVarsAllFound)' == '1'" Text="Platform linker not found. Ensure you have all the required prerequisites documented at https://aka.ms/nativeaot-prerequisites, in particular the Desktop Development for C++ workload in Visual Studio. For ARM64 development also install C++ ARM64 build tools." />
   </Target>
+
+  <Target Name="CreateShimExes"
+          Condition="'$(_AggregateExecutable)' == 'true'"
+          DependsOnTargets="LinkNative;WriteAggregateExecutableShimRspFiles"
+          Inputs="$(NativeImportLibrary);@(_AggregateExecutableReferencePath->'%(ShimSource)');@(_AggregateExecutableReferencePath->'%(ShimCompileRspFile)');@(_AggregateExecutableReferencePath->'%(ShimLinkRspFile)')"
+          Outputs="@(_AggregateExecutableShim);@(_AggregateExecutableShimSymbol)">
+
+    <MakeDir Directories="$(NativeIntermediateOutputPath);$(NativeOutputPath)" />
+    <Exec Command="&quot;$(CppCompiler)&quot; @&quot;%(_AggregateExecutableReferencePath.ShimCompileRspFile)&quot;" />
+    <Exec Command="&quot;$(CppLinker)&quot; @&quot;%(_AggregateExecutableReferencePath.ShimLinkRspFile)&quot;" />
+  </Target>
+
+  <Target Name="WriteAggregateExecutableShimRspFiles"
+          Condition="'$(_AggregateExecutable)' == 'true'"
+          DependsOnTargets="LinkNative">
+
+    <ItemGroup>
+      <_AggregateExecutableReferencePath>
+        <ShimSourceCode><![CDATA[extern int __stdcall %(_AggregateExecutableReferencePath.EntryPointSymbol)(int, unsigned short**);
+
+int wmain(int argc, unsigned short** argv)
+{
+    return %(_AggregateExecutableReferencePath.EntryPointSymbol)(argc, argv);
+}
+]]></ShimSourceCode>
+        <ShimPdbLinkerArg Condition="'$(NativeDebugSymbols)' == 'true'">/PDB:"%(_AggregateExecutableReferencePath.ShimSymbol)"</ShimPdbLinkerArg>
+      </_AggregateExecutableReferencePath>
+    </ItemGroup>
+
+    <ItemGroup>
+      <_AggregateExecutableShimCompilerArg Include="/nologo" />
+      <_AggregateExecutableShimCompilerArg Include="/c" />
+      <_AggregateExecutableShimCompilerArg Include="/MT" />
+      <_AggregateExecutableShimCompilerArg Condition="'$(NativeDebugSymbols)' == 'true'" Include="/Z7" />
+      <_AggregateExecutableShimCompilerArg Condition="'$(ControlFlowGuard)' == 'Guard'" Include="/guard:cf" />
+
+      <!-- binskim BA2007 X was compiled at too low a warning level -->
+      <_AggregateExecutableShimCompilerArg Include="/W4" />
+      <!-- binskim BA2026 X is a Windows PE that wasn't compiled with recommended Security Development Lifecycle (SDL) checks -->
+      <_AggregateExecutableShimCompilerArg Include="/sdl" />
+
+      <_AggregateExecutableShimLinkerArg Include="@(LinkerArg)" Condition="'%(LinkerArg.Shim)' == 'true'" />
+      <_AggregateExecutableShimLinkerArg Include="/ENTRY:wmainCRTStartup" />
+      <_AggregateExecutableShimLinkerArg Include="/STACK:$(IlcDefaultStackSize)" />
+      <_AggregateExecutableShimLinkerArg Include="@(AdditionalNativeLibraryDirectories->'/LIBPATH:&quot;%(Identity)&quot;')" />
+    </ItemGroup>
+
+    <MakeDir Directories="$(NativeIntermediateOutputPath);$(NativeOutputPath)" />
+    <WriteLinesToFile File="%(_AggregateExecutableReferencePath.ShimSource)" Lines="$([MSBuild]::Escape('%(_AggregateExecutableReferencePath.ShimSourceCode)'))" Overwrite="true" Encoding="utf-8" WriteOnlyWhenDifferent="true" />
+    <WriteLinesToFile File="%(_AggregateExecutableReferencePath.ShimCompileRspFile)" Lines="@(_AggregateExecutableShimCompilerArg);&quot;%(_AggregateExecutableReferencePath.ShimSource)&quot;;/Fo&quot;%(_AggregateExecutableReferencePath.ShimObject)&quot;" Overwrite="true" Encoding="utf-8" WriteOnlyWhenDifferent="true" />
+    <WriteLinesToFile File="%(_AggregateExecutableReferencePath.ShimLinkRspFile)" Lines="&quot;%(_AggregateExecutableReferencePath.ShimObject)&quot;;&quot;$(NativeImportLibrary)&quot;;/OUT:&quot;%(_AggregateExecutableReferencePath.ShimBinary)&quot;;/SUBSYSTEM:%(_AggregateExecutableReferencePath.ShimLinkerSubsystem);%(_AggregateExecutableReferencePath.ShimPdbLinkerArg);@(_AggregateExecutableShimLinkerArg)" Overwrite="true" Encoding="utf-8" WriteOnlyWhenDifferent="true" />
+  </Target>
 </Project>
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
index 9c961cbee95b34..ce0f7292f4c76d 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -82,6 +82,11 @@ The .NET Foundation licenses this file to you under the MIT license.
 
     <NativeObject>$(NativeIntermediateOutputPath)$(TargetName)$(NativeObjectExt)</NativeObject>
     <NativeBinary>$(NativeOutputPath)$(NativeBinaryPrefix)$(TargetName)$(NativeBinaryExt)</NativeBinary>
+    <NativeImportLibrary Condition="'$(NativeImportLibrary)' == '' and '$(_targetOS)' == 'win' and '$(NativeLib)' == 'Shared'">$(NativeOutputPath)$(NativeBinaryPrefix)$(TargetName)$(LibFileExt)</NativeImportLibrary>
+    <_LinkNativeOutputs>$(NativeBinary)</_LinkNativeOutputs>
+    <_LinkNativeOutputs Condition="'$(_targetOS)' == 'win' and '$(NativeLib)' == 'Shared' and '$(NativeImportLibrary)' != ''">$(NativeBinary);$(NativeImportLibrary)</_LinkNativeOutputs>
+    <NativeExecutableExt Condition="'$(NativeExecutableExt)' == '' and '$(_targetOS)' == 'win'">.exe</NativeExecutableExt>
+    <NativeExecutableExt Condition="'$(NativeExecutableExt)' == ''"></NativeExecutableExt>
     <IlcExportUnmanagedEntrypoints Condition="'$(IlcExportUnmanagedEntrypoints)' == '' and '$(NativeLib)' == 'Shared'">true</IlcExportUnmanagedEntrypoints>
     <ExportsFile Condition="$(ExportsFile) == '' and '$(BuildingFrameworkLibrary)' != 'true'">$(NativeIntermediateOutputPath)$(TargetName)$(ExportsFileExt)</ExportsFile>
 
@@ -100,7 +105,7 @@ The .NET Foundation licenses this file to you under the MIT license.
   <PropertyGroup Condition="'$(IlcCompileDependsOn)'=='' and '$(NativeCompilationDuringPublish)' != 'false'">
     <IlcCompileDependsOn Condition="'$(BuildingFrameworkLibrary)' != 'true'">Compile;ComputeIlcCompileInputs</IlcCompileDependsOn>
     <IlcCompileDependsOn Condition="'$(IlcMultiModule)' == 'true' and '$(BuildingFrameworkLibrary)' != 'true'">$(IlcCompileDependsOn);BuildFrameworkLib</IlcCompileDependsOn>
-    <IlcCompileDependsOn>$(IlcCompileDependsOn);SetupOSSpecificProps</IlcCompileDependsOn>
+    <IlcCompileDependsOn>$(IlcCompileDependsOn);ComputeAggregateExecutableInputs;SetupOSSpecificProps</IlcCompileDependsOn>
   </PropertyGroup>
 
   <ItemGroup Condition="$(IlcSystemModule) == ''">
@@ -168,6 +173,46 @@ The .NET Foundation licenses this file to you under the MIT license.
     </ItemGroup>
   </Target>
 
+  <Target Name="ComputeAggregateExecutableInputs"
+          DependsOnTargets="ResolveReferences">
+
+    <ItemGroup>
+      <_AggregateExecutableReferencePath Include="@(ReferencePath)"
+                                   Condition="'%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference' and '%(ReferencePath.IncludeInAggregateExecutable)' == 'true'">
+        <AssemblyName>%(ReferencePath.Filename)</AssemblyName>
+        <SanitizedAssemblyName>__AggregateExeShim_$([System.Text.RegularExpressions.Regex]::Replace('%(ReferencePath.Filename)', '[^A-Za-z0-9_]', '_'))</SanitizedAssemblyName>
+        <AssemblyNameHash>$([MSBuild]::StableStringHash('%(ReferencePath.Filename)', 'Sha256'))</AssemblyNameHash>
+      </_AggregateExecutableReferencePath>
+      <_AggregateExecutableReferencePath>
+        <EntryPointSymbol>_AggregateExeMain_%(SanitizedAssemblyName)_%(AssemblyNameHash)</EntryPointSymbol>
+        <ShimLinkerSubsystem Condition="'%(_AggregateExecutableReferencePath.LinkerSubsystem)' != ''">%(_AggregateExecutableReferencePath.LinkerSubsystem)</ShimLinkerSubsystem>
+        <ShimLinkerSubsystem Condition="'%(_AggregateExecutableReferencePath.LinkerSubsystem)' == '' and '$(LinkerSubsystem)' != ''">$(LinkerSubsystem)</ShimLinkerSubsystem>
+        <ShimLinkerSubsystem Condition="'%(_AggregateExecutableReferencePath.LinkerSubsystem)' == '' and '$(LinkerSubsystem)' == ''">CONSOLE</ShimLinkerSubsystem>
+        <ShimSource>$(NativeIntermediateOutputPath)%(AssemblyName).aggregateexe.c</ShimSource>
+        <ShimObject>$(NativeIntermediateOutputPath)%(AssemblyName).aggregateexe$(NativeObjectExt)</ShimObject>
+        <ShimCompileRspFile>$(NativeIntermediateOutputPath)%(AssemblyName).aggregateexe.cl.rsp</ShimCompileRspFile>
+        <ShimLinkRspFile>$(NativeIntermediateOutputPath)%(AssemblyName).aggregateexe.link.rsp</ShimLinkRspFile>
+        <ShimCompileLinkRspFile>$(NativeIntermediateOutputPath)%(AssemblyName).aggregateexe.rsp</ShimCompileLinkRspFile>
+        <ShimBinary>$(NativeOutputPath)%(AssemblyName)$(NativeExecutableExt)</ShimBinary>
+        <ShimSymbol>$(NativeOutputPath)%(AssemblyName)$(NativeSymbolExt)</ShimSymbol>
+      </_AggregateExecutableReferencePath>
+      <_AggregateExecutableShim Include="%(_AggregateExecutableReferencePath.ShimBinary)">
+        <RelativePath>%(_AggregateExecutableReferencePath.AssemblyName)$(NativeExecutableExt)</RelativePath>
+      </_AggregateExecutableShim>
+      <_AggregateExecutableShimSymbol Include="%(_AggregateExecutableReferencePath.ShimSymbol)" Condition="'$(NativeDebugSymbols)' == 'true'">
+        <RelativePath>%(_AggregateExecutableReferencePath.AssemblyName)$(NativeSymbolExt)</RelativePath>
+      </_AggregateExecutableShimSymbol>
+    </ItemGroup>
+
+    <PropertyGroup>
+      <_AggregateExecutable Condition="'$(NativeLib)' == 'Shared' and '@(_AggregateExecutableReferencePath)' != ''">true</_AggregateExecutable>
+    </PropertyGroup>
+
+    <Error Condition="'@(_AggregateExecutableReferencePath)' != '' and '$(OutputType)' != 'Library'" Text="IncludeInAggregateExecutable requires OutputType=Library." />
+    <Error Condition="'@(_AggregateExecutableReferencePath)' != '' and '$(NativeLib)' != 'Shared'" Text="IncludeInAggregateExecutable requires NativeLib=Shared." />
+    <Error Condition="'@(_AggregateExecutableReferencePath)' != '' and '$(EnablePreviewFeatures)' != 'true'" Text="IncludeInAggregateExecutable requires EnablePreviewFeatures=true." />
+  </Target>
+
   <!--
     BuildFrameworkLib is invoked before IlcCompile in multi-module builds to
     produce the shared framework library on demand
@@ -286,6 +331,8 @@ The .NET Foundation licenses this file to you under the MIT license.
 
       <!-- Export the managed entry point if building a native library in custom main mode -->
       <IlcArg Condition="'$(NativeLib)' == 'Shared' and '$(CustomNativeMain)' == 'true'" Include="--export-dynamic-symbol:__managed__Main" />
+      <IlcArg Condition="'@(_AggregateExecutableReferencePath)' != ''" Include="@(_AggregateExecutableReferencePath->'--aggregateexe:%(AssemblyName)=%(EntryPointSymbol)')" />
+      <IlcArg Condition="'@(_AggregateExecutableReferencePath)' != ''" Include="@(_AggregateExecutableReferencePath->'--export-dynamic-symbol:%(EntryPointSymbol)')" />
 
       <IlcArg Condition="'$(_InstrumentReachability)' == 'true'" Include="--reachabilityinstrument" />
       <IlcArg Condition="'$(_InstrumentReachability)' == 'true'" Include="--feature:Internal.Runtime.CompilerHelpers.ReachabilityInstrumentationSupport=true" />
@@ -329,13 +376,14 @@ The .NET Foundation licenses this file to you under the MIT license.
 
   <Target Name="LinkNative"
       Inputs="$(NativeObject);@(NativeLibrary)"
-      Outputs="$(NativeBinary)"
+      Outputs="$(_LinkNativeOutputs)"
       DependsOnTargets="$(LinkNativeDependsOn)">
 
     <ItemGroup>
       <CustomLinkerArg Include="&quot;$(NativeObject)&quot;" />
       <CustomLinkerArg Include="-o &quot;$(NativeBinary)&quot;" Condition="'$(_targetOS)' != 'win'" />
       <CustomLinkerArg Include="/OUT:&quot;$(NativeBinary)&quot;" Condition="'$(_targetOS)' == 'win'" />
+      <CustomLinkerArg Include="/IMPLIB:&quot;$(NativeImportLibrary)&quot;" Condition="'$(_targetOS)' == 'win' and '$(NativeLib)' == 'Shared' and '$(NativeImportLibrary)' != ''" />
       <CustomLinkerArg Include="/DEF:&quot;$(ExportsFile)&quot;" Condition="'$(_targetOS)' == 'win' and $(ExportsFile) != ''" />
       <CustomLinkerArg Include="/LIBPATH:&quot;%(AdditionalNativeLibraryDirectories.Identity)&quot;" Condition="'$(_targetOS)' == 'win' and '@(AdditionalNativeLibraryDirectories->Count())' &gt; 0" />
       <CustomLinkerArg Include="-exported_symbols_list &quot;$(ExportsFile)&quot;" Condition="'$(_IsApplePlatform)' == 'true' and '$(ExportsFile)' != ''" />
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MainMethodRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MainMethodRootProvider.cs
index 75c6de55579702..8152a0f6eae661 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MainMethodRootProvider.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MainMethodRootProvider.cs
@@ -21,13 +21,15 @@ public class MainMethodRootProvider : ICompilationRootProvider
         /// </summary>
         public const string ManagedEntryPointMethodName = "__managed__Main";
 
-        private EcmaModule _module;
-        private IReadOnlyCollection<MethodDesc> _libraryInitializers;
-        private bool _generateLibraryAndModuleInitializers;
+        private readonly EcmaModule _module;
+        private readonly string _entryPointName;
+        private readonly IReadOnlyCollection<MethodDesc> _libraryInitializers;
+        private readonly bool _generateLibraryAndModuleInitializers;
 
-        public MainMethodRootProvider(EcmaModule module, IReadOnlyCollection<MethodDesc> libraryInitializers, bool generateLibraryAndModuleInitializers)
+        public MainMethodRootProvider(EcmaModule module, IReadOnlyCollection<MethodDesc> libraryInitializers, bool generateLibraryAndModuleInitializers, string entryPointName = null)
         {
             _module = module;
+            _entryPointName = entryPointName ?? ManagedEntryPointMethodName;
             _libraryInitializers = libraryInitializers;
             _generateLibraryAndModuleInitializers = generateLibraryAndModuleInitializers;
         }
@@ -41,7 +43,7 @@ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
             TypeDesc owningType = _module.GetGlobalModuleType();
             var startupCodeMain = new StartupCodeMainMethod(owningType, mainMethod, _libraryInitializers, _generateLibraryAndModuleInitializers);
 
-            rootProvider.AddCompilationRoot(startupCodeMain, "Startup Code Main Method", new Utf8String(ManagedEntryPointMethodName));
+            rootProvider.AddCompilationRoot(startupCodeMain, $"Startup Code Main Method for {_module.Assembly.GetName().Name}", new Utf8String(_entryPointName));
         }
     }
 }
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/StartupCodeMainMethod.Sorting.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/StartupCodeMainMethod.Sorting.cs
index 59d582451c80ae..0cf90ba02ec626 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/StartupCodeMainMethod.Sorting.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/StartupCodeMainMethod.Sorting.cs
@@ -2,7 +2,6 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using Internal.TypeSystem;
-using Debug = System.Diagnostics.Debug;
 
 namespace Internal.IL.Stubs.StartupCode
 {
@@ -12,9 +11,7 @@ public partial class StartupCodeMainMethod
 
         protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
         {
-            // Should be a singleton
-            Debug.Assert(this == other);
-            return 0;
+            return comparer.Compare(OwningType, other.OwningType);
         }
 
         private partial class MainMethodWrapper
@@ -23,9 +20,7 @@ private partial class MainMethodWrapper
 
             protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
             {
-                // Should be a singleton
-                Debug.Assert(this == other);
-                return 0;
+                return comparer.Compare(OwningType, other.OwningType);
             }
         }
     }
diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
index 91547f5749adc0..875bbeaf73b9e7 100644
--- a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
+++ b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs
@@ -44,6 +44,8 @@ internal sealed class ILCompilerRootCommand : RootCommand
             new("--nativelib") { Description = "Compile as static or shared library" };
         public Option<bool> SplitExeInitialization { get; } =
             new("--splitinit") { Description = "Split initialization of an executable between the library entrypoint and a main entrypoint" };
+        public Option<string[]> AggregateExeLibrary { get; } =
+            new("--aggregateexe") { Description = "Specify aggregate executable library entrypoint modules (format: 'assemblyName=MainEntryPointName')" };
         public Option<string> ExportsFile { get; } =
             new("--exportsfile") { Description = "File to write exported symbol and method definitions" };
         public Option<bool> ExportUnmanagedEntryPoints { get; } =
@@ -204,6 +206,7 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler")
             Options.Add(UseDwarf5);
             Options.Add(NativeLib);
             Options.Add(SplitExeInitialization);
+            Options.Add(AggregateExeLibrary);
             Options.Add(ExportsFile);
             Options.Add(ExportDynamicSymbols);
             Options.Add(ExportUnmanagedEntryPoints);
diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs
index b0f39723c9ce70..3e3c9a3eb002a9 100644
--- a/src/coreclr/tools/aot/ILCompiler/Program.cs
+++ b/src/coreclr/tools/aot/ILCompiler/Program.cs
@@ -239,7 +239,24 @@ public int Run()
                     compilationRoots.Add(new RuntimeConfigurationRootProvider(settingsBlobName, runtimeOptions));
                     compilationRoots.Add(new RuntimeConfigurationRootProvider(knobsBlobName, runtimeKnobs));
                     compilationRoots.Add(new ExpectedIsaFeaturesRootProvider(instructionSetSupport));
-                    if (SplitExeInitialization)
+
+                    string[] aggregateExeModules = Get(_command.AggregateExeLibrary);
+                    if (aggregateExeModules.Length > 0)
+                    {
+                        foreach (string specifier in aggregateExeModules)
+                        {
+                            int separatorIndex = specifier.IndexOf('=');
+                            if (separatorIndex < 0)
+                                throw new CommandLineException($"Invalid format for --aggregateexe: '{specifier}'. Missing '=' separator between assemblyName and MainEntryPointName. Expected format: assemblyName=MainEntryPointName.");
+
+                            if (separatorIndex == 0 || separatorIndex != specifier.LastIndexOf('=') || separatorIndex == specifier.Length - 1)
+                                throw new CommandLineException($"Invalid format for --aggregateexe: '{specifier}'. Expected format: assemblyName=MainEntryPointName with non-empty assemblyName and MainEntryPointName.");
+
+                            EcmaModule module = typeSystemContext.GetModuleForSimpleName(specifier.Substring(0, separatorIndex));
+                            compilationRoots.Add(new MainMethodRootProvider(module, null, generateLibraryAndModuleInitializers: false, specifier.Substring(separatorIndex + 1)));
+                        }
+                    }
+                    else if (SplitExeInitialization)
                     {
                         compilationRoots.Add(new MainMethodRootProvider(entrypointModule, CreateInitializerList(typeSystemContext), generateLibraryAndModuleInitializers: false));
                     }
diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets
index bd32e565d6baad..782301f35eff8c 100644
--- a/src/tests/Directory.Build.targets
+++ b/src/tests/Directory.Build.targets
@@ -593,6 +593,6 @@
 
   <Target Name="LinkNativeIfBuildAndRun"
           Condition="'$(_WillCLRTestProjectBuild)' == 'true' and '$(CLRTestKind)' == 'BuildAndRun'"
-          DependsOnTargets="ComputeResolvedFilesToPublishList;LinkNative" />
+          DependsOnTargets="ComputeResolvedFilesToPublishList;NativeCompile" />
 
 </Project>
diff --git a/src/tests/nativeaot/AggregateExecutableLibrary/AggregateLibrary.csproj b/src/tests/nativeaot/AggregateExecutableLibrary/AggregateLibrary.csproj
new file mode 100644
index 00000000000000..730c7c1181824d
--- /dev/null
+++ b/src/tests/nativeaot/AggregateExecutableLibrary/AggregateLibrary.csproj
@@ -0,0 +1,42 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+    <CLRTestPriority>0</CLRTestPriority>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <BuildAsStandalone>false</BuildAsStandalone>
+    <!-- Unable to compile a project with the Library output type for apple mobile devices -->
+    <CLRTestTargetUnsupported Condition="'$(TargetsAppleMobile)' == 'true'">true</CLRTestTargetUnsupported>
+    <!-- Unable to build a library project with native dependencies for android mobile devices:
+         https://github.com/dotnet/runtime/issues/121210 -->
+    <CLRTestTargetUnsupported Condition="'$(TargetsAndroid)' == 'true'">true</CLRTestTargetUnsupported>
+    <RequiresProcessIsolation>true</RequiresProcessIsolation>
+    <CLRTestIsHosted>false</CLRTestIsHosted>
+    <CLRTestRunFile Condition="'$(TargetsWindows)' == 'true'">native/ValidatorExe.exe</CLRTestRunFile>
+    <CLRTestRunFile Condition="'$(TargetsWindows)' != 'true'">./native/ValidatorExe</CLRTestRunFile>
+    <SkipInferOutputType>true</SkipInferOutputType>
+    <EnablePreviewFeatures>true</EnablePreviewFeatures>
+    <!-- warning CS2008: No source files specified -->
+    <NoWarn>$(NoWarn);CS2008</NoWarn>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="HelloExe\HelloExe.csproj" IncludeInAggregateExecutable="true" />
+    <ProjectReference Include="ValidatorExe\ValidatorExe.csproj" IncludeInAggregateExecutable="true" />
+  </ItemGroup>
+
+  <Target Name="OverrideTestEntryPointToValidator" BeforeTargets="GenerateBatchExecutionScript;GenerateBashExecutionScript">
+    <PropertyGroup>
+      <InputAssemblyName>ValidatorExe.dll</InputAssemblyName>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="WriteHelixExtraExecutablesList" AfterTargets="NativeCompile" Condition="'$(TargetsWindows)' != 'true'">
+    <PropertyGroup>
+      <_HelloExeRelative>$(BuildProjectRelativeDir)native/HelloExe</_HelloExeRelative>
+      <_HelloExeRelative Condition="'$(BuildProjectRelativeDir)' == ''">$([System.IO.Path]::GetRelativePath('$(TestBinDir)', '$(TargetDir)native/HelloExe'))</_HelloExeRelative>
+    </PropertyGroup>
+
+    <WriteLinesToFile File="$(TargetDir)helix-extra-executables.list" Lines="$(_HelloExeRelative)" Overwrite="true" WriteOnlyWhenDifferent="true" />
+  </Target>
+</Project>
diff --git a/src/tests/nativeaot/AggregateExecutableLibrary/HelloExe/HelloExe.cs b/src/tests/nativeaot/AggregateExecutableLibrary/HelloExe/HelloExe.cs
new file mode 100644
index 00000000000000..9f476b06021221
--- /dev/null
+++ b/src/tests/nativeaot/AggregateExecutableLibrary/HelloExe/HelloExe.cs
@@ -0,0 +1,6 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+Console.WriteLine("Hello from HelloExe");
diff --git a/src/tests/nativeaot/AggregateExecutableLibrary/HelloExe/HelloExe.csproj b/src/tests/nativeaot/AggregateExecutableLibrary/HelloExe/HelloExe.csproj
new file mode 100644
index 00000000000000..f1bb752fd9c004
--- /dev/null
+++ b/src/tests/nativeaot/AggregateExecutableLibrary/HelloExe/HelloExe.csproj
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>SharedLibrary</CLRTestKind>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="HelloExe.cs" />
+  </ItemGroup>
+</Project>
diff --git a/src/tests/nativeaot/AggregateExecutableLibrary/ValidatorExe/ValidatorExe.cs b/src/tests/nativeaot/AggregateExecutableLibrary/ValidatorExe/ValidatorExe.cs
new file mode 100644
index 00000000000000..465c66a304455e
--- /dev/null
+++ b/src/tests/nativeaot/AggregateExecutableLibrary/ValidatorExe/ValidatorExe.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading.Tasks;
+
+string executableExtension = OperatingSystem.IsWindows() ? ".exe" : "";
+string helloExePath = Path.Combine(AppContext.BaseDirectory, $"HelloExe{executableExtension}");
+
+using Process? helloExe = Process.Start(new ProcessStartInfo(helloExePath)
+{
+    RedirectStandardError = true,
+    RedirectStandardOutput = true,
+    UseShellExecute = false,
+});
+
+if (helloExe is null)
+{
+    Console.Error.WriteLine($"Failed to start {helloExePath}");
+    return 1;
+}
+
+Task<string> outputTask = helloExe.StandardOutput.ReadToEndAsync();
+Task<string> errorTask = helloExe.StandardError.ReadToEndAsync();
+helloExe.WaitForExit();
+string output = (await outputTask).Trim();
+string error = (await errorTask).Trim();
+if (helloExe.ExitCode != 0 || output != "Hello from HelloExe")
+{
+    Console.Error.WriteLine($"Unexpected HelloExe result. Exit code: {helloExe.ExitCode}; output: '{output}'; error: '{error}'");
+    return 1;
+}
+
+return 100;
diff --git a/src/tests/nativeaot/AggregateExecutableLibrary/ValidatorExe/ValidatorExe.csproj b/src/tests/nativeaot/AggregateExecutableLibrary/ValidatorExe/ValidatorExe.csproj
new file mode 100644
index 00000000000000..bfc1086b4fb732
--- /dev/null
+++ b/src/tests/nativeaot/AggregateExecutableLibrary/ValidatorExe/ValidatorExe.csproj
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>SharedLibrary</CLRTestKind>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="ValidatorExe.cs" />
+  </ItemGroup>
+</Project>
