The new _CopyLocalBindingResources target has potential MAX_PATH issues on Windows
The _CopyLocalBindingResources target was added to ensure binding resources are copied along with the binding assembly when the binding assembly is copied around.
A problem arises on Windows however, because some binding resources have long paths, and we end up with MAX_PATH problems.
Ref: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1832539
A temporary workaround is being added here, to opt out of the _CopyLocalBindingResources target (by setting a property in the user's csproj without having to edit the Xamarin.Shared.Sdk.targets file): https://github.com/xamarin/xamarin-macios/pull/18443, but that doesn't fix the real problem.
One idea might be to detect any potential MAX_PATH issues, and if so, instead of copying all the binding resource files, create a compressed binding resource package instead on the fly (basically zip up the binding resource files).
Current workaround
Delete the _CopyLocalBindingResources target in the Xamarin.Shared.Sdk.targets file.
The path is something like this:
C:\Program Files\dotnet\packs\Microsoft.iOS.Sdk<version>\targets\Xamarin.Shared.Sdk.targets
This is the target to delete (the exact contents might vary a bit depending on the version installed, but it should be very similar):
<Target Name="_CopyLocalBindingResources" AfterTargets="ResolveAssemblyReferences" BeforeTargets="CopyFilesToOutputDirectory">
<!--
We need to copy binding resource packages (either zipped or as a
.resources bundle) together with the binding assembly when the
binding assembly is copied around. This typically happens when
another library project references the binding project, in which
case the ResolveAssemblyReference task will add the binding
library to the ReferenceCopyLocalPaths item group (when building
the library project), which will cause the binding assembly to be
copied to the output directory for the other library project.
If this isn't done, then any projects referencing the library
project (and not the binding project), won't see any binding
resource packages from the binding project.
This is not good (https://github.com/xamarin/xamarin-macios/issues/13910).
This is a target that runs after the ReferenceCopyLocalPaths item
group has been populated by the ResolveAssemblyReferences target,
and will add any binding resource packages to the
ReferenceCopyLocalPaths item group.
This is somewhat complicated by the fact that we can have
.resources bundles (i.e. directories), so we need to expand those
to all their contained files.
-->
<ItemGroup>
<!-- List all potential compressed binding resource packages next to the assemblies we're copying to the output directory -->
<_CompressedBindingPackagesFromReferencedAssembliesCandidates Include="@(ReferenceCopyLocalPaths -> '%(RootDir)%(Directory)%(Filename).resources.zip')" />
<!-- We only care about those that actually exist, and we don't want duplicates either -->
<_CompressedBindingPackagesFromReferencedAssemblies Include="@(_CompressedBindingPackagesFromReferencedAssembliesCandidates->Distinct())" Condition="Exists('%(Identity)')" />
<!-- List all potential binding resource packages next to the assemblies we're copying to the output directory -->
<_BindingPackagesFromReferencedAssembliesDirectoriesCandidates Include="@(ReferenceCopyLocalPaths -> '%(RootDir)%(Directory)%(Filename).resources')" />
<!-- We only care about those that actually exist, and we don't want duplicates either -->
<_BindingPackagesFromReferencedAssembliesDirectoriesExists Include="@(_BindingPackagesFromReferencedAssembliesDirectoriesCandidates->Distinct())" Condition="Exists('%(Identity)')" />
</ItemGroup>
<!--
We need to expand items in an item group using globs, which is
kind of tricky, because globs in item transformations aren't
treated as globs. The workaround is to use a custom task for this.
Note that this task should run remotely from Windows when there's
a Mac connected, but locally when there's not a Mac connected (for
Hot Restart builds for instance), so we're not conditioning this
task on IsMacEnabled.
-->
<GetFileSystemEntries
SessionId="$(BuildSessionId)"
DirectoryPath="@(_BindingPackagesFromReferencedAssembliesDirectoriesExists)"
Pattern="*"
Recursive="true"
IncludeDirectories="false"
>
<Output TaskParameter="Entries" ItemName="_BindingPackagesFromReferencedAssemblies" />
</GetFileSystemEntries>
<ItemGroup>
<!-- We need to set the 'DestinationSubDirectory' metadata to indicate the actual target directory for items we expanded using a wildcard -->
<_BindingPackagesFromReferencedAssembliesWithDestinationDir Include="@(_BindingPackagesFromReferencedAssemblies)">
<DestinationSubDirectory>$([System.IO.Path]::GetFileName('%(OriginalItemSpec)'))\</DestinationSubDirectory>
<DestinationSubDirectory Condition="'%(RecursiveDir)' != ''">$([System.IO.Path]::GetFileName('%(OriginalItemSpec)'))\$([System.IO.Path]::GetDirectoryName('%(RecursiveDir)'))\</DestinationSubDirectory>
</_BindingPackagesFromReferencedAssembliesWithDestinationDir>
<!-- Add what we found to ReferenceCopyLocalPaths. Note that binding resource packages should generally not be published, so we're setting PublishFolderType=None -->
<ReferenceCopyLocalPaths Include="@(_CompressedBindingPackagesFromReferencedAssemblies)">
<PublishFolderType>None</PublishFolderType>
</ReferenceCopyLocalPaths>
<ReferenceCopyLocalPaths Include="@(_BindingPackagesFromReferencedAssembliesWithDestinationDir)">
<PublishFolderType>None</PublishFolderType>
</ReferenceCopyLocalPaths>
</ItemGroup>
</Target>
The original version of the file can be found in the targets/ directory in the NuGet here: https://nuget.info/packages/Microsoft.iOS.Sdk/16.4.7054 (replace the version with the one from the path to Xamarin.Shared.Sdk.targets above).
I recently ran into a similar issue on Windows using the GeniusScanSDK.Scanflow.iOS Nuget package.
On Mac this package can be added fine but trying to add/restore this package or build the project on Windows leads to the following error:
Could not find a part of the path 'C:\Development\packages\geniusscansdk.scanflow.ios\4.12.0\lib\net7.0-ios16.1\GeniusScanSDK.ScanFlow.iOS.resources\GSSDKCore.xcframework\ios-arm64_x86_64-simulator\GSSDKCore.framework\Modules\GSSDKCore.swiftmodule\arm64-apple-ios-simulator.abi.json'.
(C:\Development\packages is my NuGet globalPackagesFolder)
Is this related to this specific issue (considering the path is 263 characters, just over the 260 of MAX_PATH) or is this more NuGet related in general?
@leonluc-dev I had this exact problem and it was 100% the MAX_PATH issue with my binding project that uses .xcframeworks. Since I have full control of it, I squished the file names down to be nearly unreadable but it got the path under 260 characters. That got past this problem.
It sounds like a workaround is if you enable long paths in Windows (it's a registry setting) and you do dotnet restore at the command line, it will actually respect the long path setting and restore the packages. The 260 limit seems to be hard and fast in VS builds. I haven't tried the workaround myself though.
Another thing you could do is to shorten your NuGet package path. I believe a lot of people have had success doing that.
For the workaround to work, I had to delete the folder "C:\Users<USER>\AppData\Local\Temp\Xamarin\HotRestart\Signing<ASSEMBLY>.app" so that it was completely regenerated when rebuilding the project