Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/building-apps/build-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,20 @@ Only applicable to macOS and Mac Catalyst projects.

See [BuildIpa](#buildipa) for iOS and tvOS projects.

## Device

Specifies which mobile device or emulator to target when using `dotnet run
--device <Device>` or MSBuild targets that interact with devices (such as
`Run`, `Install`, or `Uninstall`).

The value can be anything the command-line tools `simctl` or `devicectl`
accept for the device name; this is typically either the UDID or the name of
the device. For example, for the device `My iOS Device` with UDID `00001111-012301230123ABCD`, use
either `-p:Device="My iOS Device"` or `-p:Device=00001111-012301230123ABCD`.

For more information about device selection, see the
[.NET SDK device selection specification](https://github.com/dotnet/sdk/blob/2b9fc02a265c735f2132e4e3626e94962e48bdf5/documentation/specs/dotnet-run-for-maui.md).

## DeviceSpecificBuild

If the build should be specific to the selected device.
Expand Down
32 changes: 30 additions & 2 deletions docs/building-apps/build-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,39 @@ Builds the source code within a project and all dependencies.

Removes all files generated by the build process.

## ComputeAvailableDevices

Queries and returns a list of available iOS or tvOS devices and simulators that can be used with `dotnet run`.

This target is called automatically by the .NET SDK's `dotnet run` command to
support device selection via the `--device` option. It returns a `@(Devices)`
item group where each device has the following metadata:

- **Description**: The name of the device (e.g., "iPhone 16 - iOS 26.0" for simulators, "My iPhone 16" for physical devices)
- **Type**: Either "Device" or "Simulator"
- **OSVersion**: The OS version of the device
- **UDID**: The UDID of the device
- **RuntimeIdentifier**: The RuntimeIdentifier of the device

For example, to list all available devices:

```shell
$ dotnet build -t:ComputeAvailableDevices
```

This target is part of the [.NET SDK device selection specification](https://github.com/dotnet/sdk/blob/2b9fc02a265c735f2132e4e3626e94962e48bdf5/documentation/specs/dotnet-run-for-maui.md) and enables commands like:

```shell
$ dotnet run --device UDID
```

Added in .NET 11.

## Run

Builds the source code within a project and all dependencies, and then deploys and runs it
on a default simulator/device. A specific deployment target can be set by using the `$(_DeviceName)` property.
on a default simulator/device. A specific deployment target can be set by using the `$(Device)` property.

```dotnetcli
dotnet build -t:Run project.csproj -p:_DeviceName=$(MY_DEVICE_UDID)
dotnet build -t:Run project.csproj -p:Device=$(MY_DEVICE_UDID)
```
2 changes: 2 additions & 0 deletions dotnet/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ $(1)_NUGET_TARGETS = \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Microsoft.$(1).Sdk.props \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Microsoft.$(1).Sdk.Versions.props \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Microsoft.$(1).Sdk.targets \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Microsoft.Sdk.Desktop.targets \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Microsoft.Sdk.Eol.targets \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Microsoft.Sdk.Mobile.targets \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Xamarin.Shared.Sdk.DefaultItems.targets \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Xamarin.Shared.Sdk.Publish.targets \
$(DOTNET_DESTDIR)/$($(1)_NUGET_SDK_NAME)/targets/Xamarin.Shared.Sdk.TargetFrameworkInference.props \
Expand Down
28 changes: 28 additions & 0 deletions dotnet/targets/Microsoft.Sdk.Desktop.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target
Name="_PrepareRunDesktop"
BeforeTargets="ComputeRunArguments"
Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">

<PropertyGroup Condition="'$(RunWithOpen)' != 'false'">
<_OpenArguments Condition="'$(XamarinDebugMode)' != ''">$(_OpenArguments) --env __XAMARIN_DEBUG_MODE__=$(XamarinDebugMode)</_OpenArguments>
<_OpenArguments Condition="'$(XamarinDebugPort)' != ''">$(_OpenArguments) --env __XAMARIN_DEBUG_PORT__=$(XamarinDebugPort)</_OpenArguments>
<_OpenArguments Condition="'$(XamarinDebugHosts)' != ''">$(_OpenArguments) --env "__XAMARIN_DEBUG_HOSTS__=$(XamarinDebugHosts)"</_OpenArguments>
<_OpenArguments Condition="'$(XamarinDebugConnectTimeout)' != ''">$(_OpenArguments) --env __XAMARIN_DEBUG_CONNECT_TIMEOUT__=$(XamarinDebugConnectTimeout)</_OpenArguments>
<_OpenArguments Condition="'$(StandardOutputPath)' != ''">$(_OpenArguments) --stdout "$(StandardOutputPath)"</_OpenArguments>
<_OpenArguments Condition="'$(StandardErrorPath)' != ''">$(_OpenArguments) --stderr "$(StandardErrorPath)"</_OpenArguments>
<_OpenArguments Condition="'$(StandardInputPath)' != ''">$(_OpenArguments) --stdin "$(StandardInputPath)"</_OpenArguments>
<_OpenArgumentsPre Condition="'$(OpenNewInstance)' == 'true'">-n </_OpenArgumentsPre>
<_OpenArgumentsPre Condition="'$(OpenWaitForExit)' == 'true'">$(_OpenArgumentsPre) -W </_OpenArgumentsPre>
<_OpenArguments>$(_OpenArguments) $(RunEnvironment)</_OpenArguments>
<RunCommand>open</RunCommand>
<RunArguments>$(_OpenArgumentsPre) -a "$(TargetDir)/$(_AppBundleName).app" $(OpenArguments) $(_OpenArguments) --args</RunArguments>
</PropertyGroup>

<PropertyGroup Condition="'$(RunWithOpen)' == 'false'">
<RunCommand>$(TargetDir)/$(_AppBundleName).app/Contents/MacOS/$(_NativeExecutableName)</RunCommand>
<RunArguments />
</PropertyGroup>
</Target>
</Project>
177 changes: 177 additions & 0 deletions dotnet/targets/Microsoft.Sdk.Mobile.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<!-- Install & Run -->

<PropertyGroup>
<!-- We used to use '_MlaunchPath' as the property name, but we've made it public, so it's MlaunchPath now, but keep setting/supporting the underscored version for a while -->
<MlaunchPath Condition="'$(MlaunchPath)' == '' And '$(_MlaunchPath)' != ''">$(_MlaunchPath)</MlaunchPath>
<MlaunchPath Condition="'$(MlaunchPath)' == ''">$(_XamarinSdkRootDirectory)tools\bin\mlaunch</MlaunchPath>
<_MlaunchPath Condition="'$(_MlaunchPath)' == ''">$(MlaunchPath)</_MlaunchPath>
<!-- this is the path to mlaunch relative to the root of the .NET installation -->
<!-- We used to use '_RelativeMlaunchPath' as the property name, but we've made it public, so it's RelativeMlaunchPath now, but keep setting/supporting the underscored version for a while -->
<RelativeMlaunchPath Condition="'$(RelativeMlaunchPath)' == '' And '$(_RelativeMlaunchPath)' != ''">$(_RelativeMlaunchPath)</RelativeMlaunchPath>
<RelativeMlaunchPath Condition="'$(RelativeMlaunchPath)' == ''">$(XamarinRelativeSdkRootDirectory)tools\bin\mlaunch</RelativeMlaunchPath>
<_RelativeMlaunchPath Condition="'$(_RelativeMlaunchPath)' == ''">$(RelativeMlaunchPath)</_RelativeMlaunchPath>

<!-- Try to keep _DeviceName working for a while yet -->
<Device Condition="'$(Device)' == ''">$(_DeviceName)</Device>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

</PropertyGroup>

<Target
Name="ShowRunHelp"
DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;_DetectAppManifest">
<Error Condition="$([MSBuild]::IsOSPlatform('windows'))" Text="It's currently not supported to launch an app from the command line on Windows." />
<Error Condition="!Exists('$(_AppBundleManifestPath)')" Text="The app must be built before showing how to launch it." />

<GetMlaunchArguments
AppManifestPath="$(_AppBundleManifestPath)"
Help="true"
MlaunchPath="$(MlaunchPath)"
SdkDevPath="$(_SdkDevPath)"
SdkIsSimulator="$(_SdkIsSimulator)"
SdkVersion="$(_SdkVersion)"
SupportedOSPlatformVersion="$(SupportedOSPlatformVersion)"
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)"
>
</GetMlaunchArguments>

<!-- If invoked from 'dotnet run', don't actually run anything -->
<PropertyGroup>
<RunCommand>true</RunCommand>
<RunArguments />
</PropertyGroup>
</Target>
<Target Name="_ShowRunHelpConditioned" Condition="'$(Help)' == 'true'" DependsOnTargets="ShowRunHelp" />

<Target Name="ComputeMlaunchInstallArguments" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;_DetectAppManifest;_ShowRunHelpConditioned;_ComputeMlaunchInstallArguments" />
<Target Name="_ComputeMlaunchInstallArguments" Condition="'$(_SdkIsSimulator)' == 'false' And '$(Help)' != 'true'">
<!-- Launching from the command line on windows hasn't been implemented: https://github.com/dotnet/macios/issues/16609 -->
<Error Condition="$([MSBuild]::IsOSPlatform('windows'))" Text="It's currently not supported to launch an app from the command line on Windows." />
<Error Condition="!Exists('$(_AppBundleManifestPath)')" Text="The app must be built before the arguments to launch the app using mlaunch can be computed." />

<GetMlaunchArguments
SessionId="$(BuildSessionId)"
AppManifestPath="$(_AppBundleManifestPath)"
DeviceName="$(Device)"
InstallApp="$(_AppBundlePath)"
MlaunchPath="$(MlaunchPath)"
SdkDevPath="$(_SdkDevPath)"
SdkIsSimulator="$(_SdkIsSimulator)"
SdkVersion="$(_SdkVersion)"
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)"
>
<Output TaskParameter="MlaunchArguments" PropertyName="MlaunchInstallArguments" />
</GetMlaunchArguments>

<WriteLinesToFile
File="$(MlaunchInstallScript)"
Lines="$(MlaunchPath) $(MlaunchInstallArguments)"
Overwrite="true"
WriteOnlyWhenDifferent="true"
Condition="'$(MlaunchInstallScript)' != ''"
/>
</Target>

<Target Name="_InstallMobile" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;ComputeMlaunchInstallArguments" Condition="'$(_SdkIsSimulator)' == 'false'">
<Exec SessionId="$(BuildSessionId)" Command="'$(MlaunchPath)' $(MlaunchInstallArguments)" />
</Target>

<Target Name="ComputeMlaunchRunArguments" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;_DetectAppManifest;_ShowRunHelpConditioned;_ComputeMlaunchRunArguments" Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'" />

<Target Name="_ComputeMlaunchRunArguments" Condition="'$(Help)' != 'true'">
<!-- Launching from the command line on windows hasn't been implemented: https://github.com/dotnet/macios/issues/16609 -->
<Error Condition="$([MSBuild]::IsOSPlatform('windows'))" Text="It's currently not supported to launch an app from the command line on Windows." />
<Error Condition="!Exists('$(_AppBundleManifestPath)')" Text="The app must be built before the arguments to launch the app using mlaunch can be computed." />

<PropertyGroup>
<!-- capture output by default -->
<_MlaunchCaptureOutput Condition="'$(_MlaunchCaptureOutput)' == ''">true</_MlaunchCaptureOutput>
<!-- wait for exit by default -->
<_MlaunchWaitForExit Condition="'$(_MlaunchWaitForExit)' == ''">true</_MlaunchWaitForExit>
<!-- don't set standard output/error path, mlaunch will by default write to stdout/stderr -->
</PropertyGroup>
<ItemGroup>
<MlaunchEnvironmentVariables Include="__XAMARIN_DEBUG_MODE__=$(XamarinDebugMode)" Condition="'$(XamarinDebugMode)' != ''" />
<MlaunchEnvironmentVariables Include="__XAMARIN_DEBUG_PORT__=$(XamarinDebugPort)" Condition="'$(XamarinDebugPort)' != ''" />
<MlaunchEnvironmentVariables Include="__XAMARIN_DEBUG_HOSTS__=$(XamarinDebugHosts.Replace(';', '%3B'))" Condition="'$(XamarinDebugHosts)' != ''" />
<MlaunchEnvironmentVariables Include="__XAMARIN_DEBUG_CONNECT_TIMEOUT__=$(XamarinDebugConnectTimeout)" Condition="'$(XamarinDebugConnectTimeout)' != ''" />
<!-- It's not possible to set an item group from the command line, so add support for setting a property (with semi-colon separated items) that we'll include into the item group -->
<MlaunchAdditionalArguments Include="$(MlaunchAdditionalArgumentsProperty)" Condition="'$(MlaunchAdditionalArgumentsProperty)' != ''" />
</ItemGroup>
<GetMlaunchArguments
SessionId="$(BuildSessionId)"
AdditionalArguments="@(MlaunchAdditionalArguments)"
AppManifestPath="$(_AppBundleManifestPath)"
CaptureOutput="$(_MlaunchCaptureOutput)"
DeviceName="$(Device)"
EnvironmentVariables="@(MlaunchEnvironmentVariables)"
LaunchApp="$(_AppBundlePath)"
MlaunchPath="$(MlaunchPath)"
SdkIsSimulator="$(_SdkIsSimulator)"
SdkDevPath="$(_SdkDevPath)"
SdkVersion="$(_SdkVersion)"
StandardErrorPath="$(_MlaunchStandardErrorPath)"
StandardOutputPath="$(_MlaunchStandardOutputPath)"
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)"
WaitForExit="$(_MlaunchWaitForExit)"
>
<Output TaskParameter="MlaunchArguments" PropertyName="MlaunchRunArguments" />
</GetMlaunchArguments>

<WriteLinesToFile
File="$(MlaunchRunScript)"
Lines="$(MlaunchPath) $(MlaunchRunArguments)"
Overwrite="true"
WriteOnlyWhenDifferent="true"
Condition="'$(MlaunchRunScript)' != ''"
/>

<PropertyGroup>
<RunCommand>$(MlaunchPath)</RunCommand>
<RunArguments>$(MlaunchRunArguments) -- </RunArguments>
</PropertyGroup>
</Target>

<!-- This is only needed for mobile platforms, RunCommand and RunArguments are defined for macOS in Microsoft.macOS.Sdk.targets. -->
<Target
Name="_PrepareRunMobile"
BeforeTargets="ComputeRunArguments"
DependsOnTargets="_InstallMobile;ComputeMlaunchRunArguments"
Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">
</Target>

<!--
***********************************************************************************************
ComputeAvailableDevices
Target that queries available devices and simulators.
This target is called by 'dotnet run' to support device selection.
Returns @(Devices) items that always has these metadata: Description, Type, OSVersion, UDID, RuntimeIdentifier
(but others might be present too, for debug purposes, depending on whether it's a simulator or a device)
See: https://github.com/dotnet/sdk/blob/2b9fc02a265c735f2132e4e3626e94962e48bdf5/documentation/specs/dotnet-run-for-maui.md
***********************************************************************************************
-->
<Target Name="ComputeAvailableDevices"
DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;"
Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'"
Returns="@(Devices)">
<PropertyGroup>
<_FilterDevicesToRuntimeIdentifier Condition="'$(_XamarinUsingDefaultRuntimeIdentifier)' != 'true'">$(RuntimeIdentifier)</_FilterDevicesToRuntimeIdentifier>
</PropertyGroup>
<GetAvailableDevices
Condition="'$(IsMacEnabled)' == 'true'"
SessionId="$(BuildSessionId)"
AppBundleManifestPath="$(_AppBundleManifestPath)"
RuntimeIdentifier="$(_FilterDevicesToRuntimeIdentifier)"
SdkDevPath="$(_SdkDevPath)"
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)"
Verbose="$(Verbose)"
>
<Output TaskParameter="Devices" ItemName="Devices" />
<Output TaskParameter="DiscardedDevices" ItemName="DiscardedDevices" />
</GetAvailableDevices>
</Target>

</Project>
Loading
Loading