In my builds, I need to ensure a specific intermediate directory. Now, I have noticed that building a .vcxproj
file uses a different intermediate directory than building the same project as part of an .sln
file: in fact, the former has the project file name prepended as an additional level while the latter does not.
In debugging this, I found that the intermediate directories differs between .vcxproj
files in the .sln
's folder (which do have the project name prepended) and .vcxproj
files elsewhere (which do not).
Why is that, where is this documented, and how can I configure this to stay constant?
The documentation I found says that
$(IntDir)
: Path to the directory specified for intermediate files. If it's a relative path, intermediate files go to this path appended to the project directory.
I assume that "the project directory" is $(ProjectDir)
which does not differ between builds, so I have no explanation why the $(IntDir)
s do.
Here's an MWE to reproduce the problem:
Project.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns=";>
<PropertyGroup Label="Globals">
<ProjectGuid>{00000000-0000-0000-0000-000000000001}</ProjectGuid>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
Sub\Project.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns=";>
<PropertyGroup Label="Globals">
<ProjectGuid>{00000000-0000-0000-0000-000000000002}</ProjectGuid>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
Solution.sln
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RootProject", "Project.vcxproj", "{00000000-0000-0000-0000-000000000001}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SubProject", "Sub\Project.vcxproj", "{00000000-0000-0000-0000-000000000002}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{00000000-0000-0000-0000-000000000001}.Debug|x64.ActiveCfg = Debug|x64
{00000000-0000-0000-0000-000000000001}.Debug|x64.Build.0 = Debug|x64
{00000000-0000-0000-0000-000000000002}.Debug|x64.ActiveCfg = Debug|x64
{00000000-0000-0000-0000-000000000002}.Debug|x64.Build.0 = Debug|x64
EndGlobalSection
EndGlobal
Build.bat
@echo off
pushd "%~dp0"
if "%VSCMD_VER%" == "" (
call "%VS2022INSTALLDIR%\Common7\Tools\VsDevCmd.bat" -arch=amd64
)
set CMD=MSBuild.exe -v:diag -property:Configuration=Debug -property:Platform=x64
set GREP=findstr /b /c:"IntDir ="
%CMD% Solution.sln -target:RootProject | %GREP%
%CMD% Solution.sln -target:SubProject | %GREP%
%CMD% Project.vcxproj | %GREP%
%CMD% Sub\Project.vcxproj | %GREP%
Output
IntDir = Project\x64\Debug\
IntDir = x64\Debug\
IntDir = Project\x64\Debug\
IntDir = Project\x64\Debug\
dir *.lastbuildstate /s/b
(expecting two files, finding three)
.\Project\x64\Debug\Project.tlog\Project.lastbuildstate
.\Sub\Project\x64\Debug\Project.tlog\Project.lastbuildstate
.\Sub\x64\Debug\Project.tlog\Project.lastbuildstate
In my builds, I need to ensure a specific intermediate directory. Now, I have noticed that building a .vcxproj
file uses a different intermediate directory than building the same project as part of an .sln
file: in fact, the former has the project file name prepended as an additional level while the latter does not.
In debugging this, I found that the intermediate directories differs between .vcxproj
files in the .sln
's folder (which do have the project name prepended) and .vcxproj
files elsewhere (which do not).
Why is that, where is this documented, and how can I configure this to stay constant?
The documentation I found says that
$(IntDir)
: Path to the directory specified for intermediate files. If it's a relative path, intermediate files go to this path appended to the project directory.
I assume that "the project directory" is $(ProjectDir)
which does not differ between builds, so I have no explanation why the $(IntDir)
s do.
Here's an MWE to reproduce the problem:
Project.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{00000000-0000-0000-0000-000000000001}</ProjectGuid>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
Sub\Project.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{00000000-0000-0000-0000-000000000002}</ProjectGuid>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
Solution.sln
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RootProject", "Project.vcxproj", "{00000000-0000-0000-0000-000000000001}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SubProject", "Sub\Project.vcxproj", "{00000000-0000-0000-0000-000000000002}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{00000000-0000-0000-0000-000000000001}.Debug|x64.ActiveCfg = Debug|x64
{00000000-0000-0000-0000-000000000001}.Debug|x64.Build.0 = Debug|x64
{00000000-0000-0000-0000-000000000002}.Debug|x64.ActiveCfg = Debug|x64
{00000000-0000-0000-0000-000000000002}.Debug|x64.Build.0 = Debug|x64
EndGlobalSection
EndGlobal
Build.bat
@echo off
pushd "%~dp0"
if "%VSCMD_VER%" == "" (
call "%VS2022INSTALLDIR%\Common7\Tools\VsDevCmd.bat" -arch=amd64
)
set CMD=MSBuild.exe -v:diag -property:Configuration=Debug -property:Platform=x64
set GREP=findstr /b /c:"IntDir ="
%CMD% Solution.sln -target:RootProject | %GREP%
%CMD% Solution.sln -target:SubProject | %GREP%
%CMD% Project.vcxproj | %GREP%
%CMD% Sub\Project.vcxproj | %GREP%
Output
IntDir = Project\x64\Debug\
IntDir = x64\Debug\
IntDir = Project\x64\Debug\
IntDir = Project\x64\Debug\
dir *.lastbuildstate /s/b
(expecting two files, finding three)
.\Project\x64\Debug\Project.tlog\Project.lastbuildstate
.\Sub\Project\x64\Debug\Project.tlog\Project.lastbuildstate
.\Sub\x64\Debug\Project.tlog\Project.lastbuildstate
Share
Improve this question
edited Nov 18, 2024 at 19:53
bers
asked Nov 18, 2024 at 12:03
bersbers
6,0132 gold badges46 silver badges87 bronze badges
5
|
1 Answer
Reset to default 1Somewhat hypothetical/heuristical answer:
Why is that?
I think this is primarily to avoid warning MSB8028 ("The intermediate directory (shared-intermediate-path) contains files shared from another project (intermediate-path).")
If so, this somewhat poorly executed, since putting projects in subdirectories does not guarantee they do not share intermediate directories. But I understand the assumption may be that projects are put into individual subdirectories, and in that case the changed behavior does make sense to avoid one level of intermediate directories.
Where is this documented?
I am still looking for anything written. However, I noticed that the Visual Studio IDE correctly shows the default value of "Intermediate Directory" to be different for the two projects in the solution file:
Note the addition of $(ShortProjectName)
. So at least this is consistent.
So one should probably note that MSBuild
uses $(ShortProjectName)\$(Platform)\$(Configuration)\
as a default Intermediate Directory for *.sln
root projects as well as when compiling individual *.vcxproj
files.
Google-searching for ShortProjectName
reveals that this additional level of Intermediate Directory is intended and was introduced in VS 2022 17.9, see Issue with Intermediate Directory (new folder when building) since update to VS 2022 CE 17.9.0.
How can I configure this to stay constant?
Given the previous answer, the solution is straightforward: by overwriting the default value of Intermediate Directory, e.g., in each vcxproj
file or, somewhat more elegantly, using a shared property or even a Directory.build.props
file:
<?xml version = "1.0" encoding="utf-8"?>
<Project ToolsVersion = "4.0" xmlns="http://schemas.microsoft/developer/msbuild/2003">
<PropertyGroup>
<!-- https://stackoverflow/q/79199847/ -->
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
</Project>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745619455a4636434.html
RootProject
andSubProject
don't exist -- which would be an error ifDebug/x64
existed. You are relying on the diagnostic output (which outputs "initial properties", not property values as used) instead of what a working project actually produces as an intermediate directory. When built via the solution the properties reported by-v:diag
include the property values as the solurtion sees them. – Jonathan Dodds Commented Nov 18, 2024 at 17:05IntDir
values that are output are consistent with what I observe when compiling an actual project. Also, if you are right, I can easily change my question to "why are 'initial properties' different ...?" Either way, I will update the answer with a completely MWE. – bers Commented Nov 18, 2024 at 19:43dir
output in the updated question. Now, it so happens that the initial location equals the final location, so my hypothesis is that the initial location needs to be fixed. If you know another way to fix the final location, by all means, please go ahead. – bers Commented Nov 19, 2024 at 6:04Build.bat
file) and I can see that the directories are created as you say. I think your own answer is on-point -- This is a somewhat recent change in behavior that is a somewhat poorly executed fix for an issue. – Jonathan Dodds Commented Nov 19, 2024 at 17:26