Skip to content

Instantly share code, notes, and snippets.

@jonpryor
Created February 15, 2024 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonpryor/adcbf621b6bf2ce29a782daa2d2f2d52 to your computer and use it in GitHub Desktop.
Save jonpryor/adcbf621b6bf2ce29a782daa2d2f2d52 to your computer and use it in GitHub Desktop.
Assemblies & build variations, oh my!

C# projects can reference other projects. This is done via @(ProjectReference):

<ItemGroup>
  <ProjectReference Include="Path\To\OtherProject.csproj" />
</ItemGroup>

However, sometimes you don't want to reference the "default" (same build $(Configuration)) project, but instead a build variation based upon setting some MSBuild properties.

This seems straightforward: just use %(ProjectReference.AdditionalProperties)!

<ItemGroup>
  <ProjectReference
      Include="Path\To\OtherProject.csproj"
      AdditionalProperties="UseNativeAot=True"
  />
</ItemGroup>

…except that doesn't actually work by default. It may work "in the small", but if you build a top-level .sln and OtherProject.csproj is referenced by multiple other projects, you may find that the project specifying %(ProjectReference.AdditionalProperties) doesn't actually use/get an assembly that was built with those additional properties set. The first build "wins"!

In order to make this work as you would expect, OtherProject.csproj needs to override $(OutputPath) and $(IntermediateOutputPath) so that these properties are taken into consideration:

<PropertyGroup>
  <IntermediateOutputPath Condition=" '$(UseNativeAot)' == 'true' ">$(BaseIntermediateOutputPath)$(Configuration)+NativeAOT\$(TargetFramework.ToLowerInvariant())\</IntermediateOutputPath>
  <OutputPath Condition=" '$(UseNativeAot)' == 'true' ">bin\$(Configuration)+NativeAOT-$(DotNetTargetFramework.ToLowerInvariant())\</OutputPath>
</PropertyGroup>

That way, properties which make "uniquely different" assemblies get different build & output directories, and things will rebuild appropriately.

See also: https://github.com/xamarin/Java.Interop/commit/b5fc4cf223e9f2c34a632d06f13a3b293ac47f4b

diff --git a/src/Java.Interop/Java.Interop.csproj b/src/Java.Interop/Java.Interop.csproj
index 43d5937e3..f93e38e6a 100644
--- a/src/Java.Interop/Java.Interop.csproj
+++ b/src/Java.Interop/Java.Interop.csproj
@@ -22,14 +22,15 @@
<Import Project="..\..\TargetFrameworkDependentValues.props" />
<PropertyGroup>
<DefineConstants>INTEROP;FEATURE_JNIOBJECTREFERENCE_INTPTRS;INTERNAL_NULLABLE_ATTRIBUTES;$(JavaInteropDefineConstants)</DefineConstants>
- <IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFramework.ToLowerInvariant())\</IntermediateOutputPath>
- <OutputPath>$(ToolOutputFullPath)</OutputPath>
- <DocumentationFile>$(ToolOutputFullPath)Java.Interop.xml</DocumentationFile>
+ <IntermediateOutputPath Condition=" '$(UseNativeAot)' == 'true' ">$(BaseIntermediateOutputPath)$(Configuration)+NativeAOT\$(TargetFramework.ToLowerInvariant())\</IntermediateOutputPath>
+ <IntermediateOutputPath Condition=" '$(IntermediateOutputPath)' == '' ">$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFramework.ToLowerInvariant())\</IntermediateOutputPath>
+ <OutputPath Condition=" '$(UseNativeAot)' == 'true' ">bin\$(Configuration)+NativeAOT-$(DotNetTargetFramework.ToLowerInvariant())\</OutputPath>
+ <OutputPath Condition=" '$(OutputPath)' == '' ">$(ToolOutputFullPath)</OutputPath>
+ <DocumentationFile>$(OutputPath)Java.Interop.xml</DocumentationFile>
<JNIEnvGenPath>$(BuildToolOutputFullPath)</JNIEnvGenPath>
<LangVersion Condition=" '$(JIBuildingForNetCoreApp)' == 'True' ">9.0</LangVersion>
<LangVersion Condition=" '$(LangVersion)' == '' ">8.0</LangVersion>
<Version>$(JICoreLibVersion)</Version>
- <Standalone Condition=" '$(Standalone)' == '' ">true</Standalone>
</PropertyGroup>
<PropertyGroup Condition=" '$(Standalone)' == 'True' ">
<DefineConstants Condition=" '$(JIBuildingForNetCoreApp)' == 'True' ">FEATURE_JNIENVIRONMENT_JI_FUNCTION_POINTERS;$(DefineConstants)</DefineConstants>
@@ -38,6 +39,9 @@
<PropertyGroup Condition=" '$(Standalone)' != 'True' ">
<DefineConstants>FEATURE_JNIENVIRONMENT_JI_PINVOKES;$(DefineConstants)</DefineConstants>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(UseNativeAot)' == 'True' ">
+ <DefineConstants>FEATURE_NATIVE_AOT;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
<ItemGroup>
<Compile Condition=" '$(TargetFramework)' == 'netstandard2.0' " Include="..\utils\NullableAttributes.cs" />
<Compile Remove="Java.Interop\JniLocationException.cs" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment