Msbuild and ClCompile options [duplicate] - c++

This question already has an answer here:
How to get all the metadata keys for any ItemGroup item?
(1 answer)
Closed 6 years ago.
I compile C++ code with msbuild and I specify cl options inside ClCompile item. Something like...
<ItemGroup>
<ClCompile Include="something.cpp">
<FloatingPointModel>Precise</FloatingPointModel>
<WarningLevel>Level2</WarningLevel>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Targets" />
The above is just an example. Now I want to print all options used for cl invocation. The question is: How do I do that? My first attempt was to use something like the following:
<Target Name="WriteToFile" AfterTargets="ClCompile" >
<WriteLinesToFile File="$(OutDir)\log.txt" Lines="#(ClCompile)" Overwrite="true" />
</Target>
Sadly, this logs only filename (something.cpp) and not the options.
Note that I'm aware that the compiler options are stored by Tracker.exe in CL.command.*.tlog file, but first, I don't want to rely on that as it's subject to change and second, I will most likely need to do some transformations later on. I also know that I could access individual options (like %(ClCompile.FloatingPointModel)), but I don't want handle each option separately either.
Is there a better way to do this?

There is no trivial solutions to do that.
You could find a starting point here
and another example here

Related

MSBuild - Override MinimalRebuild (/Gm) to false

After some research, to get VisualStudio to build a project's object files in parallel, one must ensure that project properties MinimalRebuild is off and MultiProcessorCompilation is on. I can configure this in the project file, but is there a way to override these project settings on the command line using msbuild?
In other words, using msbuild from the command line, how would I override MinimalRebuild (/Gm-) to be false and MultiProcessorCompilation (/MP) to be true? The following doesn't seem to work
msbuild /m:7 /p:CL_MPCount=7 /p:MinimalRebuild=false /p:MultiProcessorCompilation=true
As an aside, is /p:CL_MPCOUNT redundant with the MultiProcessorCompilation property? Overall, I'm having trouble finding documentation on what fits the /p option.
In other words, using msbuild from the command line, how would I
override MinimalRebuild (/Gm-) to be false and
MultiProcessorCompilation (/MP) to be true?
CL_MPCount can be overrided by /p:xxx=xxx but MultiProcessorCompilation and MinimalRebuild are not. Just to be clear, It can only be overridden by /p:xxx=xxx(p means property) if it is a property of MSBuild. And the Property usually can be called by $. So I do some tests:
Edit
Test
1)CL_MPCount
This value means Maximum Number of concurrent C++ compilations in VS IDE.You can refer to this.
So I have assigned a value by VS IDE by(Debug->Options->Projects and Solutions->VC++ Project Solutions and set the Maximum Number of concurrent C++ compilations to 2.)
write a custom target like
<Target Name ="Test" AfterTargets="Build">
<Message Importance="high" Text="CL_MPCount is= $(CL_MPCount)">
</Message>
</Target>
Then Build and it shows;
From this we can see that this is a property that belongs to MSBuild.
2)MinimalRebuild
Usually, it means /GM and it usually set in the Properties in a c++ project. l have set it to True by (Right-click on the project-->Properties-->C/C++-->Code Generation-->set Enable Minimal Rebuild to True).
Custom target like
<Target Name ="Test" AfterTargets="Build">
<Message Importance="high" Text="MinimalRebuild is= $(MinimalRebuild)">
</Message>
</Target>
The result is like
From it, the value which set in the VS IDE cannot be available by $(MinimalRebuild) which means it is not a property of MSBuild.
3) MultiProcessorCompilation
It also means /MP and from the document we will find that it is an option of the the compiler not a property of MSBuild. Besides, l did the same as the MinimalRebuild and it is not being output. So it is also not a property of MSBuild.
In addition, l thought MinimalRebuild and MultiProcessorCompilation are the options of MSBuild before. So I type MSBuild -help in Command Line and found that it did not list these parameters at all. So I think these two parameters have nothing to do with MSBuild at all, but are just some of the compiler's options.
Hope it could help you.
I found a way to override both properties at User level. Anyway you may find them helpful (for example for Build host where incremental build is not meaningful at all).
Create these two properties files:
%USERPROFILE%\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props
%USERPROFILE%\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.x64.user.props
with following content:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ProcessorNumber>2</ProcessorNumber>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
Feel free to customize ProcessorNumber to suit your hardware.
Now MSBUild will use above values for all projects.

Custom ProjectSchemaDefinitions in Project Property Sheet

I finally managed to configure my Visual Studo C++ Project to show my Custom ProjectSchemaDefinition if I take a look at a Single Project->Property.
My Question:
Is there any way to show this in a Shared Project Property (eg external.props) ?
My current shared.targets configuration
<PropertyGroup Label="Import Settings">
<UseDefaultProjectTools>true</UseDefaultProjectTools>
<UseDefaultPropertyPageSchemas>true</UseDefaultPropertyPageSchemas>
<UseDefaultGeneralPropertyPageSchema>true</UseDefaultGeneralPropertyPageSchema>
</PropertyGroup>
<ItemGroup>
<PropertyPageSchema Include="$(SolutionDir)\props\PublishConfig.xml">
<Context>Project</Context>
</PropertyPageSchema>
<ProjectTools Include="PublishConfig" />
</ItemGroup>
I think I miss just the right Context in this definition but cannot find any reliable source at msdn where different Context Targets are correctly described.
Thank you in advance

How to use the Web Publishing Pipeline and Web Deploy (MSDEPLOY) to Publish a Console Application?

I would like to use web deploy to publish a Visual Studio "Console" application to a folder on the target system.
I have had some luck, and have been able to produce something similar to what I need, but not quite.
I've added the following to the console .csproj:
added the following projectName.wpp.targets file
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
and I've added the following projectName.wpp.targets:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<DeployAsIisApp>false</DeployAsIisApp>
<IncludeSetAclProviderOnDestination>false</IncludeSetAclProviderOnDestination>
</PropertyGroup>
<ItemGroup>
<FilesForPackagingFromProject Include="$(IntermediateOutputPath)$(TargetFileName).config">
<DestinationRelativePath>bin\%(RecursiveDir)%(FileName)%(Extension)</DestinationRelativePath>
<FromTarget>projectName.wpp.targets</FromTarget>
</FilesForPackagingFromProject>
</ItemGroup>
</Project>
I then edit the .SetParameters.xml file as follows:
<parameters>
<setParameter name="IIS Web Application Name" value="c:\company\project" />
</parameters>
When I then deploy using the generated .cmd file, I get all the files deployed to C:\company\project\bin.
That's not bad, but I'd like to do better. In particular, I'd like to omit the "bin" folder and put all files in the "C:\company\project" folder, and I'd like to be able to specify the ACLs
Has anybody been able to work around these problems?
Ok, so here's the way how to omit the 'bin' folder.
First of all, I'd like to emphasize that all this msdeploy-related stuff is for web apps deployment, and 'bin' folder seems for me to be almost hardcoded deeply inside. So if you want to get rid of it - you have to do some dirty things. Which I did.
We'll have to change $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets project a little bit, so it's better to change not it, but it's copy.
Steps:
1.Backup $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets(alternatively, you could install MSBuild.Microsoft.VisualStudio.Web.targets package, redirect your csproj file to Microsoft.WebApplication.targets file obtained from package and work with it).
2. In the $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplicaton.targets find the xml node which looks like <CopyPipelineFiles PipelineItems="#(FilesForPackagingFromProject)"(there are several ones of them, take the one from the line ~2570).
3. Comment the node out, replace with the custom one, so eventually it will look like:
<!--
<CopyPipelineFiles PipelineItems="#(FilesForPackagingFromProject)"
SourceDirectory="$(WebPublishPipelineProjectDirectory)"
TargetDirectory="$(WPPAllFilesInSingleFolder)"
SkipMetadataExcludeTrueItems="True"
UpdateItemSpec="True"
DeleteItemsMarkAsExcludeTrue ="True"
Condition="'#(FilesForPackagingFromProject)' != ''">
<Output TaskParameter="ResultPipelineItems" ItemName="_FilesForPackagingFromProjectTempory"/>
</CopyPipelineFiles>-->
<!-- Copying files to package folder in 'custom'(dirty) way -->
<CreateItem Include="$(OutputPath)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="#(YourFilesToCopy)"
DestinationFiles="#(YourFilesToCopy->'$(WPPAllFilesInSingleFolder)\%(RecursiveDir)%(Filename)%(Extension)')" />
Then
4. Your projectName.wpp.targets don't have to have FilesForPackagingFromProject, so it will look like:
<!-- targets -->
<PropertyGroup>
<DeployAsIisApp>false</DeployAsIisApp>
<IncludeSetAclProviderOnDestination>false</IncludeSetAclProviderOnDestination>
</PropertyGroup>
<ItemGroup>
<!-- intentionally left blank -->
</ItemGroup>
</Project>
That's it. Worked for me(tm), tested. Let me be honest, I don't like this approach, but that was the only way I made it working in the needed way. It's up to you whether you'll use it in your project or not.
My opinion is not to use msdeploy here - it was not for you task.
Better to write msbuild-scripts from scratch or accept the 'bin' folder, and fight against the framework again once next customization is required.

Running unit tests from a .proj file with MSBuild

I want to run unit tests using MSBuild. Here is how I invoke msbuild today:
msbuild MySolution.sln
Instead, I want to use an MSBuild project file called "MyBuild.proj" like this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5" DefaultTargets="Build">
<Target Name="Build">
<ItemGroup>
<SolutionToBuild Include="MySolution.sln" />
<TestContainer Include="..\Output\bin\Debug\*unittests.dll"/>
</ItemGroup>
</Target>
</Project>
And then call this command line:
msbuild MyBuild.proj
For some reason, when I do that the command succeeds immediately and the build doesn't even happen. I fear I must be missing something very obvious as I am new to MSBuild.
I suppose I really have 2 questions:
Why doesn't this even build my solution
Is the "TestContainer" element correct for executing my tests
Thanks!
You havent supplied any task to actually do anything,
inside your build target you need a call to an msbuild task, your example becomes:
<Target Name="Build">
<ItemGroup>
<SolutionToBuild Include="MySolution.sln" />
<TestContainer Include="..\Output\bin\Debug\*unittests.dll"/>
</ItemGroup>
<MSBuild Projects="#(SolutionToBuild)"/>
</Target>
this specifies what projects you actually want msbuild to build.
See:http://msdn.microsoft.com/en-us/library/vstudio/z7f65y0d.aspx for more details and the parameters it takes.
Thats part one.
As for part 2? what testing framework are you using? If using mstest id try wrapping the commandline mstest.exe in an msbuild exec statement to get it to run and execute the tests. See an example here:http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/cb87a184-6589-454b-bf1c-2e82771fc3aa

Copy all files and folders using msbuild

Just wondering if someone could help me with some msbuild scripts that I am trying to write. What I would like to do is copy all the files and sub folders from a folder to another folder using msbuild.
{ProjectName}
|----->Source
|----->Tools
|----->Viewer
|-----{about 5 sub dirs}
What I need to be able to do is copy all the files and sub folders from the tools folder into the debug folder for the application. This is the code that I have so far.
<ItemGroup>
<Viewer Include="..\$(ApplicationDirectory)\Tools\viewer\**\*.*" />
</ItemGroup>
<Target Name="BeforeBuild">
<Copy SourceFiles="#(Viewer)" DestinationFolder="#(Viewer->'$(OutputPath)\\Tools')" />
</Target>
The build script runs but doesn't copy any of the files or folders.
Thanks
I was searching help on this too. It took me a while, but here is what I did that worked really well.
<Target Name="AfterBuild">
<ItemGroup>
<ANTLR Include="..\Data\antlrcs\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(ANTLR)" DestinationFolder="$(TargetDir)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
This recursively copied the contents of the folder named antlrcs to the $(TargetDir).
I think the problem might be in how you're creating your ItemGroup and calling the Copy task. See if this makes sense:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
<YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
</PropertyGroup>
<Target Name="BeforeBuild">
<CreateItem Include="$(YourSourceDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="#(YourFilesToCopy)"
DestinationFiles="#(YourFilesToCopy->'$(YourDestinationDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
</Project>
I'm kinda new to MSBuild but I find the EXEC Task handy for situation like these. I came across the same challenge in my project and this worked for me and was much simpler. Someone please let me know if it's not a good practice.
<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
<Exec Command="xcopy.exe $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
<YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
</PropertyGroup>
<Target Name="BeforeBuild">
<CreateItem Include="$(YourSourceDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="#(YourFilesToCopy)"
DestinationFiles="$(YourFilesToCopy)\%(RecursiveDir)" />
</Target>
</Project>
\**\*.* help to get files from all the folder.
RecursiveDir help to put all the file in the respective folder...
This is the example that worked:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MySourceFiles Include="c:\MySourceTree\**\*.*"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy
SourceFiles="#(MySourceFiles)"
DestinationFiles="#(MySourceFiles->'c:\MyDestinationTree\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
source: https://msdn.microsoft.com/en-us/library/3e54c37h.aspx
This is copy task i used in my own project, it was working perfectly for me that copies folder with sub folders to destination successfully:
<ItemGroup >
<MyProjectSource Include="$(OutputRoot)/MySource/**/*.*" />
</ItemGroup>
<Target Name="AfterCopy" AfterTargets="WebPublish">
<Copy SourceFiles="#(MyProjectSource)"
OverwriteReadOnlyFiles="true" DestinationFolder="$(PublishFolder)api/% (RecursiveDir)"/>
In my case i copied a project's publish folder to another destination folder, i think it is similiar with your case.
Did you try to specify concrete destination directory instead of
DestinationFolder="#(Viewer->'$(OutputPath)\\Tools')" ?
I'm not very proficient with advanced MSBuild syntax, but
#(Viewer->'$(OutputPath)\\Tools')
looks weird to me. Script looks good, so the problem might be in values of $(ApplicationDirectory) and $(OutputPath)
Here is a blog post that might be useful:
How To: Recursively Copy Files Using the <Copy> Task
Personally I have made use of CopyFolder which is part of the SDC Tasks Library.
http://sdctasks.codeplex.com/
The best way to recursively copy files from one directory to another using MSBuild is using Copy task with SourceFiles and DestinationFiles as parameters. For example - To copy all files from build directory to back up directory will be
<PropertyGroup>
<BuildDirectory Condition="'$(BuildDirectory)' == ''">Build</BuildDirectory>
<BackupDirectory Condition="'$(BackupDiretory)' == ''">Backup</BackupDirectory>
</PropertyGroup>
<ItemGroup>
<AllFiles Include="$(MSBuildProjectDirectory)/$(BuildDirectory)/**/*.*" />
</ItemGroup>
<Target Name="Backup">
<Exec Command="if not exist $(BackupDirectory) md $(BackupDirectory)" />
<Copy SourceFiles="#(AllFiles)" DestinationFiles="#(AllFiles->
'$(MSBuildProjectDirectory)/$(BackupDirectory)/%(RecursiveDir)/%(Filename)%
(Extension)')" />
</Target>
Now in above Copy command all source directories are traversed and files are copied to destination directory.
If you are working with typical C++ toolchain, another way to go is to add your files into standard CopyFileToFolders list
<ItemGroup>
<CopyFileToFolders Include="materials\**\*">
<DestinationFolders>$(MainOutputDirectory)\Resources\materials\%(RecursiveDir)</DestinationFolders>
</CopyFileToFolders>
</ItemGroup>
Besides being simple, this is a nice way to go because CopyFilesToFolders task will generate appropriate inputs, outputs and even TLog files therefore making sure that copy operations will run only when one of the input files has changed or one of the output files is missing. With TLog, Visual Studio will also properly recognize project as "up to date" or not (it uses a separate U2DCheck mechanism for that).