You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Visual Studio 2017 uses `.vsix` files for Xamarin.Android SDK support.
A `.vsix` file is [ZIP container with additional metadata][0], and the
[Microsoft.VSSDK.BuildTools NuGet package][1] contains various MSBuild
targets and tools to assist in creating `.vsix` files.
Add a new `build-tools/create-vsix/create-vsix.csproj` project to
create the `bin/Build$(Configuration)/Xamarin.Android.Sdk*.vsix` file,
so that we can plausibly provide per-build OSS Xamarin.Android
releases that work with Visual Studio 2017.
Unfortunately those tools were written on Windows, and not really well
tested on macOS or Linux... In particular, there are case-sensitivity
and directory-separator-char issues with the tooling, necessitating
that `MONO_IOMAP=all` be exported in order to run them:
MONO_IOMAP=all MONO_OPTIONS=--arch=64 msbuild \
build-tools/create-vsix/create-vsix.csproj /p:CreateVsixContainer=True
Meanwhile, we're still attempting to allow things to be built with
`xbuild` [^3]. Thread this needle by "special-casing" the
`$(BuildDependsOn)`, `$(CopyVsixManifestFileDependsOn)`, and
`$(DetokenizeVsixManifestFileDependsOn)` MSBuild properties so that
when the `$(CreateVsixContainer)` MSBuild property is False -- the
default -- no `.vsix` package will be created, and `xbuild` will be
able to build the project.
Similar needle threading is needed to "support" building on Linux: the
Microsoft.VSSDK.BuildTools NuGet package uses case in an inconsistent
fashion -- or is it `nuget`? -- which results in
[failures when building on Linux][2] because `nuget` extracts e.g.:
packages/Microsoft.VSSDK.BuildTools.15.0.26201/tools/vssdk/Microsoft.VsSDK.targets
while Microsoft.VSSDK.BuildTools attempts to `<Import/>` the file:
packages/Microsoft.VSSDK.BuildTools.15.0.26201/tools/VSSDK/Microsoft.VsSDK.targets
`vssdk` != `VSSDK` on case-sensitive filesystems, so this results in
an error on Ubuntu (and presumably case-senstive macOS as well).
Handle the Linux case by extending the `xbuild` case: *even when*
`$(CreateVsixContainer)` is True, we won't actually build the `.vsix`
unless the `$(VsSDKInstall)` directory exists, which is the
`tools/VSSDK` path.
Building with `$(CreateVsixContainer)` set to True will require using
`msbuild` with `MONO_IOMAP=all` and `MONO_OPPTIONS=--arch=64`
exported, while using a case-insensitive filesystem.
The new `make create-vsix CONFIGURATIONS=Debug` target can be used to
explicitly create the `Xamarin.Android.Sdk*.vsix` file.
One problem with creating `.vsix` files: macOS still defaults to using
a 32-bit process for `mono`, and `make create-vsix` regularly fails
for me with an `OutOfMemoryException` when attempting to generate a
`.vsix` file ~600-700+MB in size. (Why so large? In part because for
Debug configuration we're including un-`strip`'d native libraries;
`libmonosgen-2.0.dll` is *237MB* in size (!); it's closer to 5MB when
`strip`'d, but any un-`strip`'d MXE-generated native libraries to the
`.vsix` file quickly results in `OutOfMemoryException`s.)
A 64-bit mono can be used by using `mono64` -- which isn't easily done
with `msbuild` -- or by using `mono --arch=64`, which *can* be done
with `msbuild` by exporting `MONO_OPTIONS=--arch=64`.
The `make create-vsix` target does this.
Finally, once we have a `.visx` being created, we then examine the
*contents* of the `.vsix` file, which is...weird:
$MSBuild/Xamarin/Android/Xamarin.Android.CSharp.targets # Desirable
$ReferenceAssemblies/Microsoft/Framework/MonoAndroid/v1.0/Xamarin.Android.CSharp.targets # wat?
$ReferenceAssemblies/Microsoft/Framework/MonoAndroid/v1.0/Facades/Xamarin.Android.CSharp.targets # really?!
$ReferenceAssemblies/Microsoft/Framework/MonoAndroid/v7.1/Xamarin.Android.CSharp.targets # !!!!
Turns Out™, the problem was due to `@(ProjectReference)`. We're
(ab)using `@(ProjectReference)` to explicitly specify project
dependencies, and the (implicit) project build order.
Unexpectedly (forgetten?), MSBuild *also* copies the *outputs* of
`@(ProjectReference)`s into the `$(OutputPath)` of the current
project.
Since e.g. `Mono.Posix.csproj` had a reference on
`Xamarin.Android.Build.Tasks.csproj`, the result of this is that the
`$(OutputPath)` of `Mono.Posix.csproj` --
`$prefix/lib/xbuild-frameworks/MonoAndroid/v1.0` -- also contained the
`%(None.CopyToOutputDirectory)` items from
`Xamarin.Android.Build.Tasks.csproj`.
Oops.
The fix is to set `%(ProjectReference.Private)` to False, which
disables this copying of additional and undesirable files.
[0]: https://msdn.microsoft.com/en-us/library/dd997148.aspx
[1]: https://www.nuget.org/packages/Microsoft.VSSDK.BuildTools/
[2]: https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-anroid-linux-pr-builder/297/consoleText
[^3]: But for how much longer?
0 commit comments