Dotnet publish -no-build
It is supported
No longer supported
dotnet --info
output:
This is a useful switch. We would like to understand why it's removed and if there is a replacement.
@dsplaisted @nguerrera @eerhardt Is there a way to trigger a publish without build?
@hongdai It would be useful if you can share how you used this flag. I think there was some debate about whether it is still useful.
It would be useful if you can share how you used this flag
Agreed. Getting all the use cases for why this switch is useful helps us understand whether to put it back or not.
One of the use cases I've recently encountered was the F# team (specifically @KevinRansom) was using this switch to publish a project's references, but he didn't want the project's output (its .dll) published. The replacement in that case is to add the MSBuild property <CopyBuildOutputToPublishDirectory>false</CopyBuildOutputToPublishDirectory>
in your .csproj. That way, the current project's .dll isn't published.
FYI - @livarcocc and @piotrpMSFT, we could use this switch in the dotnet/cli ourselves in https://github.com/dotnet/cli/blob/rel/1.0.0/src/redist/redist.csproj. Then we wouldn't need to delete the redist.dll
after publish, like we are currently doing.
It will be great to have --no-build
supported.
We do the following in vstest repo:
~In step 2, all the product dlls are built again. Depending on the number projects published, some of the common dependencies could be built multiple times.~
Update: our build process had a race condition on resources files which was slowing down the process. As @eerhardt notes below, msbuild incremental build does kick in, it is not a significant overhead for us now.
In step 2, all the product dlls are built again.
Why is incremental building not kicking in? MSBuild knows if a project is already built, and doesn't need to build it again.
@piotrpMSFT We used to have our own publish target and run in AfterBuild. Without no-build switch, the publish target will invoke a build and cause a infinite loop, unless we add a condition.
dotnet pack still supports no-build switch. I think the usage should be similar.
+1
As I see it, there should be an option to have the output of a build be the output of what you call "publish". I'd say that this should be the default behavior but that is debatable. As far as I understand it from reading the issues and documentation, this discrepancy is a workaround to speed up the build time of console apps (e.g. use the nuget cache to save on checksum calculations?!).
.Net is used for more than console apps and as such that workaround is not applicable to hosts different than dotnet run
. For those cases, the actual dependencies are needed as part of the build output so it is runnable.
For such cases, I've managed to make dotnet publish
output what is the real build output. To have it integrated with the VS Run command, I'd like to have the MSBuild Build target run the Publish target logic. This leads me to the infinite loop that @hongdai is talking about.
For me the no-build switch is a workaround. Ideally I would like you to support the case where the output of the build contains all the required runtime dependencies.
Same issue here -- Why wasn't this BREAKING CHANGE announced on the announcement repo? I've just converted all our stuff to csproj and now this broke our whole ci/azure setup.
We have 3 deployments setup on AppVeyor for a single solution, so we have 3 configurations that do the following:
@eamodio - same question as above - Why is incremental building not kicking in?
Let's say it is kicking in (which I think it is) -- just the fact the it has to run msbuild, scan for the project(s), see if they need building, etc -- all takes time; time I don't want to be waiting for my CI to finish. For example, on one of my projects it takes about 23s to build it the first time and then 9s to build it the second time (the one that used to be skipped). Yeah, 9s isn't that long in the scheme of things, but it isn't nothing either.
Also, given this flag is seemingly just a simple -- don't run msbuild -- I don't understand why it is so desirable to not support it?
I think this is caused by the current situations that large package graphs (netstandard.library, m.n.app) slow down msbuild projects which is causing project references to slow down linear (1 project 1 sec, 10 projects 10 sec) and has been discussed in https://github.com/dotnet/cli/issues/5918, https://github.com/dotnet/sdk/issues/1116, https://github.com/Microsoft/msbuild/issues/1276 and maybe even more.
Even if build targets are avoided for publish, I believe RunResolvePackageDependencies
and ResolveAssemblyReferences
would still need to be run to determine the proper publish output (I might be wrong) - and those are the targets that cause the slow incremental builds.
Also, given this flag is seemingly just a simple -- don't run msbuild -- I don't understand why it is so desirable to not support it?
@dasMulli hit the nail on the head.
What does --no-build
mean? In reality in project.json world, it really meant something closer to --no-compile
. But the Build
target in MSBuild does so much more than just Compile
your source code.
Content
files that need to be copied to the outputDoing a Publish
without the things that happen during the Build
target in MSBuild is almost pointless. What do you expect to have happened?
Another thing to understand is that dotnet publish
really means "run the Publish
MSBuild target". So it obviously isn't as simple as "don't run msbuild", since you can't run the Publish
target without MSBuild.
So the reason there is push back to supporting it is because it isn't clear what the option is supposed to do/mean. And once we settle on a definition, the next decision to make is - is the scenario we are enabling a high-priority scenario that many customers need?
From that description why wouldn't --no-build
mean don't run the Build
target and only run the Publish
target. Because if you've already run it without the --no-build
flag then the Build
target has already been run -- so everything is all prepared for the Publish
target?
Like @dasMulli says above, there are shared targets between Build
and Publish
that will still need to be executed when just executing Publish
. And the savings above and beyond an incremental build is usually negligible.
For example, on one of my projects it takes about 23s to build it the first time and then 9s to build it the second time (the one that used to be skipped). Yeah, 9s isn't that long in the scheme of things, but it isn't nothing either.
If you are interested in tracking down why the 2nd time is taking 9s, you can pass /v:diag
into both dotnet build
and dotnet publish
. This will print out a lot of information (you probably want to pipe it to a file), but what you are interested in comes at the end. There is a table that shows where all the time is being spent in the build. For example, here is the table of publishing an ASP.NET 2.0 app on my local machine:
Project Performance Summary:
6806 ms F:\DotNetTest\TestWeb\TestWeb.csproj 1 calls
6806 ms Publish 1 calls
Target Performance Summary:
0 ms _DotNetCLIPrePublish 1 calls
0 ms ComputeAndCopyFilesToPublishDirectory 1 calls
0 ms BeforeResGen 1 calls
0 ms PrepareResourceNames 1 calls
0 ms _DotNetCLIPostPublish 1 calls
0 ms ResGen 1 calls
0 ms AfterBuild 1 calls
0 ms GetFrameworkPaths 1 calls
0 ms ResolveReferences 1 calls
0 ms GetReferenceAssemblyPaths 1 calls
0 ms PrepareResources 1 calls
0 ms _AspNetCoreProjectSystemPrePublish 1 calls
0 ms BeforeBuild 1 calls
0 ms Compile 1 calls
0 ms AfterResGen 1 calls
0 ms SetWin32ManifestProperties 1 calls
0 ms CreateCustomManifestResourceNames 1 calls
0 ms GenerateUserSecretsAttribute 1 calls
0 ms CoreBuild 1 calls
0 ms GenerateAssemblyInfo 1 calls
0 ms BeforePublish 1 calls
0 ms _AspNetCoreProjectSystemPostPublish 1 calls
0 ms AfterPublish 1 calls
0 ms _CopySourceItemsToOutputDirectory 1 calls
0 ms CreateSatelliteAssemblies 1 calls
0 ms AfterCompile 1 calls
0 ms PrepareForRun 1 calls
0 ms AfterResolveReferences 1 calls
0 ms InjectReference_efa7ce74-36bd-481a-bac0-42e316fc1d57 1 calls
0 ms IncludeTransitiveProjectReferences 1 calls
0 ms InjectReference_095e2d6d-4484-4c4e-b23a-d4bd8983312a 1 calls
0 ms BeforeCompile 1 calls
0 ms BeforeResolveReferences 1 calls
0 ms Build 1 calls
0 ms CopyFilesToPublishDirectory 1 calls
0 ms PrepareProjectReferences 1 calls
0 ms _DefaultMicrosoftNETPlatformLibrary 1 calls
0 ms ResolvePackageDependenciesForBuild 1 calls
0 ms ResolveSDKReferences 1 calls
0 ms _SetTargetFrameworkMonikerAttribute 1 calls
0 ms ResolveLockFileAnalyzers 1 calls
0 ms BuildOnlySettings 1 calls
0 ms PublishWithAspNetCoreTargetManifest 1 calls
0 ms ComputePrivateAssetsPackageReferences 1 calls
0 ms ExpandSDKReferences 1 calls
0 ms GetInstalledSDKLocations 1 calls
0 ms GetTargetPath 1 calls
0 ms InjectReference_324b1a06-f466-4b33-a9b7-baf91ae299f2 1 calls
0 ms ComputeDependencyFileCompilerOptions 1 calls
0 ms _CheckForUnsupportedSelfContained 1 calls
0 ms _ComputeNetPublishAssets 1 calls
0 ms _GenerateRunCommandFile 1 calls
0 ms _SplitProjectReferencesByFileExistence 1 calls
0 ms _GenerateCompileInputs 1 calls
0 ms CoreResGen 1 calls
0 ms _DetermineProjectType 1 calls
0 ms Publish 1 calls
0 ms _InitPublishIntermediateOutputPath 1 calls
0 ms _InitProjectCapabilityProperties 1 calls
0 ms _CheckForCompileOutputs 1 calls
0 ms PrepareForPublish 1 calls
0 ms _GenerateEFSQLScripts 1 calls
0 ms _GenerateSatelliteAssemblyInputs 1 calls
0 ms _ComputeLockFileFrameworks 1 calls
0 ms _TransformAppSettings 1 calls
0 ms ResolveProjectReferences 1 calls
1 ms _ComputeNETCoreBuildOutputFiles 1 calls
1 ms SplitResourcesByCulture 1 calls
1 ms _SetEmbeddedWin32ManifestProperties 1 calls
1 ms ComputeFilesToPublish 1 calls
1 ms GeneratePublishRuntimeConfigurationFile 1 calls
1 ms GetAssemblyVersion 1 calls
1 ms GetCopyToOutputDirectoryItems 1 calls
2 ms DefaultCopyToPublishDirectoryMetadata 1 calls
2 ms _HandlePublishFileConflicts 1 calls
2 ms IncrementalClean 1 calls
2 ms AssignTargetPaths 1 calls
2 ms GenerateTargetFrameworkMonikerAttribute 1 calls
2 ms _ComputeCopyToPublishDirectoryItems 1 calls
2 ms GetCopyToPublishDirectoryItems 1 calls
2 ms _ComputeLockFileAnalyzers 1 calls
3 ms CoreGenerateUserSecretsAttribute 1 calls
3 ms _ComputeActiveTFMFileDependencies 1 calls
4 ms _GetProjectReferenceTargetFrameworkProperties 1 calls
4 ms PrepareForBuild 1 calls
4 ms _ComputeTransitiveProjectReferences 1 calls
4 ms _CheckForInvalidConfigurationAndPlatform 1 calls
4 ms CheckForDuplicateItems 1 calls
5 ms _ComputeTFMOnlyFileDependencies 1 calls
5 ms CopyFilesToOutputDirectory 1 calls
6 ms CoreGenerateAssemblyInfo 1 calls
6 ms _CopyOutOfDateSourceItemsToOutputDirectory 1 calls
6 ms _ComputeActiveTFMPackageDependencies 1 calls
7 ms _CheckForUnsupportedTargetFramework 1 calls
15 ms CheckForImplicitPackageReferenceOverrides 1 calls
19 ms _TransformWebConfig 1 calls
22 ms _ComputeResolvedFilesToPublishTypes 1 calls
24 ms RunResolvePublishAssemblies 1 calls
26 ms _GenerateCompileDependencyCache 1 calls
27 ms _CleanGetCurrentAndPriorFileWrites 1 calls
30 ms _IncludePrePublishGeneratedContent 1 calls
40 ms ComputeRefAssembliesToPublish 1 calls
62 ms _CopyResolvedFilesToPublishPreserveNewest 1 calls
64 ms GenerateBuildRuntimeConfigurationFiles 1 calls
74 ms _ComputeLockFileReferences 1 calls
81 ms GeneratePublishDependencyFile 1 calls
82 ms ResolveLockFileReferences 1 calls
87 ms RunProduceContentAssets 1 calls
148 ms GenerateBuildDependencyFile 1 calls
244 ms _ComputeLockFileCopyLocal 1 calls
247 ms _HandlePackageFileConflicts 1 calls
249 ms _CopyResolvedFilesToPublishAlways 1 calls
276 ms RunResolvePackageDependencies 1 calls
1166 ms CoreCompile 1 calls
3721 ms ResolveAssemblyReferences 1 calls
Task Performance Summary:
0 ms Delete 1 calls
0 ms ReadLinesFromFile 1 calls
0 ms AssignCulture 1 calls
0 ms RemoveDuplicates 2 calls
0 ms GetFrameworkPath 1 calls
1 ms FindAppConfigFile 1 calls
1 ms FindUnderPath 5 calls
1 ms MSBuild 1 calls
1 ms GetAssemblyVersion 1 calls
1 ms Message 4 calls
2 ms AssignTargetPath 6 calls
2 ms WriteLinesToFile 2 calls
3 ms MakeDir 2 calls
4 ms CheckForDuplicateItems 3 calls
7 ms CheckForImplicitPackageReferenceOverrides 1 calls
8 ms WriteCodeFragment 2 calls
10 ms Hash 1 calls
17 ms TransformWebConfig 1 calls
18 ms ProduceContentAssets 1 calls
22 ms ConvertToAbsolutePath 2 calls
24 ms ResolvePublishAssemblies 1 calls
64 ms GenerateRuntimeConfigurationFiles 2 calls
144 ms ResolvePackageFileConflicts 2 calls
229 ms GenerateDepsFile 2 calls
274 ms ResolvePackageDependencies 1 calls
316 ms Copy 5 calls
1164 ms Csc 1 calls
3719 ms ResolveAssemblyReference 1 calls
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:07.19
Project Performance Summary:
5923 ms F:\DotNetTest\TestWeb\TestWeb.csproj 1 calls
5923 ms Publish 1 calls
Target Performance Summary:
0 ms ResGen 1 calls
0 ms BeforeResGen 1 calls
0 ms PrepareResourceNames 1 calls
0 ms ResolveReferences 1 calls
0 ms Compile 1 calls
0 ms _DotNetCLIPostPublish 1 calls
0 ms _DotNetCLIPrePublish 1 calls
0 ms ComputeAndCopyFilesToPublishDirectory 1 calls
0 ms _AspNetCoreProjectSystemPrePublish 1 calls
0 ms AfterBuild 1 calls
0 ms GetFrameworkPaths 1 calls
0 ms PrepareResources 1 calls
0 ms AfterResGen 1 calls
0 ms SetWin32ManifestProperties 1 calls
0 ms BeforeBuild 1 calls
0 ms PrepareProjectReferences 1 calls
0 ms CreateSatelliteAssemblies 1 calls
0 ms BeforePublish 1 calls
0 ms CreateCustomManifestResourceNames 1 calls
0 ms GenerateUserSecretsAttribute 1 calls
0 ms BeforeCompile 1 calls
0 ms CoreBuild 1 calls
0 ms AfterCompile 1 calls
0 ms AfterResolveReferences 1 calls
0 ms GenerateAssemblyInfo 1 calls
0 ms CopyFilesToPublishDirectory 1 calls
0 ms _CopySourceItemsToOutputDirectory 1 calls
0 ms ResolvePackageDependenciesForBuild 1 calls
0 ms InjectReference_efa7ce74-36bd-481a-bac0-42e316fc1d57 1 calls
0 ms Build 1 calls
0 ms BuildOnlySettings 1 calls
0 ms GetReferenceAssemblyPaths 1 calls
0 ms _AspNetCoreProjectSystemPostPublish 1 calls
0 ms AfterPublish 1 calls
0 ms BeforeResolveReferences 1 calls
0 ms PrepareForRun 1 calls
0 ms IncludeTransitiveProjectReferences 1 calls
0 ms ExpandSDKReferences 1 calls
0 ms ResolveLockFileAnalyzers 1 calls
0 ms _DefaultMicrosoftNETPlatformLibrary 1 calls
0 ms InjectReference_095e2d6d-4484-4c4e-b23a-d4bd8983312a 1 calls
0 ms _SetTargetFrameworkMonikerAttribute 1 calls
0 ms PublishWithAspNetCoreTargetManifest 1 calls
0 ms ComputePrivateAssetsPackageReferences 1 calls
0 ms ResolveSDKReferences 1 calls
0 ms ComputeDependencyFileCompilerOptions 1 calls
0 ms _CheckForUnsupportedSelfContained 1 calls
0 ms _ComputeNetPublishAssets 1 calls
0 ms GetTargetPath 1 calls
0 ms _SplitProjectReferencesByFileExistence 1 calls
0 ms PrepareForPublish 1 calls
0 ms _GenerateRunCommandFile 1 calls
0 ms GetInstalledSDKLocations 1 calls
0 ms CoreResGen 1 calls
0 ms InjectReference_324b1a06-f466-4b33-a9b7-baf91ae299f2 1 calls
0 ms _DetermineProjectType 1 calls
0 ms _CheckForCompileOutputs 1 calls
0 ms _InitProjectCapabilityProperties 1 calls
0 ms _GenerateSatelliteAssemblyInputs 1 calls
0 ms GenerateBuildDependencyFile 1 calls
0 ms _GenerateCompileInputs 1 calls
0 ms _InitPublishIntermediateOutputPath 1 calls
0 ms Publish 1 calls
0 ms ResolveProjectReferences 1 calls
0 ms _GenerateEFSQLScripts 1 calls
0 ms _ComputeLockFileFrameworks 1 calls
0 ms _TransformAppSettings 1 calls
1 ms _ComputeNETCoreBuildOutputFiles 1 calls
1 ms SplitResourcesByCulture 1 calls
1 ms IncrementalClean 1 calls
1 ms _SetEmbeddedWin32ManifestProperties 1 calls
1 ms DefaultCopyToPublishDirectoryMetadata 1 calls
1 ms GetCopyToOutputDirectoryItems 1 calls
1 ms _HandlePublishFileConflicts 1 calls
1 ms GeneratePublishRuntimeConfigurationFile 1 calls
2 ms CoreGenerateUserSecretsAttribute 1 calls
2 ms ComputeFilesToPublish 1 calls
2 ms CoreGenerateAssemblyInfo 1 calls
2 ms CopyFilesToOutputDirectory 1 calls
2 ms _ComputeLockFileAnalyzers 1 calls
2 ms AssignTargetPaths 1 calls
2 ms GenerateTargetFrameworkMonikerAttribute 1 calls
2 ms GetAssemblyVersion 1 calls
3 ms PrepareForBuild 1 calls
3 ms _GetProjectReferenceTargetFrameworkProperties 1 calls
3 ms _ComputeActiveTFMFileDependencies 1 calls
3 ms _ComputeCopyToPublishDirectoryItems 1 calls
3 ms CheckForDuplicateItems 1 calls
3 ms GetCopyToPublishDirectoryItems 1 calls
4 ms _ComputeTFMOnlyFileDependencies 1 calls
4 ms _CheckForInvalidConfigurationAndPlatform 1 calls
4 ms _ComputeTransitiveProjectReferences 1 calls
6 ms _ComputeActiveTFMPackageDependencies 1 calls
8 ms _CheckForUnsupportedTargetFramework 1 calls
13 ms CheckForImplicitPackageReferenceOverrides 1 calls
14 ms CoreCompile 1 calls
16 ms _TransformWebConfig 1 calls
16 ms _ComputeResolvedFilesToPublishTypes 1 calls
24 ms _CleanGetCurrentAndPriorFileWrites 1 calls
25 ms RunResolvePublishAssemblies 1 calls
36 ms _CopyOutOfDateSourceItemsToOutputDirectory 1 calls
41 ms ComputeRefAssembliesToPublish 1 calls
50 ms _GenerateCompileDependencyCache 1 calls
72 ms _IncludePrePublishGeneratedContent 1 calls
72 ms _ComputeLockFileReferences 1 calls
80 ms GenerateBuildRuntimeConfigurationFiles 1 calls
83 ms ResolveLockFileReferences 1 calls
86 ms RunProduceContentAssets 1 calls
159 ms GeneratePublishDependencyFile 1 calls
202 ms _CopyResolvedFilesToPublishAlways 1 calls
228 ms _HandlePackageFileConflicts 1 calls
236 ms _ComputeLockFileCopyLocal 1 calls
273 ms _CopyResolvedFilesToPublishPreserveNewest 1 calls
275 ms RunResolvePackageDependencies 1 calls
3835 ms ResolveAssemblyReferences 1 calls
Task Performance Summary:
0 ms Delete 1 calls
0 ms AssignCulture 1 calls
0 ms RemoveDuplicates 2 calls
1 ms GetFrameworkPath 1 calls
1 ms FindAppConfigFile 1 calls
1 ms ReadLinesFromFile 1 calls
1 ms MSBuild 1 calls
1 ms FindUnderPath 5 calls
1 ms WriteLinesToFile 1 calls
1 ms Message 4 calls
2 ms MakeDir 2 calls
2 ms AssignTargetPath 6 calls
2 ms GetAssemblyVersion 1 calls
3 ms CheckForDuplicateItems 3 calls
6 ms CheckForImplicitPackageReferenceOverrides 1 calls
10 ms Hash 1 calls
14 ms TransformWebConfig 1 calls
18 ms ProduceContentAssets 1 calls
20 ms ConvertToAbsolutePath 2 calls
25 ms ResolvePublishAssemblies 1 calls
81 ms GenerateRuntimeConfigurationFiles 2 calls
143 ms ResolvePackageFileConflicts 2 calls
159 ms GenerateDepsFile 1 calls
204 ms Copy 3 calls
268 ms ResolvePackageDependencies 1 calls
3833 ms ResolveAssemblyReference 1 calls
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:06.18
As you can see, CSC
is only taking a little over 1s the first time. However, even in the 2nd time ResolveAssemblyReference
is taking ~65% of the time (3835 ms / 5923 ms
). As I asked above, do you expect that when you dotnet publish --no-build
that you shouldn't get any referenced assemblies copied to your output directory?
(Now granted, we probably have some sort of perf bug in ResolveAssemblyReference
, but that is a different discussion.)
Anyway, I'd be interested in learning what you find is taking 9s on your 2nd build. I'm sure you would be too 馃槈.
Thanks for the information! I will try that out and see what the bottleneck is.
As for the ResolveAssemblyReference
-- If that isn't done as part of the Build
task, then I would expect it to be done, but if it isn't done as part of the Build
task, then I would expect it to be done.
Basically I just want to avoid doing duplicate work.
The result of ResolveAssemblyReference
isn't saved to disk after the call to Build
. So when a new process comes along for dotnet publish
, it needs to be run again.
(Now granted, we probably have some sort of perf bug in ResolveAssemblyReference, but that is a different discussion.)
That different discussion is here; https://github.com/Microsoft/msbuild/issues/2015
Here is my use case. I'm working on adding CI to our process for an ASP.Net Core site we are building. I want to be able to build once, test those binaries, and then publish the tested binaries as part of the CI workflow. This flag still works with package
, which we are using for publishing internal nuget packages in our CI workflow.
To my mind, publishing a project should operate on it's built assets - therefore publishing is obviously dependent on a build having occurred! I think it would be rare in the world of CI that you would want to publish something from a vanilla state (i.e without already having just done a build to test the assets you are publishing). So the reason for wanting to specify "no build" is because at the point of the workflow you want to publish you have already done the build - mixed in with the fact that an "incremental build" doesn't seem to be as fast as it should be. If an incremental build truly was neglible (i.e zero overhead if build already done) then I don't think this would be such an issue. I guess it's debatable what an acceptable level of overhead would be. I'd be ok if, for large projects, an incremental build didn't incur more than a couple of seconds penalty when nothing has changed. If it takes more than that, and you know ahead of time nothing has changed then you can see why people would be looking to use that "no build" flag if it's available.
This brings me to another point - the willingness to remove this and break peoples CI's processes to seemingly force some feedback on the issue seems a little bit hostile :-/ don't you think?
@eerhardt
As I asked above, do you expect that when you dotnet publish --no-build that you shouldn't get any referenced assemblies copied to your output directory?
I am wondering why it should need to look at references at this point? If the build has already occurred, then the build output (including referenced assemblies / content files etc that had "copy to output") has already been produced. In other words, the assets are already all produced and publish just needs to do something with those existing assets. Why would it need to check references?
@dazinator Exactly. Even if the "incremental build" is negligible, that is still shipping a different set of compiled binaries than the ones that were tested, and in some environments that is unacceptable.
I think we should add the --no-build. I encountered an issue internally where the build portion of publish overwrote binaries that were signed in the build output directory with unsigned copies.
I worked around it with:
<Target Name="PublishWithoutBuilding"
DependsOnTargets="PreventProjectReferencesFromBuilding;
ResolveReferences;
ComputeAndCopyFilesToPublishDirectory;
GeneratePublishDependencyFile;
GeneratePublishRuntimeConfigurationFile" />
<Target Name="PreventProjectReferencesFromBuilding">
<PropertyGroup>
<BuildProjectReferences>false</BuildProjectReferences>
</PropertyGroup>
</Target>
which is the same as the real Publish
, with PreventProjectReferencesFromBuilding;ResolveReferences
replacing Build
.
cc @jaredpar @agocke
I think we should add the --no-build.
Strongly agree. Build is basically a composition of two operations: compile and deploy. Once I've compiled there is simply no need to re-compile when I want to deploy for a new platform. Compiling is just wasting CPU cycles and developer time at that point.
I'll note, for the case where publish was overwriting binaries that had a separate post-build step applied: the incremental build is a perf optimization and shouldn't be relied on for semantic guarantees. so it should never be used as a solution to this problem.
The PublishWithoutBuilding above won't be materially faster than an up-to-date incremental build (compile step would no-op but we still need to resolve references in both cases), so it is really more about semantics than speed.
The fact that reference resolution can be slow is orthogonal and something that is being worked on. It will benefit both incremental builds and things that resolve but don't build.
@nguerrera Not sure you can make that assertion without knowing the writeread speed of the user's output directory, which could theoretically be on a remote network share.
You mean read speed to determine what's up to date?
@nguerrera Yes :)
My assertion should have had more qualifications, but my main point was that you need the semantics of --no-build even more importantly than the speed.
My assertion should have had more qualifications, but my main point was that you need the semantics of --no-build even more importantly than the speed.
100% agree.
Is it possible to approximate the semantics of --no-build by using publish earlier in the build process. I.e.
I can imagine this could be problematical for users who want to build lots of projects, but only publish some. (E.g. don't publish the unit test projects). Any other issues with it?
BTW, even if this is workable, it still seems like a workaround. I agree with the @nguerrera and @jaredpar that the semantics of --no-build are desirable.
@JohnRusk that works on small projects but not on bigger ones. Consider Roslyn which has ~160+ projects in our solution and eventually will have ~10-20 test projects that in theory need publishing. There is really no way to publish all of them without rebuilding their shared dependencies.
Having an explicit, and supported, no build publish is the only reasonable solution here.
We have a post build script in our dev environments which publishes our service and then restarts a docker container running in a VM which is hosting the service. Without the --no-build switch the post build step causes an infinite loop.
I agree with bringing back the --no-build switch option - unless there is another way to achieve the above?
Whatever the solution will be, it seems clear from the comments above that Build -> Test -> Publish is a highly desired workflow, for myself included. Thus, a publish command that can take pre-existing output is a highly desirable requirement, whether this is a --no-build flag or some equivalent. Even more so using a hosted build agent service where build time = money.
My CI is based on Build, Test and finally publish those binaries that were tested. It made sure that the binaries that were tested were the ones published. Now when I publish, it rebuilds, giving me a brand new set of binaries... Please bring back that switch, it broke my CI.
Just got here looking for this. Trying to run dotnet publish with visual studio open breaks hard. Using --no-build would work. Incremental build is still broken here for quite unobvious reasons.
In answer to others above, --no-build should assume dotnet build finished and pick up the output binaries from that.
Read through the above posts, and not clear as to what the holdup is.
In my case it broke my CI step and I am now deploying manually.
Can't --no-build be added back in so we can continue to work while the debate goes on? At the very least it should have been deprecated rather than removed, as it is a breaking change.
Thanks all for the feedback. As I mentioned above, I'm in strong agreement on this. We will add --no-build in v2.1.0.
Another use case (after the horse has bolted):
We have a .NET Core solution with a number of docker containers with APIs. The solution also includes a developer-only console app for Dev investigation. When a Developer presses F5 and the whole solution builds and runs up docker, I want the console app (and only the console app) to republish itself to a Win 10 x64 target so that the devs can use the console app from Powershell. I would normally put publish in a post-build event in the .csproj
but that creates an infinite loop. I need the --no-build
parameter to stop that.
I appreciate that my Devs can still do dotnet c:/blah/myapp.dll params
but they find that upsetting.
Same problem. Trying to automate publishing Asp.NET Core project. There is no way to force publish after build, so I ended up adding a 'dotnet publish' post-build event. Sadly it results in recursive builds that never end. A --no-build switch would fix something that I will now have to spend hours trying to work around.
try dotnet msbuild /t:publish /p:NoBuild=True
Hey @gulbanana : thanks for the tip but for me msbuild still rebuilds dependent projects. So it's different than the former --no-build
options that didn't even tried to build anything and just assumed the right dll was here.
There's also the /p:BuildProjectReferences=false
switch that indicates that all dependencies are up-to-date and don't need to be rebuilt (see ProjectReference protocol)
@dasMulli : thanks a lot! works great! (and I can finally publish my 5 projects without having to rebuild everything all the time :-) )
Here's how our build process used to look like with the 1.0.4 .NET Core SDK:
dotnet restore
dotnet build /p:Version=6.6.6
dotnet test
dotnet publish
docker build <using publish output folder>
docker push
As you can see, we use a /p msbuild option for dotnet build
to specify the version that we want for our assembly. This used to work great.
With .NET Core 2, since the dotnet publish
does on dotnet build
, the result of dotnet publish
recompiles the assembly without using the 6.6.6 assembly version. We therefore end-up with a docker container that contains assemblies that:
I can fix this problem using dotnet publish /p:Version=6.6.6
. But in fact, the problem is more complex since we also use dotnet lambda package
that does an implicit dotnet publish
that does not allow me to specify the /p:Version=6.6.6
parameters. See https://github.com/aws/aws-lambda-dotnet/issues/210 for more details.
Please add the --no-build option ;)
Is there plans to add the no-build option back? Not building the references isn鈥檛 quite the same thing.. thanks!
@diegohb At the top of this issue, you can see that it's slated for release with milestone 2.1.3xx.
Check out all the issues in that milestone here: https://github.com/dotnet/cli/milestone/17
I will try to get to this soon.
dotnet/sdk#2111 (in PR) implements the dotnet/sdk half of this. After that, we just need to wire --no-build to /p:NoBuild=true here.
Most helpful comment
Thanks all for the feedback. As I mentioned above, I'm in strong agreement on this. We will add --no-build in v2.1.0.