Open DoCode opened 6 years ago
@nguerrera
cc @dsplaisted can you take a look at this one? I remember you were looking at something similar already.
Setting BaseIntermediateOutputPath
from the command line isn't supported when you have project references.
The problem is, when you build a project, its references are also built. In this case, when you build aspnetcore.csproj
, it in turn builds dotnetcore-lib.csproj
, and the BaseIntermediateOutputPath
flows through and both projects end up trying to use the same project.assets.json
file, which causes this error (a project ends up trying to use the assets file which was written for another project).
If we were to change it so that the BaseIntermediateOutputPath
didn't flow to project references, then when aspnetcore.csproj
builds dotnetcore-lib.csproj
, the BaseIntermediateOutputPath
wouldn't be specified at all, so it would put the intermediate output in the default folder (obj
in the project directory) instead of the _build
folder you specified when you built that project previously.
Instead of trying to specify this on the command line, I'd suggest creating a Directory.Build.props
file in the root folder with the following contents (or similar):
<Project>
<PropertyGroup>
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)_build\bin\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
</PropertyGroup>
</Project>
See also #867 which proposes adding a property to specify a root path under which all project output (intermediate as well as final) would go. If we add such a property, then it should be possible to specify it from the command line.
First, @livarcocc, @nguerrera... Thanks for your fast response! Very Great!
@dsplaisted, ok. I understand and tried it. And it worked!
But what about when I restore, build/publish with --no-dependencies --force
like this:
dotnet restore .\src\dotnetcore-lib\dotnetcore-lib.csproj /p:BaseIntermediateOutputPath=..\..\_build\bin\obj\dotnetcore-lib\ --no-dependencies --force
dotnet publish .\src\dotnetcore-lib\dotnetcore-lib.csproj /p:BaseIntermediateOutputPath=..\..\_build\bin\obj\dotnetcore-lib\ --no-dependencies --force
dotnet restore .\src\aspnetcore\aspnetcore.csproj /p:BaseIntermediateOutputPath=..\..\_build\bin\obj\aspnetcore\ --no-dependencies --force
dotnet publish .\src\aspnetcore\aspnetcore.csproj /p:BaseIntermediateOutputPath=..\..\_build\bin\obj\aspnetcore\ --no-dependencies --force
This does not work. But it from the wording from the arguments it should.
The question is, how can we tell the underlying compiler/linker the path to the 'pre-compiled' dotnetcore-lib.csproj obj dir?
how can we tell the underlying compiler/linker the path to the 'pre-compiled' dotnetcore-lib.csproj obj dir?
If you want to use a DLL directly instead of building the referenced project, then you can use a Reference
instead of a ProjectReference
in your project file. But I think it would be helpful to understand why you want to do this, there may be a better way to do it.
As for why --no-dependencies
didn't work, even if the referenced project isn't being built, it still calls the GetTargetPath
target on it in order to figure out what the path to the DLL to reference is.
@dsplaisted thanks for your support.
The only simple answer to your question is, that we would redirect the base obj
(BIOP) folder outside of the project directory structure.
Is there a solution for this?
@DoCode I'm not following. If you want to redirect the obj folder, then use a Directory.Build.props file like I suggested. The path you put in that file can be outside the project directory structure if you want it.
You probably don't need to use the --no-dependencies
or --force
options.
@dsplaisted thanks again! I am a little bit overcommited ;-) So what I see today, I can not build dynamically a output folder structure like this:
_build
|-> bin
|-> anyos.anycpu.<configuration>
|-> <project-name>
|-> <target-framework>
.
.
.
|-> win7.x86.debug
|-> Project1
|-> netstandard2.0
.
.
.
The only problem is, that I can not dynamic parse the informations like cpu, architecture, target framework and so on, when I use the directory.build.props.
@DoCode Yes, the target framework and runtime identifier aren't available at that point. By default they are appended to the path under the project-specific path. So if you set BaseIntermediateOutputPath
to build\obj\<project-name>
, then you will end up with folders such as Debug\netstandard2.0\win7-x86
under it.
@dsplaisted ok. No chance to calculate and read the props in a custom task (default task in directory.build.props)?
@DoCode No, these properties are set in evaluation, which is before any tasks are run.
It's probably possible to get close to the layout you want, but it would be a lot trickier. You'd still set the BaseIntermediateOutputPath
to something like build\<project-name>\obj
in Directory.Build.props, but then you would calculate the IntermediateOutputPath
and OutputPath
in a .targets file that was evaluated after the TargetFramework
and other properties you need were set.
You can use binary logs and MSBuild Structured Log Viewer to explore how the current output path calculations work, and help figure out how to override them with your own. Look for the AppendTargetFrameworkToOutputPath
and AppendRuntimeIdentifierToOutputPath
properties.
Thanks a lot, Daniel (@dsplaisted)! I will test this tomorrow... Now it's very late in the Bavarian Alps! :-)
@dsplaisted - sorry for the long delay. But other tasks have higher prio!
I ended with this Directory.Build.props
:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<Import Project="../Directory.Build.props" Condition=" Exists('../Directory.Build.props') " />
<Import Project="../dir.props" Condition=" Exists('../dir.props') " />
<Import Project="SolutionItems/version/version.props" Condition=" Exists('SolutionItems/version/version.props') " />
<PropertyGroup Condition=" '$(ConfigPropsFileImported)' == 'true' ">
<!--
_build / bin /
-->
<BaseOutputPath>$(BinDir)/</BaseOutputPath>
<!--
_build / obj /
-->
<BaseIntermediateOutputPath>$(BaseOutputDir)/obj/$(MSBuildProjectName)/</BaseIntermediateOutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
</Project>
And this Directory.Build.targets
:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<Import Project="../Directory.Build.targets" Condition=" Exists('../Directory.Build.targets') " />
<Import Project="../dir.targets" Condition=" Exists('../dir.targets') " />
<PropertyGroup Condition=" '$(ConfigPropsFileImported)' == 'true' ">
<!--
_build / bin / win7.x64.debug / DotNetCore.ConsoleApp / netcoreapp2.1 /
_build / bin / $(_OS).$(_PlatformTarget).$(Configuration) / $(MSBuildProjectName) / $(_TargetFramework) /
-->
<_OS Condition=" '$(RuntimeIdentifier)' != '' ">$(RuntimeIdentifier.Split('-')[0])</_OS>
<_OS Condition=" '$(_OS)' == '' ">AnyOS</_OS>
<_PlatformTarget>$(PlatformTarget)</_PlatformTarget>
<_PlatformTarget Condition=" '$(_PlatformTarget)' == '' ">AnyCPU</_PlatformTarget>
<_TargetFramework>$(TargetFramework)</_TargetFramework>
<_TargetFramework Condition=" '$(_TargetFramework)' == '' AND '$(TargetFrameworkIdentifier)' == '.NETFramework' ">net$(_TargetFrameworkVersionWithoutV.Replace('.', ''))</_TargetFramework>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(_OS.ToLowerInvariant()).$(_PlatformTarget.ToLowerInvariant()).$(Configuration.ToLowerInvariant())/$(_TargetFramework.ToLowerInvariant())/</IntermediateOutputPath>
<IntermediateOutputPath>$(IntermediateOutputPath.TrimEnd('/').TrimEnd('\'))/</IntermediateOutputPath>
<OutputPath>$(BinDir)/$(_OS.ToLowerInvariant()).$(_PlatformTarget.ToLowerInvariant()).$(Configuration.ToLowerInvariant())/$(MSBuildProjectName)/$(_TargetFramework.ToLowerInvariant())/</OutputPath>
<OutputPath>$(OutputPath.TrimEnd('/').TrimEnd('\'))/</OutputPath>
<OutDir>$(OutputPath)</OutDir>
<BaseOutputPath>$(OutputPath)</BaseOutputPath>
<PackageOutputPath>$(OutputPath)</PackageOutputPath>
<TargetDir>$(OutputPath)</TargetDir>
<TargetPath>$(TargetDir)$(TargetFileName)</TargetPath>
<PublishDir>$(OutputPath)</PublishDir>
</PropertyGroup>
</Project>
Now some errors occours on build:
Error MSB4018: The "GenerateBindingRedirects" task failed unexpectedly.
System.IO.DirectoryNotFoundException: Could not find a part of the path 'D:\projects\output-labs\_build\obj\DotNetCore.ConsoleApp\Debug\repocli.exe.config'.
I think the GenerateBindingRedirects
task doesnt respect the changed IntermediateOutputPath
.
This issue still presists:
in my net50 C# solution building with VS2019 I get no warnings with
<BaseArtifactsPath>$(MSBuildStartupDirectory)artifacts/</BaseArtifactsPath>
<BaseArtifactsPathSuffix>$(ProjectCategory)/$(MSBuildProjectName)</BaseArtifactsPathSuffix>
and Unknown build errors
that disappear at the end of compilation, if I add the line
<BaseIntermediateOutputPath>$(BaseArtifactsPath)obj/$(BaseArtifactsPathSuffix)/</BaseIntermediateOutputPath>
but even with this last line a startupDir/obj
directory is still created with Debug/net5.0-windows
subdirectory. And there is no obj
directory created inside startupDir/artifacts
. So the intended effect is not there.
Because:
When I use a
netcoreapp2.x
with a project reference to anetstandard2.x
project and I set theBaseIntermediateOutputPath
, then the build/publish failed with this error:Steps to reproduce:
1) Create class lib
dotnet new classlib --name dotnetcore-lib --output src/dotnetcore-lib
2) Create web appdotnet new web --name aspnetcore --output src/aspnetcore
3) Addclass lib
as reference toweb app
dotnet add .\src\aspnetcore\aspnetcore.csproj reference .\src\dotnetcore-lib\dotnetcore-lib.csproj
4) Restore and publish (without customBaseIntermediateOutputPath
) => that works 👍5) Restore and publish (with custom
BaseIntermediateOutputPath
) => that fails 👎What the hell we make it wrong?
Related issues
803 (see comments and issue references)