Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support building for multiple RIDs, similar to how TargetFrameworks works #9795

Open
joshudson opened this issue Oct 3, 2018 · 13 comments
Open
Milestone

Comments

@joshudson
Copy link

Steps to reproduce

Have project file

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.1;netcoreapp2.0</TargetFrameworks>
    <RuntimeIdentifiers>win;linux-x64</RuntimeIdentifiers>
  </PropertyGroup>
</Project>

run dotnet build

Expected behavior

Builds .dlls, that is the cross join between the RuntimeIdentifiers and TargetFrameworks

Actual behavior

Tries to build the any rid for each framework in TargetFrameworks but can't because the any rid is unbuildable on this project.

Environment data

dotnet --info output:

.NET Core SDK (reflecting any global.json):
Version: 2.1.302
Commit: 9048955

Runtime Environment:
OS Name: debian
OS Version: 9
OS Platform: Linux
RID: debian.9-x64
Base Path: /usr/share/dotnet/sdk/2.1.302/

Host (useful for support):
Version: 2.1.2
Commit: 811c3ce6c0

.NET Core SDKs installed:
2.1.302 [/usr/share/dotnet/sdk]

.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

@onovotny: I tried your MSBuild.Sdk.Extras version 1.6.30-preview and 1.7.1-preview; however while it can make a reference assembly just fine it doesn't seem to convince dotnet build or dotnet pack to do the right thing with RuntimeIdentifiers. 1.6.40 seems to be brain-damaged and the builds bomb.

dotnet /usr/share/dotnet/sdk/2.1.302/MSBuild.dll doesn't work either.

@dasMulli
Copy link
Contributor

dasMulli commented Oct 3, 2018

if no RuntimeIdentifier (singular) is set in the project file, the build won't use any.
Unlike the TargetFrameworks (plural), RuntimeIdentifiers (plural) isn't multi-targeting but only prepares some NuGet references (which one could argue is no longer necessary since dotnet build -r * will cause a new restore anyway)

@clairernovotny
Copy link
Member

I added support for that if you use my Extras package:
https://github.com/onovotny/MSBuildSdkExtras

Set that as the SDK attribute along with the version in the global.json (instructions are in the readme), then add a property in your csproj setting ExtrasBuildEachRuntimeIdentifier to true.

It will build each RID and put them into specific output folders. It will also define a RID-specific define so you can ifdef around it.

@livarcocc
Copy link
Contributor

cc @peterhuene

@peterhuene
Copy link
Contributor

@dasMulli assessment is correct and I think it is very confusing to use RuntimeIdentifier to affect the build output, but have RuntimeIdentifiers instead control what gets restored, rather than an MxN product with TargetFrameworks.

I think we would have to adopt something similar to @onovotny's extension to enable this, since it would be a breaking change for RuntimeIdentifiers to suddenly build per-RID.

As I'm working on implicitly adding a RID to RuntimeIdentifiers (at least in the short term until dependent features are enabled), I'll try to keep this scenario in mind.

@clairernovotny
Copy link
Member

clairernovotny commented Oct 3, 2018

@peterhuene what I had to hack to make it work is pretty nasty, but not overly complex:
https://github.com/onovotny/MSBuildSdkExtras/blob/master/Source/MSBuild.Sdk.Extras/Build/RIDs.targets

It's nasty because it has to reach into NuGet's output resolution (to get the right dlls and put in the right output directory in the package) and also override a few other private targets. I'd prefer not to do that :)

As part of the design, I also support conditional RID's per TFM, since some TFM's may have RID-specific implementations while others don't.

I'd love to see this incorporated directly.

@livarcocc
Copy link
Contributor

I moved it to 3.0 and under your epic. We can check the state of things when some of your changes are in and make a decision on whether we want to enable exactly this or not and how.

@peterhuene peterhuene self-assigned this Feb 19, 2019
@dsplaisted dsplaisted changed the title dotnet build doesn't honor RuntimeIdentifiers at build time Support building for multiple RIDs, similar to how TargetFrameworks works May 8, 2019
@dsplaisted
Copy link
Member

This would be a major feature to add. We won't be able to do it in the 3.0 release, so I'm moving it to the backlog.

@dasMulli
Copy link
Contributor

dasMulli commented May 8, 2019

The scenario could be interesting for how things will change in ".NET 5"..

No idea how/if TFMs are going to evolve but I could also easily see a world where we could do

<PropertyGroup>
  <TargetFramework>net5.0</TargetFramework>
  <RuntimeIdentifiers>iOS12.0-arm64;iOS12.0-x64;android-arm;android-arm64;android-x64</RuntimeIdentifiers>
</PropertyGroup>

or something similar instead of monoandroid60 and friends. (though I don't think this would be RIDs)

@peterhuene peterhuene removed their assignment Sep 10, 2019
@msftgits msftgits transferred this issue from dotnet/cli Jan 31, 2020
@msftgits msftgits added this to the Backlog milestone Jan 31, 2020
@caizixian
Copy link

The scenario could be interesting for how things will change in ".NET 5"..

No idea how/if TFMs are going to evolve but I could also easily see a world where we could do

<PropertyGroup>
  <TargetFramework>net5.0</TargetFramework>
  <RuntimeIdentifiers>iOS12.0-arm64;iOS12.0-x64;android-arm;android-arm64;android-x64</RuntimeIdentifiers>
</PropertyGroup>

or something similar instead of monoandroid60 and friends. (though I don't think this would be RIDs)

This is a valid scenario.

I'd argue that on desktop platforms, it also makes sense to have, e.g. <RuntimeIdentifiers>osx-x64;linux-x64</RuntimeIdentifiers>, so that I can get multiple executables, one for each RID, with a single dotnet publish. Of course, I can run dotnet publish -r multiple times, but it's more desirable to have it built into the build system.

@asasine
Copy link

asasine commented Sep 15, 2021

(which one could argue is no longer necessary since dotnet build -r * will cause a new restore anyway)

@dasMulli

There are certain build scenarios where package restoration must be performed in a separate step from building. Some build systems intentionally cut network access after restoration for security reasons; all tasks requiring external resources have to be performed before this cut and then made locally available for any following tasks (such as dotnet build --no-restore)

@stevefan1999-personal
Copy link

Let's prioritize this feature, since GoReleaser also have it. My ultimate use case is to use this to build single file executable for each platform in Docker (ARM, Windows, Linux/Musl, etc).

@AraHaan
Copy link
Member

AraHaan commented Apr 26, 2022

I think since .NET allows the RID in the TFM that users must really do that instead, then under the RuntimeIdentifier set it to the RID that is in the TFM the user provided.

@slxdy
Copy link

slxdy commented Mar 26, 2024

For anyone still looking for a solution, I found a really hacky work-around.
In my case, I want to build my project for x64 and x86 in a single solution build to the same directory.
I set my main build target for the project x64 and added a post build event that automatically builds the x86 version.

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
        <Platforms>x64;x86</Platforms>
        <OutDir>output/$(Configuration)/</OutDir>
        <AssemblyName Condition="'$(Platform)' == 'x86'">$(MSBuildProjectName).x86</AssemblyName>
    </PropertyGroup>

    <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Platform)' == 'x64'">
        <MSBuild Projects="$(MSBuildProjectFile)" Properties="Platform=x86" />
    </Target>

</Project>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests