Set output path for MSBuild task - msbuild

In the following simple MSBuild file I'd like to overwrite the output path that is defined in the .sln or .csproj file. In line 13 you can see that I call an MSBuild task for an existing VS solution. Usually, the projects that are part of that solution have a property where the output is stored. With my script I'd like to overwrite that so that my "build automation" uses a different directory than the default one.
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Default">
<PropertyGroup>
<appname>Some App</appname>
<version>2.9.1</version>
<file_xap>Some.App.WP8_$(version).$([System.DateTime]::Now.ToString(`yyyyMMddHHmmss`)).xap</file_xap>
</PropertyGroup>
<Target Name="Default">
<MSBuild Projects="C:\Users\User\Documents\Visual Studio 2013\Projects\SomeApp\SomeApp.sln" Properties="Configuration=Debug;Platform=Any CPU">
</MSBuild>
<Message Text="Output file: $(file_xap)"/>
</Target>
</Project>
So the actual question is: How can I call MSBuild for that sln in a way that the output (the xap-file in that case) to another directory (having all the output apart from the xap-file is fine as well)?

I will post my full xml here so you can understand it all
the structure of the project is like this:
MyProject----MyProject.sln
----MyProject.Server---
----MyProject.Server.proj
----Other server project classes and stuff
----MyProject.Client---
----MyProject.Client.proj
----Client project related stuff
----BuildFromXmlFldr---
----build_both_proj.xml <---This is the example file i posted here
Here is the build_both_proj.xml
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0"
DefaultTargets="Build">
<PropertyGroup>
<SolutionDir>..\</SolutionDir>
<ServerProjectFile>..\MyProject.Server\MyProject.Server.csproj</ServerProjectFile>
<ClientProjectFile>..\MyProject.Client\MyProject.Client.csproj</ClientProjectFile>
<ServerProjectName>MyProject.Server</ServerProjectName>
<ClientProjectName>MyProject.Client</ClientProjectName>
<ServerOutput>C:\_Publish\Server\</ServerOutput>
<ClientOutput>C:\_Publish\Client\</ClientOutput>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
</PropertyGroup>
<Target Name="BuildServer">
<MSBuild Projects="$(ServerProjectFile)"
Targets="Build"
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(ServerOutput);">
</MSBuild>
</Target>
<Target Name="BuildClient">
<MSBuild Projects="$(ClientProjectFile)"
Targets="Build"
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(ClientOutput);"
StopOnFirstFailure="true">
</MSBuild>
</Target>
<PropertyGroup>
<BuildAllDependsOn>BuildServer;BuildClient</BuildAllDependsOn>
</PropertyGroup>
<Target Name="BuildAll" DependsOnTargets="$(BuildAllDependsOn)"/>
</Project>
This is the msbuild.exe command inside the folder BuildFromXmlFldr that I used:
c:\path_to_msbuild\MSBuild.exe build_both_proj.xml /t:BuildAll
so the output is determined in the Properties attribute in the Target tag
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(ServerOutput);"

Related

MSBuild project to test a C++ program

I have a .vcxproj file that compiles a C++ program. I would like to create a second MSBuild project file that tests the program by running it, but only if the program has been rebuilt since the last successful test. How can I access the "TargetPath" of the program from the second project file?
If I could access TargetPath as an "item" from the .vcxproj file, then the the tester project file will look like this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build" Inputs="#(TargetPath)" Outputs="#(TargetPath->'%(filename).test-passed)'">
<Exec Command="#(TargetPath)" />
<Touch Files="#(TargetPath->'%(filename).test-passed)'" />
</Target>
</Project>
I would like to execute the test using a separate project file from the compilation of the program, to make it easier to choose between build-and-test or build-and-debug within Visual Studio, without multiplying the build configurations.
It is possible to run a native program compiled by a separate .vcxproj using the MSBuild task. Use the <Output> element to create an Item with the "TargetOutputs" from the C++ application build. However, if you are building a "native" program, "TargetOutputs" is normally blank. In this case, use the "GetNativeTargetPath" target to get the output path. The following project .vcxproj file works with Visual Studio. It builds test_build.vcxproj. The test_build.exe file is run, if it has changed since the last successful run.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{80DB0D71-72E0-4FB1-B53F-EFB858A1D5A8}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>nordic_test_run</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
<ProjectReference Include="test_build.vcxproj" />
</ItemGroup>
<Target Name="BuildExecutable">
<MSBuild Projects="#(ProjectReference)" Targets="Build" BuildInParallel="True" />
<MSBuild Projects="#(ProjectReference)" Targets="GetNativeTargetPath" BuildInParallel="True">
<Output TaskParameter="TargetOutputs" ItemName="NativeTests" />
</MSBuild>
</Target>
<Target Name="Build" DependsOnTargets="BuildExecutable" Inputs="#(NativeTests)" Outputs="#(NativeTests->'%(filename).test-passed')">
<Exec Command="#(NativeTests)" />
<Touch Files="#(TestTargets->'%(filename).test-passed')" />
</Target>
</Project>

MSBuild multiple outputpath

I saw this S.O question and have a similar requirement. This is what I have in a .targets file -
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="$(TeamBuildOutDir) != '' ">
<OutputPath>$(TeamBuildOutDir)\Assemblies</OutputPath>
</PropertyGroup>
How can I output to multiple folders?
e.g.- $(TeamBuildOutDir)\Assemblies2
TIA
Thanks Nick, The copy/paste mucked it up. This is what I tried -
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="$(TeamBuildOutDir) != '' ">
<OutputPath>$(TeamBuildOutDir)\Assemblies</OutputPath>
</PropertyGroup>
<Target Name="AfterBuild">
<Copy SourceFiles="$(OutputPath)\**\*.*" DestinationFolder="$(TeamBuildOutDir)\Assemblies2" />
</Target>
</Project>
I've also tried -
<Copy SourceFiles="$(OutputPath)\***\*.*" DestinationFolder="$(TeamBuildOutDir)\Assemblies2" />
and -
<Copy SourceFiles="$(OutputPath)\***\*.*" DestinationFolder="$(TeamBuildOutDir)\" />
in case the directory not being present caused an issue but still no luck.
Updated 7/28. Tried this but doesn't work still (no errors but the files are not present in the output directory. They are present in the Assemblies folder so I know the targets file is being triggered.) -
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="$(TeamBuildOutDir) != '' ">
<OutputPath>$(TeamBuildOutDir)\Assemblies</OutputPath>
</PropertyGroup>
<Target Name="AfterBuild">
<CreateItem Include="$(OutputPath)\**\*.*">
<Output ItemName="Outfiles" TaskParameter="Include" />
</CreateItem>
<Copy SourceFiles="#(Outfiles)" DestinationFiles="#(Outfiles->'$(TeamBuildOutDir)\%(relativedir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
</Target>
</Project>
You create an AfterBuild target with a copy task the contents of $(OutputPath) to $(TeamBuildOutDir)\Assemblies2.
<Target Name="AfterBuild">
<Copy SourceFiles="$(OutputPath)\**\*.*" DestinationFolder="$(TeamBuildOutDir)\Assemblies2" />
</Target>
Edit, updating this to include a test message, and include a "DependsOnTarget" attribute to see if we can get this to occur after the build process...
<Target Name="AfterBuild" DependsOnTarget="Build">
<Message Text="**** TEST **** " Importance="high" />
<Copy SourceFiles="$(OutputPath)\**\*.*" DestinationFolder="$(TeamBuildOutDir)\Assemblies2" />
</Target>

Using MSBuild to buld a solution (.sln) with many projects in how can I make each project build into its own folder?

I am trying to create a simple build process for a quite complex (many projects) vs2010 solution.
I wish for a folder structure such as this
-Build
-Proj1
-proj1.exe
-proj1.dll
-Proj2
-proj2.exe
-proj2.dll
......
-Projn
-projn.exe
-projn.dll
What I am getting from my attempts below is
-Build
-proj1.exe
-proj1.dll
-proj2.exe
-proj2.dll
-projn.exe
-projn.dll
I currently have this as a .proj file. (see below)
This builds things fine, however it puts everything in the "build" folder that I specify. I want each project to be in its own seperate folder within that 'build' folder. How can I achive this?
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildOutputDir>C:\Projects\BuildScripts\Build</BuildOutputDir>
<SolutionToCompile>PathToSolution.sln</SolutionToCompile>
</PropertyGroup>
<Target Name="Clean">
<RemoveDir Directories="$(BuildOutputDir)" />
</Target>
<Target Name="Compile">
<MakeDir Directories="$(BuildOutputDir)" />
<MSBuild Projects="$(SolutionToCompile)"
properties = "OutputPath=$(BuildOutputDir)" Targets="Rebuild" />
</Target>
<Target Name="Build" DependsOnTargets="Clean;Compile">
<Message Text="Clean, Compile"/>
</Target>
</Project>
I call the .proj with a simple bat
"%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" /nologo externalBuild.proj /m:2 %*
pause
I have also tried a more complex version (copy and paste!) that looks more like it should work, but still puts things in a single folder.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectsToBuild Include="path to solution folder\**\*proj" Exclude="$(MSBuildProjectFile)"/>
</ItemGroup>
<PropertyGroup>
<Configuration>CI</Configuration>
</PropertyGroup>
<Target Name="CoreBuild">
<MSBuild Projects ="#(ProjectsToBuild)"
ContinueOnError ="false"
Properties="Configuration=$(Configuration)">
<Output ItemName="OutputFiles" TaskParameter="TargetOutputs"/>
</MSBuild>
</Target>
<PropertyGroup>
<DestFolder>Build\</DestFolder>
</PropertyGroup>
<Target Name="CopyFiles">
<Copy SourceFiles="#(OutputFiles)"
DestinationFiles="#(OutputFiles->'$(DestFolder)%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="CleanAll">
<!-- Delete any files this process may have created from a previous execution -->
<CreateItem Include="$(DestFolder)\**\*exe;$(DestFolder)\**\*dll">
<Output ItemName="GeneratedFiles" TaskParameter="Include"/>
</CreateItem>
<Delete Files="#(GeneratedFiles)"/>
<MSBuild Projects="#(ProjectsToBuild)" Targets="Clean" Properties="Configuration=$(Configuration);"/>
</Target>
<PropertyGroup>
<BuildAllDependsOn>CleanAll;CoreBuild;CopyFiles</BuildAllDependsOn>
</PropertyGroup>
<Target Name="BuildAll" DependsOnTargets="$(BuildAllDependsOn)"/>
</Project>
Using devenv.com to build from the command line will do what you want. It will use the output directories specified in the project files. This is what we're using, because at the moment we don't need more control over the build mechanism.

Change AssemblyName of a csproject via msbuild

I have a msbuild that calls a *.sln file when doing compilation. This solution file contains 10 csprojects, one of them ( let's call it main.csproject) has the AssemblyName as WinMusic. The content of the msbuild is as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- Default value here -->
<DefineConstants Condition=" '$(DefineConstants)'==''" >TRACE</DefineConstants>
<SlnFiles Condition=" '$(SlnFiles)'==''" >FullProject.sln</SlnFiles>
</PropertyGroup>
<!-- <ItemGroup> -->
<!-- <SlnFiles Include="SlnFiles=$(SlnFiles2)"/> -->
<!-- </ItemGroup> -->
<Target Name="Build">
<MSBuild Projects="$(SlnFiles)"
Properties="DefineConstants=$(DefineConstants)"/>
</Target>
</Project>
My question is, how to set the AssemblyName property from the above msbuild task?
Just to clarify, I'm talking about AssemblyName in csproject, not in AssemblyInfo.cs.
Edit: This is the new build.proj file I tried, the FullProject.sln is a solution file with one exe and one dll, but the msbuild file renamed both the dll and the exe to NoMusic. What I want is just to rename the exe to NoMusic and the dll should retain the same name.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- Default value here -->
<DefineConstants Condition=" '$(DefineConstants)'==''" >TRACE</DefineConstants>
<SlnFiles Condition=" '$(SlnFiles)'==''" >FullProject.sln</SlnFiles>
</PropertyGroup>
<Target Name="Build">
<MSBuild Projects="$(SlnFiles)"
Properties="DefineConstants=$(DefineConstants)"/>
<MSBuild Projects="WindowsFormsApplication1\WindowsFormsApplication1.csproj"
Properties="DefineConstants=$(DefineConstants);Platform=ANYCPU;AssemblyName=NoMusic"/>
</Target>
</Project>
Just do this:
<Target Name="Build">
<MSBuild Projects="#(SlnFiles)"
Properties="DefineConstants=$(DefineConstants)"/>
<MSBuild Projects="main.csproject.csproj"
Properties="AssemblyName=NoMusic"/>
Love to know why though.

Why won't the copy task item work in my msbuild script?

I have the following code in my msbuild script:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" InitialTargets="Build">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SolutionName>CommTrac.Web\CommTrac.Web</SolutionName>
<SolutionFileName>$(SolutionName).csproj</SolutionFileName>
</PropertyGroup>
<Target Name="Build">
<Message Text="Building the solution"/>
<MSBuild Projects="$(SolutionFileName)" ContinueOnError="false" Properties="Configuration=$(Configuration)" />
</Target>
<Target Name="CopyOutput" DependsOnTargets="Build">
<ItemGroup>
<BinFolder Exclude="*.pdb" Include="$(ProjectDir)bin\**\*.*"/>
<BuildOutputFolder Include="C:\BuildOutput" />
</ItemGroup>
<Message Text="Copying from directory: $(BinFolder)"/>
<Copy SourceFiles="$(BinFolder)" DestinationFolder="$(BuildOutputFolder)"/>
</Target>
</Project>
For some reason, it will not copy the files to my output directory. I have tried all the similar
solutions with other questions that I have seen similar to this issue. Anyone have any ideas?
BindFolder and BuildOutputFolder are items, not properties. So you need to reference them using #(BindFolder) and #(BuildOutputFolder) instead of using '$'.