Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ When an item specifies *FrameworkSpecific=true*, the project's target framework
|------------------|-------------------|
| content (*) | true |
| lib | true |
| ref | true |
| dependency (**) | true |
| frameworkReference (**) | true |
| build | false |
Expand All @@ -236,7 +237,7 @@ When an item specifies *FrameworkSpecific=true*, the project's target framework

\** *dependency* and *frameworkReference* are pseudo folders containing the package references and framework (`<Reference ...`) references.

\** tool(s), native, runtime(s), ref, analyzer(s), source/src, any custom folder.
\*** tool(s), native, runtime(s), analyzer(s), source/src, any custom folder.

The `PackFolder` property (at the project level) determines the *PackFolder* metadata value for the build outputs of the project (and its xml docs, pdb and other related files like satellite assemblies). It defaults to `lib`.

Expand All @@ -260,7 +261,8 @@ Whether items are packed by default or not is controlled by properties named aft
| PackReadme | true |
| PackSymbols | true if PackBuildOutput=true (*) |
| PackSatelliteDlls | true if PackBuildOutput=true (**) |
| PackDependencies| empty (***) |
| PackRefAssembly | true if PackBuildOutput=true and ProduceReferenceAssembly=true (***) |
| PackDependencies| empty (****) |
| PackFrameworkReferences | true if PackFolder=lib, false if PackDependencies=false |
| PackProjectReferences | true |

Expand All @@ -272,7 +274,9 @@ Whether items are packed by default or not is controlled by properties named aft
\** Satellite resources can come from the main project or from dependencies, if those PackageReferences
have `PrivateAssets=all`.

\*** In some scenarios, you might want to turn off packing behavior for all PackageReference and FrameworkReferences alike. Setting PackDependencies=false achieves that.
\*** When [ProduceReferenceAssembly](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/output#producereferenceassembly) is enabled, the reference assembly is automatically included in the `ref/[tfm]` folder alongside the implementation in `lib/[tfm]`.

\**** In some scenarios, you might want to turn off packing behavior for all PackageReference and FrameworkReferences alike. Setting PackDependencies=false achieves that.


The various supported item inference are surfaced as `<PackInference Include="Compile;Content;None;..." />` items, which are ultimately evaluated together with the metadata for the individual items. These make the package inference candidates. You can also provide an exclude expression for that evaluation so that certain items are excluded by default, even if every other item of the same type is included. For example, to pack all `Content` items, except those in the `docs` folder, you can simply update the inference item like so:
Expand Down
11 changes: 11 additions & 0 deletions src/NuGetizer.Tasks/NuGetizer.Inference.targets
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ Copyright (c) .NET Foundation. All rights reserved.
<!-- Whether to include @(DebugSymbolsProjectOutputGroupOutput) items in the package -->
<PackSymbols Condition="'$(PackSymbols)' == '' and '$(PackBuildOutput)' == 'true'">true</PackSymbols>

<!-- Whether to include the reference assembly ($(TargetRefPath)) in the package when ProduceReferenceAssembly=true -->
<PackRefAssembly Condition="'$(PackRefAssembly)' == '' and '$(PackBuildOutput)' == 'true' and '$(ProduceReferenceAssembly)' == 'true'">true</PackRefAssembly>

<!-- Whether to include framework references (%(ReferencePath.ResolvedFrom)' == '{TargetFrameworkDirectory}') in the package -->
<PackFrameworkReferences Condition="'$(PackFrameworkReferences)' == '' and '$(PackDependencies)' == 'false'">false</PackFrameworkReferences>
<!-- Only default to true if the project isn't a nuget packaging project itself and its primary output is lib. -->
Expand Down Expand Up @@ -402,6 +405,14 @@ Copyright (c) .NET Foundation. All rights reserved.
<_InferredPackageFile Include="@(_InferredProjectOutput -> Distinct())" />
</ItemGroup>

<ItemGroup Label="Reference Assembly Inference" Condition="'$(PackRefAssembly)' == 'true' and '$(PackAsPublish)' != 'true' and '$(TargetRefPath)' != ''">
<!-- Include the reference assembly in the ref folder when ProduceReferenceAssembly=true -->
<_InferredPackageFile Include="$(TargetRefPath)">
<PackFolder>Ref</PackFolder>
<FrameworkSpecific>true</FrameworkSpecific>
</_InferredPackageFile>
</ItemGroup>

<ItemGroup Label="SatelliteDll Resources from Dependencies" Condition="'$(PackBuildOutput)' == 'true' and '$(PackAsPublish)' != 'true'">
<!-- Include transitive resources if their NuGetPackageId has PrivateAssets=all and Pack!=false only. -->
<_InferredPackageFile Include="@(ResourceCopyLocalItems)"
Expand Down
1 change: 1 addition & 0 deletions src/NuGetizer.Tasks/NuGetizer.props
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ Copyright (c) .NET Foundation. All rights reserved.
</PackFolderKind>
<PackFolderKind Include="Ref">
<PackageFolder>ref</PackageFolder>
<FrameworkSpecific>true</FrameworkSpecific>
</PackFolderKind>
<PackFolderKind Include="Analyzer;Analyzers">
<PackageFolder>analyzers</PackageFolder>
Expand Down
143 changes: 143 additions & 0 deletions src/NuGetizer.Tests/InlineProjectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1097,5 +1097,148 @@ public void when_dependency_is_development_dependency_then_can_explicitly_pack_i
Assert.Equal("ThisAssembly.Constants", manifest.Metadata.DependencyGroups.First().Packages.First().Id);
}
}

[Fact]
public void when_produce_reference_assembly_then_includes_ref_assembly()
{
var result = Builder.BuildProject(
"""
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
</Project>
""", output: output);

result.AssertSuccess(output);

// Should have the main assembly in lib
Assert.Contains(result.Items, item => item.Matches(new
{
Extension = ".dll",
PackFolder = PackFolderKind.Lib
}));

// Should also have the reference assembly in ref
Assert.Contains(result.Items, item => item.Matches(new
{
Extension = ".dll",
PackFolder = PackFolderKind.Ref
}));
}

[Fact]
public void when_produce_reference_assembly_false_then_does_not_include_ref_assembly()
{
var result = Builder.BuildProject(
"""
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>
</Project>
""", output: output);

result.AssertSuccess(output);

// Should have the main assembly in lib
Assert.Contains(result.Items, item => item.Matches(new
{
Extension = ".dll",
PackFolder = PackFolderKind.Lib
}));

// Should NOT have a reference assembly in ref
Assert.DoesNotContain(result.Items, item => item.Matches(new
{
PackFolder = PackFolderKind.Ref
}));
}

[Fact]
public void when_produce_reference_assembly_but_pack_build_output_false_then_does_not_include_ref_assembly()
{
var result = Builder.BuildProject(
"""
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<PackBuildOutput>false</PackBuildOutput>
</PropertyGroup>
</Project>
""", output: output);

result.AssertSuccess(output);

// Should NOT have the main assembly in lib
Assert.DoesNotContain(result.Items, item => item.Matches(new
{
Extension = ".dll",
PackFolder = PackFolderKind.Lib
}));

// Should NOT have a reference assembly in ref either
Assert.DoesNotContain(result.Items, item => item.Matches(new
{
PackFolder = PackFolderKind.Ref
}));
}

[Fact]
public void when_produce_reference_assembly_can_opt_out_with_pack_ref_assembly_false()
{
var result = Builder.BuildProject(
"""
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<PackRefAssembly>false</PackRefAssembly>
</PropertyGroup>
</Project>
""", output: output);

result.AssertSuccess(output);

// Should have the main assembly in lib
Assert.Contains(result.Items, item => item.Matches(new
{
Extension = ".dll",
PackFolder = PackFolderKind.Lib
}));

// Should NOT have a reference assembly in ref
Assert.DoesNotContain(result.Items, item => item.Matches(new
{
PackFolder = PackFolderKind.Ref
}));
}

[Fact]
public void when_produce_reference_assembly_then_ref_assembly_is_framework_specific()
{
var result = Builder.BuildProject(
"""
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<IsPackable>true</IsPackable>
</PropertyGroup>
</Project>
""", output: output);

result.AssertSuccess(output);

// The ref assembly should have a package path that includes the TFM
Assert.Contains(result.Items, item => item.Matches(new
{
PackFolder = PackFolderKind.Ref,
PackagePath = "ref/net8.0/scenario.dll"
}));
}
}
}