Using a project file as a parameter in MSBuild with Hudson - msbuild

I'm currently using the Hudson build system with MSBuild steps. As part of the build, I have a project file with various targets in, one of which is to start a build with visual studio. However, I need to pass through a seperate project file to this target in order for it to build, but I keep getting the exception 'MSBUILD : error MSB1008: Only one project can be specified.'
I believe this is because the system is unable to calculate which project is supposed to be the parameter, and which the top-level target? If so, is there anyway to resolve this.
Here is a snippet of the target project file:
<Target Name="VisualStudioTask">
<!-- Required Properties:
$(BuildType)
$(ConfigurationSetup)
$(Solution)-->
<Exec Command="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe $(BuildType) $(ConfigurationSetup) $(Solution)" />
</Target>
The MSBuild step calling this looks like this:
/t:VisualStudioTask -p:BuildType="/Build" p:ConfigurationSetup="Release" -p:Solution="%22..\MyProject.vcproj%22"
Many thanks
Chris

I have figured it out, the problem was that I'd left out a '-' when declaring the 'ConfigurationSetup' parameter, so if you look in my original example it has this:
/t:VisualStudioTask -p:BuildType="/Build" p:ConfigurationSetup="Release" -p:Solution="%22..\MyProject.vcproj%22"
When it should have this..
/t:VisualStudioTask -p:BuildType="/Build" -p:ConfigurationSetup="Release" -p:Solution="%22..\MyProject.vcproj%22"

Related

MSBuild: ProjectReference Output Path in Wix Projects

I'm trying to get the Output folder of referenced project in my Wix Visual Studio project, using MsBuild task. But it is failing with following error:
C:\Program Files
(x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(724,5):
error : The OutputPath property is not set for project
'ConsoleApplicatio n1.csproj'. Please check to make sure that you
have specified a valid combination of Configuration and Platform for
this project. Configuration='Release' Platfo rm='x86'. You may be
seeing this message because you are trying to build a project without
a solution file, and have specified a non-default Configuration or
Plat form that doesn't exist for this project.
[C:\Users\fwaheed\Documents\Visual Studio
2015\Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cspro
j]
Following is the Target calling MsBuild task.
<Target Name="AfterBuild">
<MSBuild
Projects="#(ProjectReference)"
Targets="GetTargetPath"
BuildInParallel="false"
Condition="'%(Name)'=='ConsoleApplication1'" >
<Output TaskParameter="TargetOutputs" ItemName="DependentAssemblies" />
</MSBuild>
</Target>
Please note that same target worked perfectly if it is CSharp project, but failing in Wix project.
Can someone guide how to get ReferencedProjects output dirs in Wix Projects?
Thanks
You can try to see how Wix does it for passing the reference values to candle on build. They're in the wix2010.targets or wix200x.targets file. Unfortunately I don't have the time to really dig into this stuff but the properties these tasks set should still exist to be used in your AfterBuild target.
Just search for "ResolveReferences" in one of those targets files.
You can also just try setting
<OutputPath>somepathhere</OutputPath>
in your csproj file since msbuild is complaining that the property isn't set.

MSBuild - Execute Custom Targets w/o modifying individual projects

I have custom MSBuild Tasks to execute after the : AfterBuild event for each project in a solution.
I don't want to modify each Project file as:
Visual Studio wipes out all the Custom Changes done to the project file once i modify the project in Visual Studio (VS 2012 Ultimate), say add or remove a file/reference.
I don't want to use "CustomAfterMicrosoftCommonTargets" as mentioned here as there is no way to pass this command line argument while building from Visual Studio :
msbuild.exe app.proj /property:CustomAfterMicrosoftCommonTargets=custom.target
I found a solution here, but I didn't quite get it.
Can anybody please elaborate on it or help me figure out a better solution?
Update 5/12/2014:
I figured out that Visual Studio doesn't wipe out the custom changes if I am running the Visual Studio in the Administrator mode.
I can now think of having a Custom import file that has got the required overrides, but still I have to do this for each project in the solution. If somebody adds a new project, they have to remember to add this customization. I don't like this, but probably I can live with for now.
I tried to use the "CustomAfterMicrosoftCommonTargets" approach, but I was not able to set this property from the Pre-build event of Visual Studio, even running as Administrator didn't help.
I was trying to set an environment variable with same name from the Pre-Build event, but I never got the new value while MSBuild executes.
Thanks!
Finally I found an option where in I don't have to edit the individual project file.
The idea is to invoke your custom common targets file in the "AfterBuild" event that Visual Studio exposes.
IF "$(BuildingInsideVisualStudio)"=="true" (
$(MSBuildBinPath)\msbuild.exe "$(ProjectDir)CustomMSBuild.targets" /p:Configuration="$(Configuration)"/property:"ProjectUnderCompilation=$(MSBuildThisFileDirectory)$(MSBuildThisFile)"
)
So I am passing the project under compilation as a property and import that project file.
If I throw an exception in the custom task, it appears as as Compilation error on the parent project.
This worked amazingly and I am able to perform any validations on the project that was passed.
The only downside I see is that I am spawning another MSBuild.exe and I don't see any impact of that in the compilation time as of now.
Please let me know your thoughts on this implementation.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="MyTarget">
<UsingTask AssemblyFile="$(ProjectDir)\bin\TaskLibrary.dll" TaskName="CheckProjectReferences" />
<PropertyGroup>
<ProjectUnderCompilation></ProjectUnderCompilation>
</PropertyGroup>
<Target Name="MyTarget">
<Message Text="Inside MyTarget" Importance="High" />
<CheckProjectReferences/>
</Target>
<Import Project="$(ProjectUnderCompilation)" />
</Project>

msbuild script unable to build specific build config of C++ Builder 2010 project

I have a project group in C++ Builder 2010. It contains several projects. One of these projects has, besides Debug and Releae, a Demo build configuration that is a child of the Release one.
The issue I run into is that if I run this from the build script we have, calling the project group file and telling it I want to build using the Demo configuration I get an error about unresolved WinMain. I get the same error by using a build configuration name that does not exist. So my initial thought was that this had to be due to the fact that the other projects in the project group didn't have a Demo configuration. But when I tried running msbuild against the project group file from cmd passing it Demo it built just fine.
C:\src\foo\AutoBuild> msbuild ..\foo.groupproj /t:build /p:Configuration=Demo
The same goes for building the specific project using msbuild from cmd. I have checked that the Config/*Configuration* property is carried over through each <msbuild /> task call and it is.
Hacking the project group (.groupproj) file and forcing it to run Demo for the project in question when running Release also worked.
...
<Target Name="Foo:Make">
<MSBuild Targets="Make" Projects="Foo.cbproj" Properties="Config=Demo"/>
</Target>
...
Any idea what could be causing this?
Update
Also, by running only the specific project in the main build script when Demo is selected it also works fine. Note that the Release build has been built by the build script prior to this.
<Target Name="Foo:Build">
...
<MSBuild Condition="$(Configuration)==''" Targets="Make" Projects="..\Server\Bar.groupproj" Properties="Config=Release" />
<MSBuild Condition="$(Configuration)==''" Targets="Foo" Projects="..\Server\Bar.groupproj" Properties="Config=Demo" />
...
</Target>

How do I specify the platform for MSBuild?

I am trying to use MSBuild to build a solution with a specified target platform (I need both binaries, x86 and x64). This is how I tried it:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild SolutionPath\Solution.sln /t:Rebuild /p:Configuration=Release /p:Platform="x86"
However the build always fails if the platform is different from "Any CPU". What am I doing wrong?
This is the while output MSBuild prints:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild
SolutionPath\Solution.sln /t:Rebuild
/p:Configuration=Release
/p:Platform="x86" Microsoft (R) Build
Engine Version 3.5.30729.1 [Microsoft
.NET Framework, Version
2.0.50727.3082] Copyright (C) Microsoft Corporation 2007. All rights
reserved.
Build started 1.7.2010 8:28:10.
Project "SolutionPath\Solution.sln" on
node 0 (Rebuild targe t(s)).
SolutionPath\Solution.sln : error
MSB4126: The specified sol ution
configuration "Release|x86" is
invalid. Please specify a valid
solution c onfiguration using the
Configuration and Platform properties
(e.g. MSBuild.exe Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
prope rties blank to use the default
solution configuration. Done Building
Project "SolutionPath\Solution.sln"
(Rebuild t arget(s)) -- FAILED.
Build FAILED.
"SolutionPath\Solution.sln" (Rebuild
target) (1) ->
(ValidateSolutionConfiguration target)
-> SolutionPath\Solution.sln : error MSB4126: The specified s olution
configuration "Release|x86" is
invalid. Please specify a valid
solution configuration using the
Configuration and Platform properties
(e.g. MSBuild.ex e Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
pro perties blank to use the default
solution configuration.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.03
If I try to build it for x86/x64 with devenv it works perfectly, however I am trying to set up a build server without installing all the necessary versions of Visual Studio. By the way, if there is a better free tool (that supports .NET framework 4) out there, I'd love to hear about it.
In MSBuild or Teamcity use command line
MSBuild yourproject.sln /property:Configuration=Release /property:Platform=x64
or use shorter form:
MSBuild yourproject.sln /p:Configuration=Release /p:Platform=x64
However you need to set up platform in your project anyway, see the answer by Julien Hoarau.
If you want to build your solution for x86 and x64, your solution must be configured for both platforms. Actually you just have an Any CPU configuration.
How to check the available configuration for a project
To check the available configuration for a given project, open the project file (*.csproj for example) and look for a PropertyGroup with the right Condition.
If you want to build in Release mode for x86, you must have something like this in your project file:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
...
</PropertyGroup>
How to create and edit the configuration in Visual Studio
(source: microsoft.com)
(source: msdn.com)
(source: msdn.com)
How to create and edit the configuration (on MSDN)
If you're trying to do this from the command line, you may be encountering an issue where a machine-wide environment variable 'Platform' is being set for you and working against you. I can reproduce this if I use the VS2012 Command window instead of a regular windows Command window.
At the command prompt type:
set platform
In a VS2012 Command window, I have a value of 'X64' preset. That seems to interfere with whatever is in my solution file.
In a regular Command window, the 'set' command results in a "variable not defined" message...which is good.
If the result of your 'set' command above returns no environment variable value, you should be good to go.
Hopefully this helps someone out there.
For platform I was specifying "Any CPU", changed it to "AnyCPU" and that fixed the problem.
msbuild C:\Users\Project\Project.publishproj /p:Platform="AnyCPU" /p:DeployOnBuild=true /p:PublishProfile=local /p:Configuration=Debug
If you look at your .csproj file you'll see the correct platform name to use.
For VS2017 and 2019... with the modern core library SDK project files, the platform can be changed during the build process. Here's an example to change to the anycpu platform, just before the built-in CoreCompile task runs:
<Project Sdk="Microsoft.NET.Sdk" >
<Target Name="SwitchToAnyCpu" BeforeTargets="CoreCompile" >
<Message Text="Current Platform=$(Platform)" />
<Message Text="Current PlatformTarget=$(PlatformName)" />
<PropertyGroup>
<Platform>anycpu</Platform>
<PlatformTarget>anycpu</PlatformTarget>
</PropertyGroup>
<Message Text="New Platform=$(Platform)" />
<Message Text="New PlatformTarget=$(PlatformTarget)" />
</Target>
</Project>
In my case, I'm building an FPGA with BeforeTargets and AfterTargets tasks, but compiling a C# app in the main CoreCompile. (partly as I may want some sort of command-line app, and partly because I could not figure out how to omit or override CoreCompile)
To build for multiple, concurrent binaries such as x86 and x64: either a separate, manual build task would be needed or two separate project files with the respective <PlatformTarget>x86</PlatformTarget> and <PlatformTarget>x64</PlatformTarget> settings in the example, above.
When you define different build configurations in your visual studio solution for your projects using a tool like ConfigurationTransform, you may want your Teamcity build, to build you a specified build configuration. You may have build configurations e.g., Debug, Release, Dev, UAT, Prod etc defined. This means, you will have MSBuild Configuration transformation setup for the different configurations. These different configurations are usually used when you have different configurations, e.g. different database connection strings, for the different environment. This is very common because you would have a different database for your production environment from your playground development environment.
They say a picture is worth a thousand words, please see the image below how you would specify multiple build configurations in Teamcity.
In the commandline input text box, specify as below
/p:OutputPath=Publish;Configuration=Dev
Here, I have specified two commandline build configurations/arguments OutputPath and build Configuration with values Publish and Dev respectively, but it could have been, UAT or Prod configuration. If you want more, simply separate them by semi-colon,;
There is an odd case I got in VS2017, about the space between ‘Any’ and 'CPU'.
this is not about using command prompt.
If you have a build project file, which could call other solution files. You can try to add the space between Any and CPU, like this (the Platform property value):
<MSBuild Projects="#(SolutionToBuild2)" Properties ="Configuration=$(ProjectConfiguration);Platform=Any CPU;Rerun=$(MsBuildReRun);" />
Before I fix this build issue, it is like this (ProjectPlatform is a global variable, was set to 'AnyCPU'):
<MSBuild Projects="#(SolutionToBuild1)" Properties ="Configuration=$(ProjectConfiguration);Platform=$(ProjectPlatform);Rerun=$(MsBuildReRun);" />
Also, we have a lot projects being called using $ (ProjectPlatform), which is 'AnyCPU' and work fine. If we open proj file, we can see lines liket this and it make sense.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
So my conclusion is,
'AnyCPU' works for calling project files, but not for calling solution files,
for calling solution files, using 'Any CPU' (add the space.)
For now, I am not sure if it is a bug of VS project file or MSBuild.
I am using VS2017 with VS2017 build tools installed.
In Visual Studio 2019, version 16.8.4, you can just add
<Prefer32Bit>false</Prefer32Bit>

Get a Visual Studio project (MSBuild) to know the Team Build output location

I have this custom build step form my project:
<Target Name="BeforeBuild">
<WriteLinesToFile Condition="" File="$(OutputPath)\env.config"
Lines="$(Configuration)" Overwrite="true">
</WriteLinesToFile>
</Target>
Basically it outputs the build configuration to a file.
This works fine when building in Visual Studio. Team Build decided to make things harder. The OutputPathfor Team Build is in a different spot (not bin\$(Configuration))
I know how to find out if the build is part of a team build (Condition=" '$(TeamBuildConstants)' == '_TEAM_BUILD_' ") but unless I want to hard code the path, I can't see a way to get the Team Build path.
Any ideas on how to find out (in the project, the the Team Build file) what the output location is?
You might need to use $(OutDir) when running in Team Build:
http://blogs.msdn.com/aaronhallberg/archive/2007/06/07/preserving-output-directory-structures-in-orcas-team-build.aspx
So you could use the _TEAM_BUILD_ condition and have two calls - one with OutputPath and one with OutDir.