I feel I am missing something extremely basic; yet I have spent hours to no avail. I am trying to get a TFS build working and for the life of me I cannot figure out where this property gets set from.
I have picked up a TFS 2010 project from a team member that cannot help me at this time.
I have a simple TFS build that builds a solution.
In the tfproj file I have:
<SolutionToBuild Include="$(BuildProjectFolderPath)/MySolution.sln">
This seems to work, but for the life of me I cannot figure out how. I have not set the variable $(BuildProjectFolderPath) anywhere or anything resembling the correct path to MySolution.sln.
I have checked both the build definition, the build script, and the environment variables on the build box and I cannot figure out where the path corresponding to $(BuildProjectFolderPath) comes from.
Can someone help me unravel this black magic ?
Your build is actually performed by MSBuild. When MSuild starts, it gets some environment type of variables initialized that are project / solution specific. For example on the build server, the build agent will have injected its BuildProjectFolderPath value in MSBuild, that is used to resolve the macro that is in your tfsproj file.
No magic, just the environment that startup up to process your request supplies those values.
Related
The default build template for TFS has a format of $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)
This translates to something like BuildName_20141111.1 for the first build of the day, BuildName_20141111.2 for the second and so on that.
That's all well and good but what I'd like to do is pull out that .r and insert it into the assembly before it's compiled by the build server.
I've already edited the build template to update the various AssemblyInfo.cs files and such and that's working fine. Right now we are toying with the idea of Major.Minor.yyDDD (Day of year).r but the catch is that very last part - how do we get $(Rev:.r) from within a build template?
I've tried looking through the various environmental variables and I can pull out the entire Build definition string (i.e. BuildName_20141111.1) but really all I want is that .1 (or more specifically "1"). Is there a way to do this programmatically? Is there an environment variable I've missed? Or is there a way that I can actually access things like $(Rev:.r) directly?
I am relatively new to TFS but this is the last hurdle before I can move a lot of projects to it.
You effectively need to parse this off yourself from the BuildName parameter. If you are using TFS 2013 you can do it in PowerShell. Prior versions need a customized build template.
There are prebuilt solutions to this. Best is the TfsVersion activity or the VersionAssemblies.ps1 that is provided as part of the TFS Community Build Tools.
I've got a boatload of legacy project files that use a $(ProjectRoot) variable in include paths to refer to the root of the source tree. We define the variable in our visual studio environment so desktop builds can find their way to the tfs workspace in use.
I would like to define this variable in the Team Build environment via an MSBuild command line option in my tfs build definition, but I can't seem to find a way that works. I found an answer (List of msbuild properties TFS passes to a build script) with a list of variables and SolutionRoot looked promising.
When I put /p:ProjectRoot=$(SolutionRoot) in the MSBuild Arguments for my build definition, ProjectRoot ends up empty. I want it to expand to something like D:\Builds\18\TfsProject\BuildDef\src\
Is there a way to define my variable with the value of the root of the workspace sources in Team Build?
Note: I tried to figure this out in TFS2010 and finally gave up and modified the BuildProcessTemplate to define the variable using the SourcesDirectory variable that's available inside that context. I thought I'd take another run at it in the hopes of using the new template in TFS2013 without modification, but I'm still stumped.
UPDATE: Turns out the syntax I had in my MSBuild Arguments would work if the variable I'm dereferencing were actually being passed to msbuild. The list from the other post I reference seems to no longer be valid. Looking at the detailed Team Build logs, it looks like the only variables being passed in to msbuild in Team Build are OutDir, BuildId, BuildLabel, BuildTimestamp, BuildSourceVersion, and BuildDefinition. None of those gives me the info my current msbuild scripts need at build time so I'm stuck with either reworking all our project files or continuing with the BuildProcessTemplate modifications I've been using. Unless someone comes along with a better answer here.
You should be able to specify /p:ProjectRoot=$(TF_BUILD_SOURCESDIRECTORY) in the MSBuild Arguments of your build definition when using TFS2013.
See the Team Foundation Build environment variables documentation for more information.
Set the property using the other property. Use condition to only set it if its empty.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="xxxxxxxxxxxx">
<PropertyGroup>
<ProjectRoot Condition="$(ProjectRoot)==''"/>$(SolutionRoot)</ProjectRoot>
</PropertyGroup>
I have setup a build controller etc and the builds were failing, I have fixed these now and the build failed properly - as in because of an error.
I have fixed the error and checked the code back in but now the code is not being extracted, although sometimes one folder of many is.
I have deleted the code from the build machine and requeued a build but it keeps failing. It complains that it cannot find the solution that I specified as the build solution.
I have checked the check box to build even if nothing has changed.
Have I missed a setting somewhere for extracting the code?
TFS version is 2012 Express
Visual Studio version is 2010 Professional
I had this issue recently with TFS 2012. I think it boils down to this:
In the lastest build definition files, it appears that it performs a Clean task before updating the workspace. This means that if you do something that causes the Clean part of the build to fail, it will never download the new files in order to fix it.
Recently, I was making big changes to my build file and inevitably made a lot of mistakes, I found that if one of these mistakes caused the Clean to break, I had to go onto the Build server and change the file manually to get it working again.
Does this sound like it might be the same issue?
There are several properties in your build definition you can check. I would start with setting the "Clean Workspace" to All to ensure the correct code is being pulled down and built.
There are other checks you can look at as well like the agent set for the build and the "GetVersion" property. Check the below link out. It should be able to help you in more detail.
Define a Build Process that is Based on the Default Template
I'm trying to get Silverlight unit tests integrated into a TFS build using a "Generic Test" on a test project to wrap Statlight
When I hard code the paths to everything it works fine but I'm tearing my hair out trying to work out how to pass project-relative paths to the generic test so that it works in the TFS build environment.
The closest I've come is to have the build process workflow set environment variables pointing to StatLight and the xap files containing the SL unit tests so that I can reference those in the command line arguments to statlight.
Feels hacky though - is there a better way of getting path information into generic tests based on the current solution/build configuration?
The MSDN documentation uses a couple of environment variables (%TestDeploymentDir% for one) that I can't find documented anywhere so I'm wondering if there are any more magic variables that I can use to infer paths from rather than having to set my own.
Here are some references on MSBuild properties:
Common MSBuild Project Properties
MSBuild Reserved Properties
Team Build 2008 Property Reference
Hope that helps.
I have a vcproj file that includes a simple pre-build event along the lines of:
Helpertask.exe $(ProjectDir)
This works fine on developer PCs, but when the solution is built on our TFS 2008 build server under MSBuild, $(ProjectDir) is either blank or points to an unrelated folder on the server!
So far the best workaround I have managed is to hard code the developer and server paths instead:
if exist C:\DeveloperCode\MyProject HelperTask.exe C:\DeveloperCode\MyProject
if exist D:\BuildServerCode\MyProject HelperTask.exe D:\BuildServerCode\MyProject
This hack works in post-build steps but it doesn't work for a pre-build step (the Pre-build task now does nothing at all under MSBuild!)
Do you have any ideas for a fix or workaround? I have very little hair left!
$(MSBuildProjectDirectory) worked for me
I think your problem may be related to how items are initalized. An items include attribute is evaluated at the begining of a build. So if you depend on files that are created in the build process you must declare these as dynamic items. Dynamic items are those defined inside of a target, or by using the CreateItem task. I've detailed this on my blog MSBuild: Item and Property Evaluation.
Sayed Ibrahim Hashimi
My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build
I think the problem is that build server's workspace probably isn't initialized properly.
I just kept getting problems with this - I tried many different approaches but they all failed in mysterious ways.
Once $(ProjectDir) started behaving properly again, the pre-build step stopped executing the command (I added echo commands above and below it - they were both executed, but the program in between them was not. No errors or output of any kind were generated to indicate why it failed).
I don't know if this is a dodgy server of if MSBuild is having a laugh.
I've given up now. I gave the build server a big kick and have changed tack: We now run this tool offline (manually) and check in the results for the build server to use. So much for an automated build :-( If only MSBuild would run solutions in the same way as Visual Studio does - it's maddening that it sets up the environment completely differently (different paths coming out of the solution variables, ouptus redirected into different folders so you can't find them where they're supposed to be, etc)
I branched an existing project and $(ProjectDir) kept the old directory in the newly branched code. But that's because I had some compiling errors. Once every project in the solution compiled without errors, $(ProjectDir) changed to the correct path.
Carlos A Merighe