Can't set property via .props file - visual-studio

I'm trying to change project's property via .props file. I created 2 files:
Directory.build.props
<Project>
<PropertyGroup Label="Globals">
<ForceImportBeforeCppProps>$(MsbuildThisFileDirectory)\MyProps.props</ForceImportBeforeCppProps>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
</Project>
And
MyProps.props
<Project>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<PlatformToolset>v142</PlatformToolset>
<PreferredToolArchitecture>x86</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<PlatformToolset>v142</PlatformToolset>
<PreferredToolArchitecture>x86</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<PlatformToolset>v142</PlatformToolset>
<PreferredToolArchitecture>x86</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<PlatformToolset>v142</PlatformToolset>
<PreferredToolArchitecture>x86</PreferredToolArchitecture>
</PropertyGroup>
</Project>
Both properties WindowsTargetPlatformVersion and PlatformToolset are successfully applied, but not the PreferredToolArchitecture. Could you please tell me, where I'm wrong? How to set it properly? I', using Visual Studio 2019
I also found, that this works if I delete PreferredToolArchitecture property from the .vcxproj file. Why it can't override it?

'Directory.build.props' is imported early, before the main body of the project file. The ForceImportBeforeCppProps property instructs that your 'MyProps.props' file should be imported early.
The PreferredToolArchitecture property in the .vcxproj is overriding your definition.
Move your property overrides to a 'Directory.build.targets' file.

Related

Visual Studio ignores UseDebugLibraries from .props

I have the following .props file, generated with CMake (but this does not seem to be a CMake problem):
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
</Project>
I have another .props file, next to this one in the .vcxproj, but it is correctly merged when i open it in Visual Studio, they look like this in the project file:
<ImportGroup Label="PropertySheets">
<Import Project="other_props_file_that_works.props;does_not_work.props" Condition="exists('other_props_file_that_works.props;does_not_work.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
Not really relevant, but the props are added like this in the CMakeLists.txt:
set_property(TARGET "${PROJECT_NAME}" PROPERTY VS_USER_PROPS ${USE_DEBUG_LIBARIES_PROPS_FILE_PATH} APPEND)

Custom MSBuild project that can be "run" from Visual Studio

I created a custom MSBuild project that I can "build" from Visual Studio 2019, as described in https://stackoverflow.com/a/64917535/1536933. That is, I can select the Build menu item in VS and it runs my custom MSBuild task. Is there a way to do the same with "Run" - get VS to run my custom MSBuild task when I "Start" (or "Start without debugging") that project? I worked out that for the Build menu item to appear VS needs to see MSBuild targets named "Build" and "CoreCompile" - there is probably some equivalent for Start, but what?
The custom project file looks like this:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>(some guid)</ProjectGuid>
<ProjectHome>.</ProjectHome>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
</PropertyGroup>
<!-- These property groups can be empty, but need to be defined for VS -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
</PropertyGroup>
<Import Project="My.Build.targets" />
<!-- Define empty standard MSBuild targets, since this project doesn't have them. Doing it this way allows My.Build.targets to also be used in a project that does define them. -->
<Target Name="Build" />
<Target Name="ReBuild" />
<Target Name="Clean" />
<!-- NOTE: a target named "CoreCompile" is needed for VS to display the Build menu item. -->
<Target Name="CoreCompile" />
<!-- Files shown in Visual Studio - adding and removing these in the UI works as expected -->
<ItemGroup>
<Content Include="myfile..." />
</ItemGroup>
</Project>
Note that it's not a C# project or C++ project or any other common type of project - VS treats its as a Node.js project due to the ProjectTypeGuids, but if I can get it working some other way, I'd be happy to.

How to reference one copy of vcxproj.filters and vcxproj.user per project between visual studio 2017 and visual studio 2019

I have a c++ project created in Visual Studio 2017 community edition and I have opened and "converted" it with Visual Studio 2019 community edition.
The project folder contains:
Main.sln
Main/Main.vcxproj
Main/Main.vcxproj.filters
Main/Main.vcxproj.user
According to Winmerge, the conversion only affected two values within Main/Main.vcxproj:
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
...
<PlatformToolset>v141</PlatformToolset>
changed to
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
...
<PlatformToolset>v142</PlatformToolset>
What options exist for maintaining one copy of most or all of these project files for both, VS2017 and VS2019?
Also, I would like to know:
Is there support for conditionals within .vcxproj or .sln?
Is there a way to explicitly point to a .vcxproj in one folder path and
*.vcxproj.filters and *.vcxproj.user in another?
Thanks!
Hopefully, this will help someone later.
MSBuild supports conditionals defined within the .vcxproj files that can key off of the available macros. I also found that values can be replaced by being set again further down in the file.
This example talks about checking and setting the VisualStudioVersion macro.
The solutions I found use the DefaultPlatformToolset macro, which is v141 for VS2017 and v142 for VS2019.
There are two ways that Main.vcxproj could use this in a conditional:
1) Use the Choose, When, and Otherwise tags around PropertyGroups containing the necessary values:
<Choose>
<When Condition="'$(DefaultPlatformToolset)'=='v141'">
<PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
</When>
<When Condition="'$(DefaultPlatformToolset)'=='v142'">
<PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion>$(DefaultWindowsSDKVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
</Otherwise>
</Choose>
2) Set the Conditional property of the PropertyGroups:
<PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion>$(DefaultWindowsSDKVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(DefaultPlatformToolset)'=='v141'" Label="Globals">
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(DefaultPlatformToolset)'=='v142'" Label="Globals">
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
Another approach may be to use a .sln file per Visual Studio version and base conditionals on the $(SolutionFileName) macro.
<Choose>
<When Condition="'$(SolutionFileName)'=='Main_VS2017.sln'">
...
</When>
<When Condition="'$(SolutionFileName)'=='Main_VS2019.sln'">
...
</When>
</Choose>
I've used the solution from http://www.markusweimer.com/2016/03/14/visual-c++/ hust converted it to 2015 and 2019.
<!--
Switch the PlatformToolset based on the Visual Studio Version
-->
<PropertyGroup>
<!-- Assume Visual Studio 2015 / 14.0 as the default -->
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
</PropertyGroup>
<!-- Visual Studio 2019 (16.0) -->
<PropertyGroup Condition="'$(VisualStudioVersion)' == '16.0'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<!-- Visual Studio 2015 (14.0) -->
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<!--
End of: Switch the PlatformToolset based on the Visual Studio Version
-->
Works like a charm...

Accessing the runtime library property in visual studio 2010

This is basically a follow up question to:
Using Visual Studio project properties effectively for multiple projects and configurations
Our library's target name is currently in this format:
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
We'd like to add information about the runtime library used by the project to the target name, I tried adding $(RuntimeLibrary), but that doesn't seem to be set. Is there any other way to get the runtime library at the time the target name is resolved?
Thanks,
John.
With this property sheet you can do this. Import it in your property sheet and you will be able to access the RuntimeLibrary this way: $(RuntimeLibrary)
Yes!!! This will work in your propertie sheet =^.~=
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_IsDebug>$([System.Convert]::ToString($([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration),'[Dd]ebug'))))</_IsDebug>
<_ItemDefinitionGroupRegex><![CDATA[<ItemDefinitionGroup Condition=".*']]>$(Configuration)\|$(Platform)<![CDATA['">((?:.*\n)*?.*)</ItemDefinitionGroup>]]></_ItemDefinitionGroupRegex>
<_RuntimeLibraryRegex><![CDATA[(?:.*\n)*?.*<RuntimeLibrary>(.*)</RuntimeLibrary>(?:.*\n)*?.*]]></_RuntimeLibraryRegex>
<_HasRuntimeLibrary>$([System.Text.RegularExpressions.Regex]::IsMatch($([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(ProjectPath))), $(_ItemDefinitionGroupRegex)).Result('$1')), $(_RuntimeLibraryRegex)))</_HasRuntimeLibrary>
<!--
Fix incremental build (Different results when running msbuild within Visual Studio or from console).
http://connect.microsoft.com/VisualStudio/feedback/details/677499/different-results-when-running-msbuild-within-visual-studio-or-from-console
-->
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<Choose>
<When Condition="$([System.Convert]::ToBoolean($(_HasRuntimeLibrary)))">
<!-- Extract runtime library from project file. -->
<PropertyGroup Label="UserMacros">
<_RuntimeLibrary>$([System.Text.RegularExpressions.Regex]::Match($([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(ProjectPath))), $(_ItemDefinitionGroupRegex)).Result('$1')), $(_RuntimeLibraryRegex)).Result('$1'))</_RuntimeLibrary>
</PropertyGroup>
</When>
<Otherwise>
<!-- Set default runtime library -->
<PropertyGroup Label="UserMacros">
<_RuntimeLibrary Condition=" '$(_IsDebug)' == 'True' ">MultiThreadedDebugDLL</_RuntimeLibrary>
<_RuntimeLibrary Condition=" '$(_IsDebug)' == 'False' ">MultiThreadedDLL</_RuntimeLibrary>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup Label="UserMacros">
<IsDebug>$(_IsDebug)</IsDebug>
<ConfigType Condition=" '$(IsDebug)' == 'True' ">Debug</ConfigType>
<ConfigType Condition=" '$(IsDebug)' == 'False' ">Release</ConfigType>
<Architecture Condition=" '$(Platform)' == 'Win32' ">x86</Architecture>
<Architecture Condition=" '$(Platform)' == 'x64' ">x64</Architecture>
<Toolset Condition=" '$(PlatformToolset)' == 'v110' ">msvc.110</Toolset>
<RuntimeLibrary>$(_RuntimeLibrary)</RuntimeLibrary>
</PropertyGroup>
<ItemGroup>
<BuildMacro Include="IsDebug">
<Value>$(IsDebug)</Value>
</BuildMacro>
<BuildMacro Include="Toolset">
<Value>$(Toolset)</Value>
</BuildMacro>
<BuildMacro Include="Architecture">
<Value>$(Architecture)</Value>
</BuildMacro>
<BuildMacro Include="RuntimeLibrary">
<Value>$(RuntimeLibrary)</Value>
</BuildMacro>
<BuildMacro Include="ConfigType">
<Value>$(ConfigType)</Value>
</BuildMacro>
</ItemGroup>
</Project>

Change assembly name based on configuration (Visual Studio 2005/2008)

Is it possible to change the assembly name based on the project configuration?
I have tried conditional pragmas on the assemblyinfo.cs file, but that only changes the assembly attributes, not the name itself.
If you right click on your project and choose "Edit Project File" (I'm in 2008 here and it may be a new option, if it is then just open the project file in any old text editor) you should see something similar to the following:
<PropertyGroup>
...
<AssemblyName>ClassLibrary1</AssemblyName>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
</PropertyGroup>
Basically any properties that aren't overriden in a more specific property group are inherited from the more general, first group. So to achieve what you want just edit the file so that the AssemblyName tag is defined in each of the specific groups:
<PropertyGroup>
...
<AssemblyName>ClassLibrary1</AssemblyName>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
<AssemblyName>ClassLibrary1Debug</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
<AssemblyName>ClassLibrary1Release</AssemblyName>
</PropertyGroup>
This will change the assembly name on a per config basis.

Resources