Build fails after clean with NETSDK1042: PlatformManifest.txt missing when using clr+libs subset
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
## Description
`./build.sh clr+libs -rc checked` (or any configuration) fails after a clean build with multiple `NETSDK1042` errors:
```
error NETSDK1042: Could not load PlatformManifest from
'artifacts/bin/microsoft.netcore.app.ref/data/PlatformManifest.txt' because it did not exist.
```
The errors come from OOB library ref/src projects (e.g., `System.CodeDom`, `System.Reflection.MetadataLoadContext`, `Microsoft.Extensions.*`).
## Root Cause
In `eng/Subsets.props`, the `libs` subset expands to `libs.native+libs.sfx+libs.oob+libs.pretest`. All four are added as `ProjectToBuild` items with `Category="libs"` and become peer `ProjectReference` entries in `Build.proj` (which uses `Microsoft.Build.Traversal`). The Traversal SDK builds them in parallel with no explicit ordering between siblings.
- **`pretest.proj`** (from `libs.pretest`) generates `artifacts/bin/microsoft.netcore.app.ref/data/PlatformManifest.txt` via its `GenerateFileVersionPropsRefPack` target.
- **`oob.proj`** (from `libs.oob`) builds OOB ref/src projects that target `net11.0`. The SDK's `ConflictResolution.targets` resolves the locally-built ref pack and requires `PlatformManifest.txt` to exist.
On incremental builds, this works because the manifest file is already on disk from a prior build. After a clean (`git clean -xdf` or deleting `artifacts/`), the file doesn't exist, and OOB projects can start resolving before `pretest.proj` generates it.
## Confirmed via binlog analysis
The `artifacts/log/Debug/Build.binlog` shows:
- `_subset` correctly expands to include `libs.pretest`
- `pretest.proj` is added to `ProjectToBuild` items
- `pretest.proj` **never actually builds as a project** in the binlog — the OOB failures abort the build first
- All 15 errors are `NETSDK1042` from OOB ref/src projects
## Suggested Fix
Move the **ref pack** PlatformManifest generation (`GenerateFileVersionPropsRefPack` target + `GetSharedFrameworkRuntimeFiles` + `GenerateFileVersionProps` UsingTask) from `src/libraries/pretest.proj` into `src/libraries/sfx-finish.proj`. This works because:
1. `sfx-finish.proj` already writes `FrameworkList.xml` and `PackageOverrides.txt` to the same `$(MicrosoftNetCoreAppRefPackDataDir)` directory
2. `sfx-finish.proj` is part of `sfx.proj` (`libs.sfx` subset), which completes before `oob.proj` children resolve their targeting pack (OOB projects have transitive `ProjectReference` dependencies on SFX assemblies)
3. The runtime pack files needed as inputs are already on disk by the time `sfx-finish.proj` runs (they are outputs of `sfx-src.proj`, which `sfx-finish.proj` already depends on via `sfx.proj`)
4. The **runtime pack** manifest can remain in `pretest.proj` since only test infrastructure needs it
Alternatively, a simpler (but less clean) fix would be to add an explicit `ProjectReference` from `oob.proj` to `pretest.proj`.
## Reproduction
```bash
# Clean everything
git clean -xdf artifacts/
# Build — fails with NETSDK1042
./build.sh clr+libs -rc checked
```
## Workaround
Build `libs.pretest` first to generate the manifest, then run the full build:
```bash
./build.sh libs.pretest -rc checked
./build.sh clr+libs -rc checked
```
/cc @dotnet/runtime-infrastructure
Contributor guide
Assessment
This issue has not been assessed yet.