-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[RFC] Detecting current OS #539
Comments
We just discussed this in Xamarin and we came to the conclusion that MSBuild changing @rainersigwald you said in #446 (comment) that you think it's reasonable to update conditions when moving to MSBuild, but is there a chance we can revisit this decision? |
For bad added context, there are 140 matches on github for There are 1,653 matches when targeting This isn't necessarily "a lot" -- or even accurate? -- but it does show that plenty of existing code files use Changing |
We discussed this a bit today in our team meeting. This is a tricky one because msbuild isn't exactly the same as xbuild. So if we're migrating users from xbuild to msbuild, while we want it to be as easy as possible we definitely don't want to implement "bugs" in msbuild to match xbuild behavior (to the largest extent possible). "Bug" is a stretch here, but it's definitely not behavior we would choose (at least in hindsight). Few options we talked about:
Personally I think this should not be done in MSBuild but passed off to the Runtime. The closest thing I know of there would be to use OSPlatform. Unfortunately that a) doesn't include Also for the statistics @jonpryor mentioned, most of those 1600+ hits are Thoughts? We will discuss this again during our team triage tomorrow. |
I would lean towards option 2, matching the xbuild behavior, as right now it has a lot more adoption than .NET Core MSBuild and it is better to keep this behavior consistent if possible. The OSPlatform APIs don't allow you to get the name (by design), they only allow you to check to see if you are on a specified OS. So if we want to expose this functionality, I think we should do so as an intrinsic function instead of a property, ie |
Team Triage: Marking as up-for-grabs. We would like to make |
We talked about this a bit more. It's unfortunate that |
@rainersigwald afaik you can use the System.Runtime.InteropServices.RuntimeInformation package which has these new APIs on full framework too, but @ericstj can confirm. |
Based on the discussion in issue dotnet#539, $(OS) property will return `Windows_NT` whenever running on windows and `Unix` for any other OS. NativeMethodsShared.OSName is used to set that property, hence this is being changed.
Usage: $([MSBuild]::IsOSPlatform(Windows)) Based on @dsplaisted's suggestion in issue dotnet#539 .
Usage: $([MSBuild]::IsOSPlatform(Windows)) Based on @dsplaisted's suggestion in issue dotnet#539 .
Usage: $([MSBuild]::IsOSPlatform(Windows)) Based on @dsplaisted's suggestion in issue dotnet#539 .
Usage: $([MSBuild]::IsOSPlatform(Windows)) Based on @dsplaisted's suggestion in issue dotnet#539 .
Hello, just wanted to chime in with the detection task I have added today using I saw @jeffkl's pull request #1486, which will probably allow us to get rid of the reflection calls and make code look decent, but is there a way to get the list of all dependencies that are in closure of Regardless, it would be nice to get this information using RuntimeInformation type (which provides xplat OS description and architectures beyond X86/X64 ; ARM and ARM64 etc.) intrinsically from MSBuild. :) Note that the project is targeting Framework 4.0 at the moment, while (cc: @nschonni, @darrenkopp for visibility) |
@am11 I made a sample based on your needs that doesn't use reflection: https://github.com/jeffkl/MSBuild-NetCore/tree/master/src/UsingTaskWithReference I only needed to add a reference to |
@jeffkl, thanks a lot! 🎉 Running into few issues with MSBuild v14.0, I have started a thread in your repo: jeffkl/MSBuild-NetCore#1. :) |
So I wanted to figure out "am I building on OSX or not?" and came across this issue. I want to know whether I am building on Windows, OSX, or Linux, and I want to know it statically (so I can set some other properties statically). I've figured out that if I'm running MSBuild on .NET Core, I can call <PropertyGroup>
<IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildRuntimeType)' == 'Core'">
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<Target Name="PrintRID" BeforeTargets="Build">
<Message Text="IsWindows $(IsWindows)" Importance="high" />
<Message Text="IsOSX $(IsOSX)" Importance="high" />
<Message Text="IsLinux $(IsLinux)" Importance="high" />
</Target> The above works in Visual Studio and when using |
@eerhardt the above should work on Mono MSBuild as well since (recent) Mono ships with System.Runtime.InteropServices.RuntimeInformation. You'll need to change the MSBuildRuntimeType check of course. |
Perfect! That's exactly what I wanted to hear. And since RuntimeInformation is available on |
Hmm, seems we're missing the FEATURE_RUNTIMEINFORMATION in dir.props in our Mono MSBuild build so it might not be available at runtime. @radical I don't see a reason why this shouldn't work, could you look into enabling it? |
Enabled cross-platform in #1926 |
The above trick does not work with regular .NET on VS 2017. What incarnation should someone use to detect Mac/Linux/Windows platforms? |
@migueldeicaza It should be there with the next big Visual Studio update. Daily CLI builds should also have it. It brings the following new stuff: MicrosoftDocs/visualstudio-docs#111 |
For the record, you can use Sample usage: <PropertyGroup>
<OpenCommand Condition="$([MSBuild]::IsOSPlatform('Linux'))">xdg-open</OpenCommand>
<OpenCommand Condition="$([MSBuild]::IsOSPlatform('OSX'))">open</OpenCommand>
<OpenCommand Condition="$([MSBuild]::IsOSPlatform('Windows'))">explorer</OpenCommand>
</PropertyGroup> |
Context: dotnet/msbuild#539 (comment) Sometimes the `%OS%` environment variable is set, which overrides the normally expected `$(OS)` MSBuild property. Instead of using `$(OS)`, use `$([MSBuild]::IsOSPlatform(name))`.
Context: 5c756b1 Context: 08ff4db Context: https://discord.com/channels/732297728826277939/732297952676020316/819978878948868166 Context: microsoft/vstest#2571 Context: dotnet/msbuild#539 (comment) Context: #816 (comment) With the `cmake`-based build system knowledge behind 5c756b1 in mind, update `src/java-interop` to *also* use a `cmake`-based build system, then add support so it can build on Windows. On Windows, this builds both e.g. a 32-bit `bin\Debug\win-x86\java-interop.dll` *and* 64-bit `bin\Debug\win-x64\java-interop.dll` libraries. This allows the `Java.Interop-Tests.dll` unit tests to *also* be run on Windows, under .NET Core [^0]. Note that this requires updating `java_interop_lib_load()` to also include [`LOAD_LIBRARY_SEARCH_SYSTEM32`][0]: * `LOAD_LIBRARY_SEARCH_SYSTEM32`: `%windows%\system32` is searched for the DLL and its dependencies. This specifically is needed so that `JVM.DLL` dependencies such as `KERNEL32.DLL` can be resolved, allowing `JVM.DLL` to be loaded. This allows .NET Core on Windows to run `Java.Interop-Tests.dll`! > dotnet test bin\TestDebug-netcoreapp3.1\Java.Interop-Tests.dll … A total of 1 test files matched the specified pattern. Skipped Dispose_ClearsLocalReferences [11 ms] Passed! - Failed: 0, Passed: 617, Skipped: 1, Total: 618, Duration: 2 s - Java.Interop-Tests.dll (netcoreapp3.1) Install .NET 5.0.103, as that version is required in order for `dotnet test Java.Interop-Tests.dll` to reliably use a 64-bit process. ~~~ Aside: So you want to create a file which is built into a *subdirectory* of `$(OutputPath)`. The "obvious thing" fails: <!-- Fails --> <ItemGroup> <None Include="$(OutputPath)win-x64\java-interop.dll" /> </ItemGroup> This results in: error MSB3030: Could not copy the file… This can be done by: 1. Providing `%(Link)` item metadata which contains the relative directory and filename, *not* `$(OutputPath)`, and 2. Using `\` *everywhere*. Thus: <!-- Works --> <ItemGroup> <None Include="$(OutputPath)win-x64\java-interop.dll"> <Link>win-x64\java-interop.dll</Link> </None> </ItemGroup> This works because: 1. The [`<AppendTargetPath/> task`][1] uses `%(Link)` as an *override* when setting `%(TargetPath)`. 2. The [`_CopyOutOfDateSourceItemsToOutputDirectory` target][2] uses `$(OutDir)%(TargetPath)` for `Copy.DestinationFiles`.. 3. The [`<Copy/>` task][3] *ignores errors* when `SourceFiles[i]` and `DestinationFiles[i]` are *identical*. This is why `\` must be used, to ensure that the values are identical. [^0]: …but not .NET Framework, as .NET Framework on CI is launching a 32-bit process for the unit tests, while we need a 64-bit process to match the `JVM.DLL` we're loading. [0]: https://docs.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw [1]: https://github.com/dotnet/msbuild/blob/17677364d656a98ce4c6eff73b49eddf24f0fd72/src/Tasks/AssignTargetPath.cs#L74 [2]: https://github.com/dotnet/msbuild/blob/17677364d656a98ce4c6eff73b49eddf24f0fd72/src/Tasks/Microsoft.Common.CurrentVersion.targets#L4965-L4977 [3]: https://github.com/dotnet/msbuild/blob/17677364d656a98ce4c6eff73b49eddf24f0fd72/src/Tasks/Copy.cs#L787-L796
MSBuild sets the
$(OS)
property to OSX/Unix/Windows at runtime, which can be used in targets to determine the current OS. Butxbuild
has been using$(OS)==Unix
on OSX and Linux, because of an old mono bug. And it continues to do so for compatibility reasons.It makes sense for MSBuild to follow the same, since users would want to use it with existing targets. PR #538 reverts back to that behavior. So, for non-windows case,
$(OS)
property is effectively acting as aIsUnixLike
. Considering it like that,$(OS)
should probably have only two values now -Windows_NT
andUnix
.Now, I think it might be useful to be able to differentiate between
OSX
and other specific unices. But maybe we should use some other (new) property for that?$(OSName)
? I am not sure how the CoreCLR case is affected by this, but AFAIU, it would be in the same boat.Thoughts?
The text was updated successfully, but these errors were encountered: