Better support for non-standard $(Configuration) names #31918
Description
Is your feature request related to a problem? Please describe.
.NET MAUI customers commonly create customer project configuration names, such as ReleaseProd, AdHoc, AppStore, etc.
Visual Studio gives a handy UI for creating configurations and setting properties based on them, and so customers use this to toggle values in their applications such as:
- Service endpoint URLs: is it Dev or Prod? Using
$(DefineConstants)and#iftogether. - iOS signing settings: is it a Release build for the App Store or Development/beta testing
The problem becomes once a custom configuration is made, customers have to somehow know lots of MSBuild properties to set. Starting with:
| <!-- User-facing configuration-specific defaults --> | |
| <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> | |
| <DebugSymbols Condition=" '$(DebugSymbols)' == '' ">true</DebugSymbols> | |
| <Optimize Condition=" '$(Optimize)' == '' ">false</Optimize> | |
| </PropertyGroup> | |
| <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> | |
| <Optimize Condition=" '$(Optimize)' == '' ">true</Optimize> | |
| </PropertyGroup> |
At minimum, they would need to know to set $(DebugSymbol) and $(Optimize) appropriately.
Then for mobile, they would also need:
- For Debug scenarios
$(UseInterpreter)set totruefor Hot Reload$(EmbedAssembliesIntoApk)set tofalsefor Android "fast deployment" / sideloading
- For Release scenarios on Android
$(PublishTrimmed)$(RunAOTCompilation)$(AndroidPackageFormat)set toaabto create Android "app bundles" for Google Play instead of an.apk
- The settings required on iOS further complicates things
- Debug builds need
$(PublishTrimmed) - Trimmer settings like
$(DebuggerSupport)are off forReleasemode
- Debug builds need
There may be several more iOS properties I've left out here.
Describe the solution you'd like
A simple approach would be introduction of new properties like $(IsDebug) and $(IsRelease) where the new code would instead do:
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<IsDebug Condition=" '$(IsDebug)' == '' ">true</IsDebug>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<IsRelease Condition=" '$(IsRelease)' == '' ">true</IsRelease>
</PropertyGroup>
<PropertyGroup Condition=" '$(IsDebug)' == 'true' ">
<DebugSymbols Condition=" '$(DebugSymbols)' == '' ">true</DebugSymbols>
<Optimize Condition=" '$(Optimize)' == '' ">false</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(IsRelease)' == 'true' ">
<Optimize Condition=" '$(Optimize)' == '' ">true</Optimize>
</PropertyGroup> Customer projects would do:
<PropertyGroup Condition=" '$(Configuration)' == 'DebugFoo' ">
<IsDebug>true</IsDebug>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseFoo' ">
<IsRelease>true</IsRelease>
</PropertyGroup>And then any defaults defined in optional workloads, etc. are based on these new properties instead of the configuration name directly.
An alternative would be some new MSBuild feature to "inherit" or "extend" configurations. That may just be too much for solving this problem.
Links
- .NET MAUI problem encountered: [xamlc] enable for $(Configuration) names like ReleaseProd maui#14638
- Android defaults: https://github.com/xamarin/xamarin-android/blob/1645103eede3ae26301167bf9aa527e813ae3786/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets#L44-L53
- iOS defaults: https://github.com/xamarin/xamarin-macios/blob/43813d69c367143d4e2198dcda5ddbca16707cdb/dotnet/targets/Xamarin.Shared.Sdk.targets#L111
Activity
jonathanpeppers commentedon Apr 20, 2023
@rolfbjarne is there anything you'd like to add here?
rolfbjarne commentedon Apr 21, 2023
We've documented the properties for iOS that depend on the configuration here: https://github.com/xamarin/xamarin-macios/blob/main/docs/configuration-properties.md
One point is what's the difference beteween "release" and "publish": would "dotnet build /p:Configuration=Release" be the same as "dotnet publish"? Or would we need a third option (say
IsPublish) as well?Otherwise I agree with everything in the description :)
jonathanpeppers commentedon Apr 21, 2023
There is a new
$(PublishRelease)that will default totruein .NET 8:https://learn.microsoft.com/dotnet/core/project-sdk/msbuild-props#publishrelease
So anything changed here, should keep this property in mind.
rolfbjarne commentedon May 26, 2023
Another idea could be to let the user tell us their intentions.
So we could have a
BuildIntentionproperty with a set of known values (sayDebug,Release,Profile, etc.)And maybe a
PublishIntentionproperty as well (with values such asAppStore,AdHoc,WebSite- each SDK would support a certain set of of intentions, and also define the meaning of each).By default we'd do something like:
grendello commentedon Oct 12, 2023
@rolfbjarne I like your idea, but I would stay with just a single property, say
BuildProfile(instead ofBuildIntention- I think "profile" expresses the goal better in this case), with the semantics of yourBuildIntention.PublishIntentionis, IMO, unnecessary since publishing involves building at some point. A single variable with a restricted (but open for future additions) set of values would be easier to document, create less information overload.rolfbjarne commentedon Oct 13, 2023
This is intented to solve the following problem: for macOS (and Mac Catalyst), publishing to the App Store involves using a signing configuration that produces an app that won't run locally, and publishing outside of the App Store involves a signing configuration that produces an app that can't be published to the App Store. People get this wrong all the time (Apple didn't make signing particularly easy to be honest), but if we knew the developer's intentions, we could create better defaults, and show warnings/errors if the developer does something we know won't work. Right now our defaults are wrong half the time...
mtanml commentedon May 2, 2024
Any updates on this? We have a MAUI project with 14 debug profiles and 14 release profiles to build all of our apps. Among other issues, hot reload isn't working. Thanks
phillippschmedt commentedon May 2, 2024
@mtanml We have a similar scope on our configurations and also struggle with the hot reload bit the most. We tried to manually set all the android/ios defaults for our debug/release equivalent but it will still not work.
jonathanpeppers commentedon May 2, 2024
So, I would assume you have various MSBuild logic that has conditions on
$(Configuration). A workaround for now would be to use a different property for now like$(Brand)and set it to your custom values likeNikeandAdidas, for example. Then just useDebugandReleasefor$(Configuration), as it seems like the only sane approach. To toggle the$(Brand)value, you could set it your.csproj,Directory.Build.props, custom MSBuild file, etc.However, I'm with you; it would be nice if the .NET SDK had support for this.
MichaelLHerman commentedon Feb 5, 2025
For anyone working off the values in the question, PublishTrimmed should not be used anymore
From https://learn.microsoft.com/en-us/dotnet/maui/deployment/trimming?view=net-maui-9.0:
Documentation is still not unified and all over the place and it seems like its not possible to make a 2nd Hot Reload Debug-like config
https://github.com/xamarin/xamarin-macios/blob/main/docs/configuration-properties.md
https://learn.microsoft.com/en-us/dotnet/ios/building-apps/build-properties#trimmode
From https://learn.microsoft.com/en-us/dotnet/maui/xaml/hot-reload?view=net-maui-9.0:
AlleSchonWeg commentedon May 6, 2025
Hi @jonathanpeppers ,
i also have more than one release configuration. When i use the default 'Release' configuration my apk has a size of 52.391 Kb. When i use my custom configuration my apk is 18.364 Kb. Default 'Debug' the apk is 18.524 Kb. I only add a value to DefineConstants, depending on the configuration.
My guess the size gap between 'Release' and the other two configurations is because that more architectures included in the 'Release' apk. Is this correct?
For my custom configuration i want a release build. So i expect that the apk size for my custom build is also 52.391 Kb. What properties i have to set to get a release build?
It would be nice to know which are the default build property values for 'Debug' and 'Release'. It makes it easier to create custom build configuration based on 'Debug' or 'Release'.
Thank you.
jonathanpeppers commentedon May 6, 2025
Since no one knows the full set of properties, the solution for now is:
ReleaseconfigurationYou can name
$(IsGooglePlay)anything you want, but I would try to choose a unique name that won't conflict with some other existing property.3 remaining items
LeoJHarris commentedon May 7, 2025
@jonathanpeppers I think there's also a lot more developers then we realize that use Config names outside of the Release|Debug etc.
dartasen commentedon Jun 16, 2025
It's crazy that such an obvious pain-point hasn't been addressed by Microsoft in years
phillippschmedt commentedon Jun 16, 2025
I agree that it's a useful feature. But there is definitely way more crazy bugs in MAUI that are open for years :-D Does the solution suggested by @baaaaif with custom properties not work for you? We are doing quite fine with it.
jonathanpeppers commentedon May 11, 2026
Reviving this issue, here are some of my current thoughts...
Name it
$(ConfigurationBasedOn), and it's eitherDebugorReleasefor now. This name is pretty clean from GH search:(Some of the other suggested names, I can find existing usage)
Customer projects could do:
Then we wouldn't have to update every spot that uses
$(Configuration), only places that compare it vs Debug or Release, which is mainly:Other repos could slowly start adopting this after merged into dotnet/sdk.
/cc @baronfel
marcpopMSFT commentedon May 12, 2026
Triage: We discussed and a concern we had is that some of the places that these are used are in props so it would force the customer to set this in directory.build.props (ie it couldn't be a per project Configuration). That limitation affects ArtifactsPath as well and has slowed adoption of that.
An alternative is to design a props file that gets imported to set all release or all debug properties. We'd need a full list of everywhere this needs to be set so we'd need to check msbuild, roslyn, runtime, vstest, maybe c++ as well. We think msbuild and roslyn are probably clean.
jonathanpeppers commentedon May 18, 2026
My example above (#31918 (comment)) wouldn't work due to ordering:
Microsoft.NET.Sdk.propslooks at$(Configuration).csprojis evaluated, where you'd set$(ConfigurationBasedOn)-- this is already too lateDirectory.Build.propsmight work, but that is solution-wide. "Inventing a new file" seems like the only solution here.[xabt] Enable CoreCLR R2R for custom publish configurations (#12366)
[dotnet] Use the existing '$(_BundlerDebug)' property instead of the …