dotnet / dotnet/macios

iOS SDK fails to build .ipa when Build target is built first

Open
#20,958 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C#
Stars
2.9k
Forks
576
Avg merge
2d 12h
Merged PRs (30d)
123

Description

The .ipa package is not constructed, and an incomplete log message is emitted claiming success, when an iOS project is built with `Build` then `Publish` target order.

## Repro steps

1. Create a new Maui project.
1. Connect Visual Studio to a local mac.
1. Set the debug target dropdown to an iPhone emulator.
1. Build the project. This should succeed.
1. Open up the Developer PowerShell terminal and proceed with the following commands.
1. `dotnet build -f net8.0-ios -r ios-arm64` succeeds and builds just the .dll
1. `dotnet build -f net8.0-ios -r ios-arm64 -t:publish` succeeds and creates the .ipa package:
> Created the package: bin\Debug\net8.0-ios\ios-arm64\publish\\MauiApp2.ipa
1. But now build such that the Build target runs before the publish target:
`dotnet build -f net8.0-ios -r ios-arm64 -t:build,publish`

## Expected

The build succeeds as well as the publish target, which constructs the .ipa package.

## Actual

The build succeeds, but the Publish target skips building the .ipa package, yet prints an incomplete message trying to say that it did (though it didn't):

> MauiApp2 -> C:\temp\MauiApp2\MauiApp2\bin\Debug\net8.0-ios\ios-arm64\MauiApp2.dll
> Created the package:

[msbuild.binlog.zip](https://github.com/user-attachments/files/16447286/msbuild.binlog.zip)

## Analysis

This happens because the Build target leads the `_CoreCreateIpa` target to execute due to target dependencies, but that target is **skipped** because its condition (`'$(BuildIpa)' == 'true'`) is false.
`BuildIpa` is a property that is only set to `true` by the `_PrePublish` target. But that target doesn't run as part of Build -- only as part of Publish.
So as long as the Publish target is listed *first* on the command line or as the only target, it works because `_PrePublish` executes before `_CoreCreateIpa`. But it is vulnerable to target execution order and publish never happens if Build is also built (first).

This is particularly a problem when a repo is built through traversal projects (Microsoft.Build.Traversal SDK) because even if I ask the dirs.proj to build targets in "Publish,Build" order, the traversal only propagates those targets to the iOS/Maui project in Build,Publish order.

In general, MSBuild .targets files should be authored such that if the order in which the Targets execute is significant, that order is guaranteed rather than just relying on chance.
While docs may suggest publishing an iOS app with `dotnet publish`, doing so leads to overbuilding a repo when the iOS project has already been largely built (and signed) by a prior step in the build. Builds can be *much* faster when they never build the same target twice, and traversal projects have allowed me to do that.

## Workaround

I've hacked a workaround for the time being that ensures target order matches the Microsoft.iOS.SDK's assumptions. It relies on the fact that I set the `CI` msbuild property to `true` in CI builds where I build traversal projects.

The workaround is to add this target to my iOS project:

```xml



_PrePublish;$(CreateIpaDependsOn)


```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.