Skip to content

Conversation

@jonpryor
Copy link
Contributor

Cecil is an "interesting" complication: it's a dependency of
Java.Interop, but Xamarin.Android use requires that it be "vendorized"
-- renamed as Xamarin.Android.Cecil.dll -- to avoid previously seen
issues because it's an unsigned assembly, and thus There Can Be Only
One Mono.Cecil.dll loaded into an AppDomain, and whichever is loaded
first "wins", but that version may not be compatible with what other
assemblies in the AppDomain need, and...

Renaming the assembly was just seen as the easiest solution.

This choice hasn't been without its own shortcomings; see e.g. commits
168c94d ("priorities"), cfa74d3 (downstream build system changes),
5eeb287 ("rebuilds are hard"), 6717275 ("because of 168c94d,
xamarin-android 'owns' the checkout, but that may not be API
compatible, oops"), etc., etc.

Plus, it kinda became moot with xamarin/xamarin-android@0c9f83b7
which removed the mono git submodule from xamarin-android. Instead
of building mono from source -- and, implicitly, building cecil from
source -- mono was instead obtained from a "mono archive" which
contained a prebuilt Mono.Cecil.dll which was "renamed" to
Xamarin.Android.Cecil.dll.

Which meant that in a xamarin-android build, cecil should never be
built from source anymore, which in turn meant that -- give or take
the occasional build system bug --
Java.Interop/src/Xamarin.Android.Cecil and company were "dead code",
as far as the commercial product is concerned.

Meanwhile, the existance of src/Xamarin.Android.Cecil proved to be
an ongoing source of maintenance pain, as -- depending on the IDE --
it couldn't build reliably, or would rebuild when it shouldn't have.

Rethink the whole Cecil relationship. If xamarin-android doesn't
require a cecil source checkout, why not ditch it entirely?

Remove the external/cecil git submodule, and the
src/Xamarin.Android.Cecil* projects, and replace them with NuGet
package references to the Mono.Cecil NuGet package.

What this means is that a "pure Java.Interop" build will now have
different assembly references than the "same" utilities built from
xamarin-android. For example, generator.exe, when built from
Java.Interop, will reference Mono.Cecil.dll, while it will instead
reference Xamarin.Android.Cecil.dll when built from xamarin-android.

The $(CecilSourceDirectory) MSBuild property is used to determine
whether the Mono.Cecil NuGet package or the Xamarin.Android.Cecil.dll
assembly reference should be used at build time.

@jonpryor jonpryor requested a review from jpobst March 10, 2020 00:24
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 10, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...
@jonpryor
Copy link
Contributor Author

...and the xamarin-android side... dotnet/android#4376

DO NOT MERGE until dotnet/android#4376 is acceptable.

jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 10, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 10, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...
<ItemGroup Condition=" '$(CecilSourceDirectory)' == '' ">
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
</ItemGroup>
<ItemGroup Condition=" '$(CecilSourceDirectory)' != '' ">
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if this condition should be:

Exists('$(UtilityOutputFullPath)Xamarin.Android.Cecil.dll')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea!

jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 10, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...
@jpobst
Copy link
Contributor

jpobst commented Mar 10, 2020

/azp run

@azure-pipelines
Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

@jpobst
Copy link
Contributor

jpobst commented Mar 10, 2020

There's a couple of now unneeded Cecil files here: https://github.com/xamarin/java.interop/tree/master/external

@jonpryor jonpryor force-pushed the jonp-cecil-nuget branch 2 times, most recently from 96cc1c2 to d9d8345 Compare March 10, 2020 18:47
@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

@jonpryor
Copy link
Contributor Author

Short-form SDK project migration needs to happen first: #547

@jonpryor
Copy link
Contributor Author

PR #547 has been merged and this PR has been rebased.

jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 18, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...
Copy link
Contributor

@jpobst jpobst left a comment

Choose a reason for hiding this comment

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

❤️ I played with this for a bit locally in VS2019 and it seems great.

jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 19, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 19, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 19, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)

Note: `$(TargetFrameworks)` throws a wrench into things.  If two
`$(TargetFramework)` builds share the same output directory, the
`IncrementalClean` target will *remove files created by previous
builds*, e.g. when e.g. `generator.csproj` builds the `netcoreapp3.1`
framework, it will *delete* the `generator.exe` built by the `net472`
framework, which results in subsequent build breaks.

The only path to sanity is to *ensure* that different
`$(TargetFramework)` builds have *completely separate* `$(OutputPath)`
values.

The "normal" approach to doing this is for `$(OutputPath)` to end with
`$(TargetFramework)`.

The problem here is that xamarin-android is setup so that we mirror
the installation directory, with e.g. `bin/Debug` being an
"installation root", and that installation root *won't* (normally?)
have *both* net472 and netcoreapp3.1 outputs for the "same" project.

The "solution" is to use the new `$(UtilityOutputFullPathCoreApps)`
property within Java.Interop to ensure that Java.Interop "utility"
apps -- normally placed into
`bin/Debug/lib/xamarin.android/xbuild/Xamarin/Android` -- are
*instead* placed into `bin/Debug-netcoreapp3.1` for netcoreapp3.1
builds.

This ensure that things *actually build*.  Locally.  YMMV.
Cecil is an "interesting" complication: it's a dependency of
Java.Interop, but Xamarin.Android use requires that it be "vendorized"
-- renamed as `Xamarin.Android.Cecil.dll` -- to avoid previously seen
issues because it's an unsigned assembly, and thus There Can Be Only
One `Mono.Cecil.dll` loaded into an AppDomain, and whichever is loaded
first "wins", but that version may not be compatible with what other
assemblies in the AppDomain need, and...

Renaming the assembly was just seen as the easiest solution.

This choice hasn't been without its own shortcomings; see e.g. commits
168c94d ("priorities"), cfa74d3 (downstream build system changes),
5eeb287 ("rebuilds are hard"), 6717275 ("because of 168c94d,
xamarin-android 'owns' the checkout, but that may not be API
compatible, oops"), etc., etc.

Plus, it kinda became moot with [dotnet/android@0c9f83b7][0]
which removed the `mono` git submodule from xamarin-android.  Instead
of building mono from source -- and, implicitly, building *cecil* from
source -- mono was instead obtained from a "mono archive" which
contained a prebuilt `Mono.Cecil.dll` which was "renamed" to
`Xamarin.Android.Cecil.dll`.

Which meant that in a xamarin-android build, cecil should *never* be
built from source anymore, which in turn meant that -- give or take
the occasional build system bug --
`Java.Interop/src/Xamarin.Android.Cecil` and company were "dead code",
as far as the commercial product is concerned.

Meanwhile, the existance of `src/Xamarin.Android.Cecil` proved to be
an ongoing source of maintenance pain, as -- depending on the IDE --
it couldn't build reliably, or would rebuild when it shouldn't have.

Rethink the whole Cecil relationship.  If xamarin-android doesn't
require a cecil source checkout, why not ditch it entirely?

Remove the `external/cecil` git submodule, and the
`src/Xamarin.Android.Cecil*` projects, and replace them with NuGet
package references to the [`Mono.Cecil` NuGet package][1].

What this means is that a "pure Java.Interop" build will now have
*different* assembly references than the "same" utilities built from
xamarin-android.  For example, `generator.exe`, when built from
Java.Interop, will reference `Mono.Cecil.dll`, while it will instead
reference `Xamarin.Android.Cecil.dll` when built from xamarin-android.

The `$(CecilSourceDirectory)` MSBuild property is used to determine
whether the Mono.Cecil NuGet package or the `Xamarin.Android.Cecil.dll`
assembly reference should be used at build time.

[0]: dotnet/android@0c9f83b
[1]: https://www.nuget.org/packages/Mono.Cecil/0.11.2
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 20, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)

Note: `$(TargetFrameworks)` throws a wrench into things.  If two
`$(TargetFramework)` builds share the same output directory, the
`IncrementalClean` target will *remove files created by previous
builds*, e.g. when e.g. `generator.csproj` builds the `netcoreapp3.1`
framework, it will *delete* the `generator.exe` built by the `net472`
framework, which results in subsequent build breaks.

The only path to sanity is to *ensure* that different
`$(TargetFramework)` builds have *completely separate* `$(OutputPath)`
values.

The "normal" approach to doing this is for `$(OutputPath)` to end with
`$(TargetFramework)`.

The problem here is that xamarin-android is setup so that we mirror
the installation directory, with e.g. `bin/Debug` being an
"installation root", and that installation root *won't* (normally?)
have *both* net472 and netcoreapp3.1 outputs for the "same" project.

The "solution" is to use the new `$(UtilityOutputFullPathCoreApps)`
property within Java.Interop to ensure that Java.Interop "utility"
apps -- normally placed into
`bin/Debug/lib/xamarin.android/xbuild/Xamarin/Android` -- are
*instead* placed into `bin/Debug-netcoreapp3.1` for netcoreapp3.1
builds.

This ensure that things *actually build*.  Locally.  YMMV.
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 21, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)

Note: `$(TargetFrameworks)` throws a wrench into things.  If two
`$(TargetFramework)` builds share the same output directory, the
`IncrementalClean` target will *remove files created by previous
builds*, e.g. when e.g. `generator.csproj` builds the `netcoreapp3.1`
framework, it will *delete* the `generator.exe` built by the `net472`
framework, which results in subsequent build breaks.

The only path to sanity is to *ensure* that different
`$(TargetFramework)` builds have *completely separate* `$(OutputPath)`
values.

The "normal" approach to doing this is for `$(OutputPath)` to end with
`$(TargetFramework)`.

The problem here is that xamarin-android is setup so that we mirror
the installation directory, with e.g. `bin/Debug` being an
"installation root", and that installation root *won't* (normally?)
have *both* net472 and netcoreapp3.1 outputs for the "same" project.

The "solution" is to use the new `$(UtilityOutputFullPathCoreApps)`
property within Java.Interop to ensure that Java.Interop "utility"
apps -- normally placed into
`bin/Debug/lib/xamarin.android/xbuild/Xamarin/Android` -- are
*instead* placed into `bin/Debug-netcoreapp3.1` for netcoreapp3.1
builds.

This ensure that things *actually build*.  Locally.  YMMV.
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 25, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)

Note: `$(TargetFrameworks)` throws a wrench into things.  If two
`$(TargetFramework)` builds share the same output directory, the
`IncrementalClean` target will *remove files created by previous
builds*, e.g. when e.g. `generator.csproj` builds the `netcoreapp3.1`
framework, it will *delete* the `generator.exe` built by the `net472`
framework, which results in subsequent build breaks.

The only path to sanity is to *ensure* that different
`$(TargetFramework)` builds have *completely separate* `$(OutputPath)`
values.

The "normal" approach to doing this is for `$(OutputPath)` to end with
`$(TargetFramework)`.

The problem here is that xamarin-android is setup so that we mirror
the installation directory, with e.g. `bin/Debug` being an
"installation root", and that installation root *won't* (normally?)
have *both* net472 and netcoreapp3.1 outputs for the "same" project.

The "solution" is to use the new `$(UtilityOutputFullPathCoreApps)`
property within Java.Interop to ensure that Java.Interop "utility"
apps -- normally placed into
`bin/Debug/lib/xamarin.android/xbuild/Xamarin/Android` -- are
*instead* placed into `bin/Debug-netcoreapp3.1` for netcoreapp3.1
builds.

This ensure that things *actually build*.  Locally.  YMMV.
jonpryor added a commit to jonpryor/xamarin-android that referenced this pull request Mar 26, 2020
***DO NOT MERGE***

Context: dotnet/java-interop#597

Just testing to see if dotnet/java-interop#597 works...

Need to use `msbuild /restore` for all builds to allow
`Java.Interop.Tools.Cecil` to build; see:

dotnet#4376 (comment)

Note: `$(TargetFrameworks)` throws a wrench into things.  If two
`$(TargetFramework)` builds share the same output directory, the
`IncrementalClean` target will *remove files created by previous
builds*, e.g. when e.g. `generator.csproj` builds the `netcoreapp3.1`
framework, it will *delete* the `generator.exe` built by the `net472`
framework, which results in subsequent build breaks.

The only path to sanity is to *ensure* that different
`$(TargetFramework)` builds have *completely separate* `$(OutputPath)`
values.

The "normal" approach to doing this is for `$(OutputPath)` to end with
`$(TargetFramework)`.

The problem here is that xamarin-android is setup so that we mirror
the installation directory, with e.g. `bin/Debug` being an
"installation root", and that installation root *won't* (normally?)
have *both* net472 and netcoreapp3.1 outputs for the "same" project.

The "solution" is to use the new `$(UtilityOutputFullPathCoreApps)`
property within Java.Interop to ensure that Java.Interop "utility"
apps -- normally placed into
`bin/Debug/lib/xamarin.android/xbuild/Xamarin/Android` -- are
*instead* placed into `bin/Debug-netcoreapp3.1` for netcoreapp3.1
builds.

This ensure that things *actually build*.  Locally.  YMMV.
@jonpryor jonpryor merged commit 56c92c7 into dotnet:master Mar 27, 2020
@jpobst jpobst added this to the d16-7 milestone Apr 10, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Apr 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants