diff --git a/readme.md b/readme.md
index 5fa1e652..bd0bbc58 100644
--- a/readme.md
+++ b/readme.md
@@ -445,6 +445,7 @@ You can also add a reference to a CLI *tools* program like the following:
net6.0
+ Exe
tools
false
@@ -465,6 +466,20 @@ content inference.
This section contains miscellaneous useful features that are typically used in advanced scenarios and
are not necessarily mainstream.
+### PackAsPublish for CLI tools
+
+When a project's output type is `Exe` and it's not set to `PackAsTool=true` (used specifically for .NET tools),
+it will default to be use the `Publish` output for packing. This is typically what you want for a CLI
+project, since dependencies are included in the publish directory automatically without having to annotate
+any references with `PrivateAssets=all`.
+
+This can be turned off by setting `PackAsPublish=false` on the project, which will cause the project
+to be packed as a regular class library, with the dependencies inference rules applied (such as
+`PrivateAssets=all` for package reference and `CopyLocal=true` for references).
+
+When packing as publish, the output won't be framework-specific by default, and will just contribute
+the published contents to the specified `PackFolder`.
+
### Dynamically Extending Package Contents
If you need to calculate additional items to inject into the package dynamically, you can run a target
diff --git a/src/NuGetizer.Tasks/NuGetizer.Inference.targets b/src/NuGetizer.Tasks/NuGetizer.Inference.targets
index 3c85598a..3a801550 100644
--- a/src/NuGetizer.Tasks/NuGetizer.Inference.targets
+++ b/src/NuGetizer.Tasks/NuGetizer.Inference.targets
@@ -248,6 +248,7 @@ Copyright (c) .NET Foundation. All rights reserved.
+
@@ -294,7 +295,7 @@ Copyright (c) .NET Foundation. All rights reserved.
'%(_InferenceCandidateWithTargetPath.CopyToOutputDirectory)' == 'Never'" />
-
+
@@ -318,9 +319,20 @@ Copyright (c) .NET Foundation. All rights reserved.
<_InferredPackageFile Include="@(_InferredProjectOutput -> Distinct())" />
+
+ <_InferredPublishItem Include="@(PublishItemsOutputGroupOutputs -> '%(OutputPath)')" />
+ <_InferredPackageFile Include="@(_InferredPublishItem -> '%(FullPath)')">
+ $(PackFolder)
+ false
+
+
+
+
<_InferredPackageFile Include="@(PackageReference)"
Condition="'$(PackAsTool)' != 'true' and
+ '$(PackAsPublish)' != 'true' and
'%(PackageReference.Identity)' != 'NuGetizer' and
'%(PackageReference.Identity)' != 'NETStandard.Library' and
'%(PackageReference.PrivateAssets)' != 'all' and
@@ -334,6 +346,7 @@ Copyright (c) .NET Foundation. All rights reserved.
TBD: maybe include ResolvedFrom=ImplicitlyExpandDesignTimeFacades too? -->
<_InferredPackageFile Include="@(ReferencePath->'%(OriginalItemSpec)')"
Condition="'$(PackAsTool)' != 'true' and
+ '$(PackAsPublish)' != 'true' and
'$(PackFrameworkReferences)' == 'true' and
'%(ReferencePath.ResolvedFrom)' == '{TargetFrameworkDirectory}' and
'%(ReferencePath.Pack)' != 'false'">
@@ -385,7 +398,9 @@ Copyright (c) .NET Foundation. All rights reserved.
-
+
@@ -416,6 +431,7 @@ Copyright (c) .NET Foundation. All rights reserved.
-
+
<_SupportsReferences Condition="
@@ -500,7 +516,26 @@ Copyright (c) .NET Foundation. All rights reserved.
$(InferPackageContentsDependsOn);
AllProjectOutputGroups
+
+
+ true
+
+
+ $(InferPackageContentsDependsOn);
+ PublishItemsOutputGroup
+
+
diff --git a/src/NuGetizer.Tests/given_a_tool_project.cs b/src/NuGetizer.Tests/given_a_tool_project.cs
index c6df2ef3..d9185c7a 100644
--- a/src/NuGetizer.Tests/given_a_tool_project.cs
+++ b/src/NuGetizer.Tests/given_a_tool_project.cs
@@ -85,5 +85,59 @@ public void when_pack_folder_tool_but_no_pack_as_tool_then_packs_dependencies_no
Identity = "Microsoft.Extensions.DependencyModel"
}));
}
+
+ [Fact]
+ public void when_pack_folder_tool_no_pack_as_tool_and_executable_then_packs_as_publish_with_no_dependencies()
+ {
+ var result = Builder.BuildProject(
+ """
+
+
+ Exe
+ MyTool
+ net6.0
+ MyTool
+ tools
+
+
+
+
+
+ """,
+ "GetPackageContents", output);
+
+ result.AssertSuccess(output);
+ Assert.DoesNotContain(result.Items, item => item.Matches(new
+ {
+ Identity = "Microsoft.Extensions.DependencyModel"
+ }));
+
+ Assert.All(result.Items, item => item.Matches(new
+ {
+ OutputGroup = "PublishItemsOutputGroup",
+ }));
+ }
+
+ [Fact]
+ public void when_both_PackAsTool_and_PackAsPublish_true_then_fails()
+ {
+ var result = Builder.BuildProject(
+ """
+
+
+ Exe
+ net6.0
+ MyTool
+ tools
+ true
+ true
+
+
+ """,
+ "GetPackageContents", output);
+
+ Assert.Equal(Microsoft.Build.Execution.BuildResultCode.Failure, result.BuildResult.OverallResult);
+ }
+
}
}
diff --git a/src/dotnet-nugetize/Program.cs b/src/dotnet-nugetize/Program.cs
index cf49f0ac..c8182ef2 100644
--- a/src/dotnet-nugetize/Program.cs
+++ b/src/dotnet-nugetize/Program.cs
@@ -128,8 +128,7 @@ int Run(string[] args)
"-p:SkipCompilerExecution=true",
"-p:DesignTimeBuild=true",
"-p:DesignTimeSilentResolution=true",
- "-p:ResolveAssemblyReferencesSilent=true",
- "-p:IsPublishable=false"
+ "-p:ResolveAssemblyReferencesSilent=true"
});
if (help)