[net6] Infer Xcode without VSMac being installed
Originally posted in https://github.com/dotnet/net6-mobile-samples/issues/126
I have multiple Xcode versions installed:
-rw-r--r--@ 1 alklig admin 836 Feb 8 15:06 Xcode
lrwxr-xr-x 1 root admin 28 Feb 8 15:08 Xcode.app -> /Applications/Xcode_12.4.app
drwxr-xr-x 3 alklig staff 96 Jun 4 2018 Xcode94.app
drwxr-xr-x 3 alklig staff 96 Oct 8 2020 Xcode_12.1.app
drwxr-xr-x 4 alklig staff 128 Feb 8 15:07 Xcode_12.4.app
dotnet build HelloiOS produces
/usr/local/share/dotnet/packs/Microsoft.iOS.Sdk/14.4.100-ci.main.1192/tools/msbuild/iOS/Xamarin.Shared.targets(891,3): error : Could not find a valid Xcode app bundle at '/Applications/Xcode_12.3.app'. Please update your Apple SDK location in Visual Studio's preferences (Projects > SDK Locations > Apple > Apple SDK). [/Users/alklig/work/net6-mobile-samples/HelloiOS/HelloiOS.csproj]
/usr/local/share/dotnet/packs/Microsoft.iOS.Sdk/14.4.100-ci.main.1192/tools/msbuild/iOS/Xamarin.Shared.targets(891,3): error : [/Users/alklig/work/net6-mobile-samples/HelloiOS/HelloiOS.csproj]
Build FAILED.
because in VS for Mac I had the Apple SDK setting pointing to /Applications/Xcode_12.3.app (which I deleted).
the CLI builds should use the result of xcode-select -p for the SDK, not the VS for Mac setting.
A tricky part is that dotnet msbuild files are re-using / sharing code with legacy ones. We do not want (and must take care) to change the existing behaviour.
Also xcode-select -p is not really the best way as it can change as you build something (ask me how I know).
We should be using xcrun everywhere [1]. That's almost identical to xcode-select -p (by default) but you can override it with DEVELOPER_DIR so, in theory [2], more than one build can happen simultaneously with different Xcode. In practice you have, at least, a better chance to have a complete build with the same tool chain :-)
That override also means VSfM could use its Xcode location to set that variable - and nothing more should be needed.
For legacy: msbuild needs to check DEVELOPER_DIRand, if not present, go back to check with VSfM config (current check).
For dotnet: use DEVELOPER_DIR and, if not present, define it with xcode-select -p making the whole build consistent.
[1] there are still (even if many were fixed) msbuild tasks that call tools directly with their own logic.
[2] some tools (like ibtool) starts a short-lived daemon to avoid respawing the tool many time consecutively so YMMV...
One point to have in mind here is that to change xcode-select -p you need sudo, while modifying the VSMac setting doesn't, it's a per-user setting.
Just for reference, this is how we find Xcode:
- If the
MD_APPLE_SDK_ROOTenvironment variable is set, use that. - If the
~/Library/Preferences/Xamarin/Settings.plistfile exists, use that. - Check
xcode-select --print-path. - Use
/Applications/Xcode.app.
This happens in this file: https://github.com/xamarin/Xamarin.MacDev/blob/14d53612d4624459a7ae617141c45e940ada6df5/Xamarin.MacDev/AppleSdkSettings.cs
One idea for improving this is to deprecate ~/Library/Preferences/Xamarin/Settings.plist, and instead add support for an MSBuild property to specify the Xcode to use.
When/how does ~/Library/Preferences/Xamarin/Settings.plist get created? just in VSM when you set the path?
When/how does ~/Library/Preferences/Xamarin/Settings.plist get created? just in VSM when you set the path?
Correct, VSM creates this file (maybe VS Windows too, not entirely sure about that).