Skip to content

Commit

Permalink
Add documentation related to msvcurt-c1xx (and a few other items)
Browse files Browse the repository at this point in the history
  • Loading branch information
vatsan-madhavan committed Apr 8, 2020
1 parent b7dc835 commit 7e162b7
Show file tree
Hide file tree
Showing 6 changed files with 685 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Documentation/C++-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# C++ Notes

- `$(RepoRoot)eng\WpfArcadeSdk\tools\` contains `Wpf.Cpp.Props`,`Wpf.Cpp.targets`, `Wpf.Cpp.PrivateTools.props` and `Wpf.Cpp.PrivateTools.targets`, which contain all the important C++ related properties
- We need to undefine the `TargetFramework` property when `ProjectReference`-ing a C++/CLI project from a C# project
- When a C++/CLI project is built directly from the solution, `TargetFramework=netcoreapp3.0` etc. property is NOT passed to it.
- When the same project is built via a C# project, it receives a global property `TargetFramework=netcoreapp3.0`.
- This results in msbuild treating those two instances as _sufficiently different_ and builds them independently.
- In turn, the same project is built twice (often simultaneously), and results in simultaneous writes to the PDB etc.
- This leads to build failures.
- The solution is to delete `TargetFramework` property when specifying `ProjectReference` to a C++/CLI project from a C# project, like this:
`<ProjectReference Include="$(WpfSourceDir)PresentationCore\CPP\PresentationCoreCpp.vcxproj">
<UndefineProperties>TargetFramework;TargetFrameworks</UndefineProperties>
</ProjectReference>`

### Deprecated Compiler Features

- /nowarn:D9035 is now being passed to build.ps1 in order to suppress the following C++ compiler warnings:
- cl : Command line error D9035: option 'clr:pure' has been deprecated and will be removed in a future release
- cl : Command line error D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future release
44 changes: 44 additions & 0 deletions Documentation/LocalMarkupCompilation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
### Local Markup Compilation

This repo builds PresentationBuildTasks.dll and the WindowsDesktop SDK itself, which are needed for markup-compilation.

Some of the projects in this repo require Markup Compilation themselves - for e.g., theme assemblies.

Here, we outline the scheme used by this repo to bootstrap markup compilation before a full-fledged WindowsDesktop SDK is available. All projects in this repo are base .NET Core SDK projects that utilize additional props/targets outlined below to enable markup compilation.

Local Markup Compilation is implemented in the following files:

- eng\WpfArcadeSdk\tools\Pbt.props
- eng\WpfArcadeSdk\tools\Pbt.targets
- eng\WpfArcadeSdk\tools\NoInternalTypeHelper.targets


See comments in these targets for further details. Some additional work is needed to make this work completely.
It can be enabled for a project by setting this:

```
<PropertyGroup>
<InternalMarkupCompilation>true</InternalMarkupCompilation>
</PropertyGroup>
```

Also, it's a good idea to use the following properties:

```
<PropertyGroup>
<NoInternalTypeHelper>true</NoInternalTypeHelper>
<GenerateDependencyFile>false<GenerateDependencyFile>
</PropertyGroup>
```

Please take a look at `src\Microsoft.DotNet.Wpf\src\PresentationUI\PresentationUI.csproj` to see how this is utilized.


In addition to these, care must be taken for the following:

- Use `<EmbeddedResource>` instead of `<Resource>`
- `PresentationBuildTask` will strip out `<Resource>` items during `_CompileTemporaryAssembly` phase. Using `EmbeddedResource` is equivalent (esp. in for `Xlf` based string resource generation with `Arcade.Sdk`) and will not be adversely affected by `PresentationBuildTasks` transformations.
- Always use `<NetCoreReference>` instead of implicitly acquiring the full set of `Microsoft.NetCore.App` references.
- `Microsoft.NetCore.App` contains a version `WindowsBase` that clashes with WPF's `WindowsBase` during markup compilation.
- To avoid this clash, we must always specify the references we need explicitly.
- Also, our code-base requires that all references be specified explicitly anyway to avoid inadvertent reference-creep to bug-fixes.
49 changes: 49 additions & 0 deletions Documentation/c++-private-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# C++ Private Tools

### What is msvcurt-c1xx in global.json?

In late Feb 2019, we discovered a bug in the C++/CLI compiler for .NET Core that requried the front-end (`c1xx.dll`) and the libraries (`msvcurt(d)_netcore.lib`) to be rebuilt.

A fix was available in mid Mar, 2019, but this change could not make it into Dev16.0, and Dev16.1 Preview1 build weren't coming out until later in Apr, 2019.

In collaboration with the C++ team, we decided to build our repo using private (but signed) copies of `c1xx.dll` and `msvcurt(d)_netcore.dll`.

We have uploaded these private DLL's to an Azure blob at this location using Arcade's [_Native Toolset Bootstrapping_](https://github.com/dotnet/arcade/blob/master/Documentation/NativeToolBootstrapping.md) process.

This results in the the packages being uploaded to locations like these:

```
- https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/msvcurt-c1xx/msvcurt-c1xx-0.0.0.3-win32-x86.zip
- https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/msvcurt-c1xx/msvcurt-c1xx-0.0.0.3-win64-x64.zip
```

PS: The version at the time this note was written is `0.0.0.3`. The version might be updated in the future and `global.json` would contain the correct version.

The version (`0.0.0.3`) is arbitrary, and simply refers to the the number of different versions we have uploaded as part of a trial-and-error approach to making our build work with these private compiler-bits.

In Azure Storage Explorer, the blobs can be found at this location:

```
- Dotnet Engineering Services
- Storage Accounts
- netcorenativeassets
- Blob Containers
- resource-packages
- external
- windows
- msvcurt-c1xx
- msvcurt-c1xx-0.0.0.3-win64-x64.zip
- msvcurt-c1xx-0.0.0.3-win32-x86.zip
```

Writing to this storage account requires special permissions and is only available to Microsoft Employees - please work with DncEng if you need to do this. Also refer to [Native Toolset Bootstrapping documentation](https://github.com/dotnet/arcade/blob/master/Documentation/NativeToolBootstrapping.md).


#### How does msvcurt-c1xx work?

- global.json + Arcade's toolset restore-phase will download the blobs and lay it out under `$(RepoRoot).tools\native\bin\msvcurt-c1xx\0.0.0.3\`
- This will happen before build starts.
- WPF's `Wpf.Cpp.props` + `Wpf.Cpp.targets` identifies the right copy of `c1xx.dll` and `msvcurt(d)_netcore.lib` and passes it to `cl.exe` and `link.exe` - thus overriding the copies that shipeed with Visual Studio.
- For testing, you can prepare appropriate zip-bundles as described in the _Native Toolset Bootstrapping_ documentation and place them under `$env:USERPROFILE\.netcoreeng\native\temp` folder.
- This is the _cache_ location used by the Arcade scripts for downloading the zip bundles from Azure Blob storage to local disk.
- When the build-scripts observe that the zip file is already present in this location, they will not attempt to download the zip file from the blob.
26 changes: 26 additions & 0 deletions Documentation/cycle-breakers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Cycle Breakers

Certain assemblies in WPF contain cycles - they use types from other assemblies which, in turn, use types from them, effectively creating a cycle.

To allow assemblies to compile, we introduced cycle-breaking assemblies which re-define the problematic types (without an implementation and/or closure) and allow projects to referene them instead of referencing themselves, and break the cycle.

There are 2 types of cycle breaking assemblies:

* **Implementation cycle breakers**

An implementation cycle breaker assembly is referenced directly from a project that uses types from another "cycled" assembly in its implementation. An implemention cycle breaking assembly is likely to include types *and* their closures, because the closure may be used from the calling assembly.

* **API cycle breakers**

An API cycle breaking assembly is an assembly is likely referenced from a ref-assembly, or an implementation cycle breaking assembly. It is likely to not contain type closures, as much as possible, and generally minimal - way smaller in footprint than an implementation cycle breaker.

Examples of such assemblies are under *src\Microsoft.DotNet.Wpf\cycle-breakers*:

> Ex: PresentationFramework\PresentationFramework-PresentationUI-api-cycle.csproj
In the previous example, this assembly contains types from PresentationFramework and is exposing them to PresentationUI as an api-cycle-breaker. You will likely see minimal types here.


> Ex: PresentationFramework\PresentationFramework-ReachFramework-impl-cycle.csproj
In the previous example, this assembly contains types from PresentationFramework and is exposing them to the ReachFramework's implementation. This is what we call an implementation cycle-breaker and you will likely see types with full closures here.
Loading

0 comments on commit 7e162b7

Please sign in to comment.