MSBuild dependency is not build - c++

I have the following targets:
<Target Name="Build" DependsOnTargets="Build_Shared" />
<Target Name="Build_Shared" DependsOnTargets="Build_Shared_x86;Build_Shared_x64"/>
<Target Name="Build_Shared_x86" DependsOnTargets="SetPlatform_x86;Shared_1;..." />
<Target Name="Build_Shared_x64" DependsOnTargets="SetPlatform_x64;Shared_1;..." />
The problem is that Shared_1 dependency is not build in the x64 target. I guess MSBuild thinks that it is already build due to the x86 target. I don't want to create different x86/x64 targets for all my shared components. And i have applications (depending on Build_Shared) that require x86 and x64 to build so i need a dependency like this.

Note that each target is only executed once during the build. If you have multiple targets depending on your Shared_1 target, Shared_1 will only be run once, and will considered to already be run when a second DependsOnTargets="..;Shared_1;.." is encountered.
If you need to run the same target multiple times, you need to use a nested msbuild command:
<Target Name="Build_Shared">
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Shard_1" Properties="Platform=x86" />
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Shard_1" Properties="Platform=x64" />
</Target>
You could also use Targets="SetPlatform_x86;Shared_1;.." if you need that.

Related

How build project for 2 platform at same time with project references?

There is MainProj.vcxproj (exe) that have project reference to HelpersLib.vcxproj. If not use proj reference we can build 2 project at once just use MSbuild to build itself but with another platform:
<Target Name="MyTargetName" AfterTargets="Build">
<MSBuild Condition="'$(Platform)' == 'x64'" Projects="$(MSBuildProjectFullPath)" Properties="Platform=Win32;" />
<MSBuild Condition="'$(Platform)' == 'Win32'" Projects="$(MSBuildProjectFullPath)" Properties="Platform=x64;" />
</Target>
But if use project reference onto HelpersLib the last will conflict with MainProj because of the platform (x86 & x64). Are there any solutions?
PS: VS Batch mode not suitable.

Azure DevOps - Enable .pdb file generation via VSBuild#1

I have a pubxml that is used in the VSBuild#1 task and the build works fine except I dont get my .pdb files. How can I make sure the .pdb files are also included in my release?
Project release Config
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Staging2|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>default</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
Pubxml file
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<PublishProvider>FileSystem</PublishProvider>
<LastUsedBuildConfiguration>Staging2</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>False</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>Publish</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
<TargetFramework>net472</TargetFramework>
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
</PropertyGroup>
</Project>
YAML build task
task: VSBuild#1
inputs:
solution: '**\MyApps\Main.csproj'
msbuildArgs: '/t:build /p:DeployOnBuild=true /p:PublishProfile=publish.pubxml /p:OutputPath=$(build.artifactStagingDirectory)\MainPublish\'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
Based on what I have looked up, if you can set the /Build=full property it will be fine. Well my question is if thats the case, where do I add it?
The MSBuild arguments equivalent of the <DebugType>Full</DebugType> part of the project file is: /p:DebugType=full.
So, if you change your msbuildArgs section of the VSBuild task by adding /p:DebugType=full, this should do the trick.

DotnetCore project IntermediateOutputPath leaves some files in the solution directory

In order to keep the repository clean and separated from output and build files we change corresponding paths in the project file.
For Net Framework project specifying IntermediateOutputPath redirects the obj directory to the corresponding folder.
For Net Core project (3.0) using this property is not sufficient. Whereas Debug, Release folders are indeed redirected, the obj folder is still created and it contains some file - such as
project.assets.json, .csproj.nuget.cache, .csproj.nuget.dgspec.json,.csproj.nuget.g.props, .csproj.nuget.g.targets .
Using BaseIntermediateOutputPath - doesnt help either.
Just wonder if someone can suggest how to move the whole obj directory?
Thanks
The Solution suggested by Martin works fine for Net Core projects
<Project>
<PropertyGroup>
<BuildDIrectory>C:\Temp\Build\$(Configuration)</BuildDIrectory>
<RelativePath>some arelative path which depends on location of corresponding project withing the solution</RelativePath>
<BaseIntermediateOutputPath>$(BuildDIrectory)\obj\$(RelativePath)\$(AssemblyName)\</BaseIntermediateOutputPath>
<OutputPath>$(BuildDIrectory)\out\$(RelativePath)\$(AssemblyName)\</OutputPath>
<DocumentationFile>$(BuildDIrectory)\Documentation\$(RelativePath)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
...
</Project>
BaseIntermediateOutputPath works as well, but it needs to be set very early in order to take effect.
The easiest way would be to add it to a Directory.Build.props file:
<Project>
<PropertyGroup>
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)..\shared-obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
</PropertyGroup>
</Project>
If you want to specify it directly in the csproj file, you cannot use the <Project Sdk=" notation since the property needs to be set before parts of the SDK are applied. However it works when using explicit SDK imports and correct ordering:
<Project>
<PropertyGroup>
<BaseIntermediateOutputPath>..\shared-obj\myprojA\</BaseIntermediateOutputPath>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

Custom Build Files changes do not trigger project rebuild in VS 2017

In my C++ VS project I added a custom target to compile shader files and set it as a initial target. This is the project xml
<Project InitialTargets="CompileShaders" DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
..... Normal Default VS C++ content here ......
<ItemGroup>
<GLSLShader Include="SPIR-V\canvas2D.vert" />
<GLSLShader Include="SPIR-V\canvas2D.frag" />
</ItemGroup>
<Target Name="CompileShaders" Inputs="#(GLSLShader)" Outputs="SPIR-V\shaders_bytecode.h" >
<PropertyGroup>
<OriginalFileName>%(GLSLShader.Filename)%(GLSLShader.Extension)</OriginalFileName>
</PropertyGroup>
<Message Text="Start Compiling GSLANG #(GLSLShader) " />
<Message Condition="'$(VULKAN_SDK)'==''" Text="Error, cant find environment variable VULKAN_SDK, Make sure that the Lunar Vulkan SDK is installed" />
<Message Condition="'$(VULKAN_SDK)'!=''" Text="$(VULKAN_SDK)\Bin\glslangValidator.exe %(GLSLShader.Filename)%(GLSLShader.Extension) -V --vn $([System.String]::Copy('%(GLSLShader.Filename)%(GLSLShader.Extension)').Replace('.','_')) -o %(GLSLShader.Filename)%(GLSLShader.Extension).h" />
<Exec Condition="'$(VULKAN_SDK)'!=''" Command="$(VULKAN_SDK)\Bin\glslangValidator.exe %(GLSLShader.Filename)%(GLSLShader.Extension) -V --vn $([System.String]::Copy('%(GLSLShader.Filename)%(GLSLShader.Extension)').Replace('.','_')) -o %(GLSLShader.Filename)%(GLSLShader.Extension).h" WorkingDirectory="$(ProjectDir)\SPIR-V" />
<Exec Condition="'$(VULKAN_SDK)'!=''" Command="del shaders_bytecode.h" WorkingDirectory="$(ProjectDir)\SPIR-V" />
<Exec Condition="'$(VULKAN_SDK)'!=''" Command="type %(GLSLShader.Filename)%(GLSLShader.Extension).h >> shaders_bytecode.h" WorkingDirectory="$(ProjectDir)\SPIR-V" />
<Exec Condition="'$(VULKAN_SDK)'!=''" Command="del %(GLSLShader.Filename)%(GLSLShader.Extension).h" WorkingDirectory="$(ProjectDir)\SPIR-V" />
</Target>
</Project>
if I change any .cpp .h file and build the solution, the shaders are compiled together with the rest of the project, but if I change only the shader files (i.e SPIR-V\canvas2D.vert) the project is not built. VS says that the project is up to date.
Now the strange thing, If I run the project using msbuild on the terminal ouside VS, the shader files changes are enough to trigger the rebuild. Go figure....!!!
It looks like something related to how VS build projects. It is outside the msbuild.
Aha!! Found it in this article. It turns out visual studio bypass msbuild and uses some other criteria to verify if a project is up to date or not. If the criteria fails it then runs the msbuild on that project.
To override the visual studio behavior set the property DisableFastUpToDateCheck as true in the Globals property group of your project's xml:
<PropertyGroup Label="Globals">
<!-- Other Global Property Settings -->
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
And it is done... I wonder if there is a away to tell Visual Studio FastUpToDateCheck Mechanism to also pay attention to the custom build files ????? The solution above will suffice for now.

VS2010 MSBuild Target only runs on rebuild

I'm currently attempting to build a C++ library and what I would like is that every time the build button is pressed I would get all of the include files to be moved to a certain directory.
What I currently have is this
<Target Name="CopyToIncludeFiles">
<Message Text="Copying All '*.h' and '*.hpp' to the include directory" Importance="high">
</Message>
<Copy SourceFiles="#(ClInclude)" DestinationFolder="..\HelperLib\x86\include\">
</Copy>
</Target>
And I include the target in the DefaultTargets likes so
<Project ToolsVersion="4.0" DefaultTargets="Build;CopyToIncludeFiles;" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
This all works fine so long as I use the rebuild, yet this never runs when I just hit build.
What do I need to do to have this run whether I hit build or rebuild?
I think task you solving easier to do with PreBuild Event in project properties, as it is just simple command-line command.
If you still want msbuild - you may use BeforeTargets like this:
<Target Name="CopyToIncludeFiles" BeforeTargets="Rebuild;Build">
<Message Text="Copying All '*.h' and '*.hpp' to the include directory" Importance="high" />
<Copy SourceFiles="#(ClInclude)" DestinationFolder="..\HelperLib\x86\include\" />
</Target>
You should not change project DefaultTargets property to include your task.
Also notice that both PreBuild event and this msbuild task will not run in case your project code doesn't require recompilation (i.e. no cpp / h files changed).