Using wixlibs from another solution with TFS builds - tfs

We have installers referencing a wixlib file to get some common functionality. The wixlib is built in another solution then moved to a folder within that solution. When we try to build the installers with a TFS build, we get an error from light.exe:
light.exe: The system cannot find the file '..\..\..\Core\Common\assemblies\v1.0\Common.Wix.wixlib' with type 'Source'.
Our regular projects can reference \assembiles\v1.0, since we have some other common assemblies stored there. How do we get WiX to recognize this location during build?

You are referencing wixlib directly. So as far as I understand the TFS build process, it should be added to TFS project of your solution. TFS project shouldn't be dependent on the output of another non-dependent solution. It is at least bad practice. And in any case you can't guarantee this output would be generated before your project build on server.
As far as I remember, TFS build creates separate folder for each build and gets sources there. So your solutions are no longer on the same folder hierarchy level.
One more point in favor of explicitly copying wixlibs into your installer project: versioning - in this case any bugs made in the common library will not immediately break all projects that reference it. And you can gradually upgrade and test every project. Can you imagine auomatically downloading new version of any 3rd party dll on every build? Any change in that dll will immediately break your application even if changes are not critical to you.

Since the shared component and the active solution are in two separate projects in TFS, the workspace must be setup so that the relative paths for references remain intact. The easiest way to do this is to set your Build Agent Folder structure in Workspace in your TFS Build to have $(SourceDir) represent your root. However, don't change your Source Control Folder - that stays the same.
For example, say you have the following structure:
-TFS
|-SharedComponents
||-MyComponents
|-ProjectArea
||-MyProject
You would want to have the following two items in the build Workspace:
Source Control Folder Build Agent Folder
---------------------------------------------------------------------------------
$/ProjectArea/MyProject $(SourceDir)\ProjectArea\MyProject
$/SharedComponents/MyComponents $(SourceDir)\SharedComponents\MyComponents
This mimics the structure in TFS in your build folder, thus allowing all relative paths to remain intact.
One more note about this configuration: Since you have the shared components in another location, you may want to create a solution folder in MyProject and add the components that you are using to it. This will ensure they get pulled automatically when anyone loads your project from TFS - they won't have to go back and pull down the share components folder separately after discovering a build error.

Related

TFS Online/VSO Build with Common Assemblies

I was wondering if anyone could help.We have the following project structure in our company :
Code/Common
Code/Project1
Code/Project2
etc...
When the Common Project builds, it has a PostBuild Event that copies all the relevant files into the Code/Common/Binaries folder. Then all the other Projects reference the Common components in this folder.
However, what we are struggling with is that when TFS Online checks-out the solution it does so to c:\a\src and the Common binaries are placed in c:\a\src\Binaries. Now, when the other projects (Project1 etc) do their build it cannot find the Common Assemblies, as not only are they removed, but the paths are different from what it expects them to be in c:\a\src\Common\Binaries instead of c:\a\src\Binaries.
Is there anyway to tell the build server to not delete those files in the "Binaries" directory and to specify the folder location to checkout to? Or how one one go about solving such a problem?
Thanks very much
A build server is a transient thing, you cannot rely on files to be there.
You need to either Create Nuget Packages for you common output and then consume these in your other projects (the 'proper' way), or you will need to check your dependencies into source control after each build so you can then reference them in subsequent builds (the 'really frowned apon' way).

How do I make an automated build use same output folders as a manual build?

Background
Currently I have many C# projects in many TFS team projects.
Several C# projects reference C# projects in different team projects. I do this by referencing the output dll in the Bin/Release folder of the other C# project.
As long as we checkout & build the solutions in the team projects in the correct order everything works fine on all dev's machines.
We're moving to Visual Studio Online and I'm playing around with automated builds.
Problem
The problem I'm having is that it can't find the dlls to reference, even after the project that would output them (to \Bin\Release) has ran.
I've disabled parallel builds (to ensure the referenced projects get built first) and this seems to be the case based on the build logs. The issue is that the projects that depend on these can't find the dlls and as a result I get "the type or namespace could not be found" errors everywhere.
What's the easiest way of resolving this?
Note that I've read several posts/tutorials etc. about this but all seem to involve changing the source control structure, or fiddling about with workspaces etc. I want something where I can keep the simple workspace mapping on the dev's machines where we map "$\" to "C:\TFS\". I don't want to have to remember to periodically merge in changes from a shared library, or maintain lots of folder mappings within a workspace (on dev machines).
Open your process template xaml (usually DefaultTemplate.11.1.xaml or TfvcTemplate.12.xaml with XML editor, not the designer). Look for mtbwa:MSBuild on Run MSBuild for Project activity. Remove the OutDir attribute, save and check-in. This will force MSBuild to use the default OutDir for each project.

TFS 2010 Working Folders Setup in a Build

I have a folder structure setup for my code like so:
MyCodeFolder
-SolutionFileOne.sln
-ProjectFolder1
-ProjectFolder2
-ProjectFolder3
-SolutionFileTwo.sln
-ProjectFolderA
-ProjectFolderB
-ProjectFolderC
-ProjectFolderCommon
Solution one contains projects 1,2,3 and Common and Solution two contains project A, B ,C and Common.
When I come to create my TFS Builds I am getting a problem. If I just add MyCodeFolder in the working folder set up then both builds will succeed but then check-ins against project 2 will kick off a build of solution two and vice versa.
If I map only the folders the solution needs the build fails, which I am guessing is down to the fact I haven't included a mapping to the folder where the solution file is (the MyCodeFolder).
Is there a way I can solve this issue without altering my file structure?
The continuous integration trigger in TFS builds will queue a new build any time an item within that build's workspace is altered. Workspace mappings can only contain folders - you cannot include \ exclude (aka "cloak") individual files within folders.
What you can do is setup your build workspace to use the entire /MyCodeFolder folder. Then, in the build for SolutionFileOne.sln you can cloak ProjectFolderA, ProjectFolderB, and ProjectFolderC. In the build for SolutionFileTwo.sln you can cloak ProjectFolder1, ProjectFolder2, and ProjectFolder3.
This is only a partial solution. Both builds will still get kicked off when someone changes either solution file, or when anything in the ProjectFolderCommon folder is changed. Since you can't cloak the solution files themselves there's no way to avoid both builds getting kicked off on a solution file check-in without changing the structure of your files.

Team Foundation Build Property for Build Folder

Using TFS 2010 I need to build a solution that depends on a couple of other solutions held in different team projects. I'm editing my build definition and I create a list of "Projects to Build'. When it comes to build the parent solution I get an error because it's unable to reference assemblies created by the other solutions. So I go back to edit build definition and add /p:ReferencePath="c:\builds\3\referencedproject\binaries\" to the "MSBuild Arguments" Build process parameters.
Problem is, I don't want to hard code the c:\build\3. I guess there may be a $() property I can use in its place - can anyone please advise?
The other problem I have is that the 'Main' project and the two other projects that it references live at the same level in the source code. As far as I can tell, I have to set the source control folder to be the level above this - which happens to be the root. This means that TFS Build does a get of all the projects on the root - which includes dozens of projects that are not required for my build. It's not a critical issue since it makes no attempt to compile these non-related projects but it does increase the time for the build cycle to complete. Is this only way to avoid this to "group" the projects that are required for my build into a different TFS source folder?
For the references issue there are a few options. The most common one taking an explicit dependency on a specific version by checking in the binary to TFS.
For example, if you have Team Project A that has a dependency on Team Project B, I would assume they are setup as separate projects because they evolve differently, probably have different teams working on them, and have different release cycles. The common approach to managing this dependency is to checkin B.dll into Team Project A (usually in a lib folder specifically for this purpose), then use a file reference from within Project A's solution/projects to the dll in the lib folder.
This approach lets the Project A team explicitly choose which version of B.dll they wish to depend on, and make an explicit decision to adopt newer versions of B.dll on their own timetable.
For the other question of how to have a build definition download only select source code paths, you can specify multiple lines in the Workspace mapping screen when setting up a build definition. For example you could have the following:
$\ProjectA -> $(SourceDir)\ProjectA
$\ProjectB -> $(SourceDir)\ProjectB
This would download Project A + B but not C.
I'll start with problem 2 as this should be easiest to solve.
You have 2 options both involve changing the workspace mapping of your Build Definition.
You don't have to map at the folder "above", you can map individual folders so if your source looks like this.
$/TP/SolutionA
$/TP/Folder1/SolutionB
$/TP/Folder1/SolutionC
$/TP/Folder2/SolutionD
and you only want to include SolutionA and SolutionC in your build, you could set the workspace up as follows.
This will get just the code you need and preserve the relative paths between them.
Another option is to use cloaking, you map the "Root" folder and then cloak any folders you want the build to ignore.
Both of these methods will restrict the amount of source being downloaded when the build runs, and also prevent "continuous" builds from starting when checkins occur in the folders that haven't been mapped / Cloaked.
Problem number 1.
As Dylan suggests, probably the best thing to do is to use Binary References between solutions. Especially solutions in seperate team projects.
Check out my answer to this question for a full description.

TFS 2010 mapping dependent files for builds

I am pretty new to TFS and Build configuration tasks so forgive me if this problem has a simple answer.
I have a team project that is sort of a common library(CL) that contains dlls and apis that I commonly use throughout my projects. All my other projects reference files directly from the mapped folder for the CL on my dev machine.
I am trying to set up a build definition for Project A(Build server is on a different machine). I want always ensure that the CL is the latest before each build so is it possible to have the build definition pull the latest files first? The only other alternative is to start including the CL in of every project directly.
I tried adding a working folder for the CL, but it does not seem to get the files before it attempts to build project A. And then after when I try to rebuild after the failure, I receive a error saying that the CL working folder "is already mapped in workspace".
Instead of mapping in the sources, why not build the common library, deploy it to a common location, and have all the projects that use it reference it at the common location?
In addition to simply making more sense (it should be common binary, not common source), this greatly improves Continuous Integration builds. If several builds map the same source into their workspace, then when the common source is changed, all of those CI builds will be kicked off.

Resources