Jenkins and MSBuild and Copy Artifacts Plugin and proper usage for multiple projects - msbuild

My problem boils down to this base case: our solution has two projects, A and B, which project C then includes into its build process.
When someone pushes to project A or B, Jenkins builds the project using MSBuild, archives the artifact, and then kicks off a build of C.
When C begins, it has four "Copy Artifacts" tasks that need to run: first, it copies the artifacts from A into .\A\obj\Release\, then it copies the same artifacts into .\A\bin\Release. Then it repeats for project B. Then it builds itself.
That's right: for each project C relies on, Copy Artifacts has to be run twice, or else MSBuild detects that something is out of date and the whole thing is built from scratch.
Is there an easier way to do this? Can I pass a parameter to MSBuild (or configure the .csproj) that says "only build this project, assume the other project binaries are up-to-date, regardless of the timestamp"? Is there a better plugin that will take care of this for me?
This is really annoying (and confusing) in our real-world case where we've got almost 20 different projects, with layered dependencies between them.

You can pass BuildProjectReferences=false into MSBuild to tell it to skip auto-building references and just build the project indicated.

Related

In cmake, what is a "project"?

This question is about the project command and, by extension, what the concept of a project means in cmake. I genuinely don't understand what a project is, and how it differs from a target (which I do understand, I think).
I had a look at the cmake documentation for the project command, and it says that the project command does this:
Set a name, version, and enable languages for the entire project.
It should go without saying that using the word project to define project is less than helpful.
Nowhere on the page does it seem to explain what a project actually is (it goes through some of the things the command does, but doesn't say whether that list is exclusive or not). The cmake.org examples take us through a basic build setup, and while it uses the project keyword it also doesn't explain what it does or means, at least not as far as I can tell.
What is a project? And what does the project command do?
A project logically groups a number of targets (that is, libraries, executables and custom build steps) into a self-contained collection that can be built on its own.
In practice that means, if you have a project command in a CMakeLists.txt, you should be able to run CMake from that file and the generator should produce something that is buildable. In most codebases, you will only have a single project per build.
Note however that you may nest multiple projects. A top-level project may include a subdirectory which is in turn another self-contained project. In this case, the project command introduces additional scoping for certain values. For example, the PROJECT_BINARY_DIR variable will always point to the root binary directory of the current project. Compare this with CMAKE_BINARY_DIR, which always points to the binary directory of the top-level project. Also note that certain generators may generate additional files for projects. For example, the Visual Studio generators will create a .sln solution file for each subproject.
Use sub-projects if your codebase is very complex and you need users to be able to build certain components in isolation. This gives you a very powerful mechanism for structuring the build system. Due to the increased coding and maintenance overhead required to make the several sub-projects truly self-contained, I would advise to only go down that road if you have a real use case for it. Splitting the codebase into different targets should always be the preferred mechanism for structuring the build, while sub-projects should be reserved for those rare cases where you really need to make a subset of targets self-contained.

MSBuild - Project Dependencies Build Order Anomaly

We have an MSBuild .proj file that is used to build and run lots of projects. That have file references to one another. Due to the fact that it is file references, we maintain the list of Project Dependencies on the solution, so that MSBuild is able to identify the order to execute projects in.
We had an issue recently, where our US development team added a new reference to one project, but didn't update the dependencies list. This builds fine for them locally, and on the server. However for the UK team, the build consistently failed for all developers.
I'm trying to understand why this was the case. The only thing I can think of is that our Culture causes the build order to be slightly different when two projects are essentially ranked at the same level. i.e. If Project A and B are perceived to have the same dependencies, then the order the two build in is arbitrarily determined, and this might be different in the UK culture vs the US culture.
That said, my machine (it broke for me) has the Region Format set the English US. And Location UK.
Does this sound feasible? or is there a better explanation for this?
Changing the culture will not fix the issue where you're making a file reference on a components output rather than a project reference to the project that will build the assembly.
Solution files do map dependencies and would help MsBuild determine build order. When MsBuild processes a solution it will first convert it in memory to MsBuild xml format, then it will determine project order by listing the dependencies, then determine if a project needs to be rebuilt by comparing the last update time of the input files to the output files.
When you have a project reference within a project (in a project, open the References folder, remove references to output assemblies and instead reference the project itself). This will modify the project file replacing Reference item groups with ProjectReference item groups. This allows MsBuild to make this determination on a project level and resolves the issue of having to manually configure the project build order.

Gated Checkins in TFS2010

I wish to utilize the new gated check-in function of TFS 2010.
I have about 10 solutions, that all share as a dependency a proprietary shared-code library.
My structure is:
TeamProj/SharedCode
TeamProj/Proj1
TeamProj/Proj2
TeamProj/Proj3
........
The question I have is, how can I set-off an integration of ALL projects that have the SharedCode project as a dependency?
It's possible someone can make breaking changes, and not be aware of it until one of the other projects is opened/built manually.
I want to only trigger a big integration build when check-ins are made against the SharedCode folder.
The problem is, if I map the source-paths required to actually run the builds for the other projects, check-ins are picked-up automatically against all THOSE projects too.
How can I have a gated-checkin controlled folder that is independent to the source actually required to run a build?
Cheers,
Dave
If I understand right, you want to create a Build Definition as gated checkin that builds
TeamProj/Proj1, TeamProj/Proj2, TeamProj/Proj3 when any source file in TeamProj/SharedCode is changed?
In this case, one solution that comes to my mind is the following:
Create the build definition with only source folder TeamProj/SharedCode.
Change the build template to do a TFS GET for the other folders
Change the build template to build all the three solutions Proj{1,2,3}, not the SharedCode solution.
Is this what you want?

Versioning CommonAssemblyInfo.cs and MSBuild

So I have a CommonAssemblyInfo.cs linked into all the projects in my solution and is dynamically generated by my rake/albacore scripts which is not checked into source control.
I also have a CommonAssemblyInfo.cs.local for use when there is no ruby available, mainly to be used by devs.
Is it possible to have a msbuild task or something that runs before any of the other project compilation that will copy CommonAssemblyInfo.cs.local to CommonAssemblyInfo.cs before trying to compile my solution? I hate having to have a command you have to just know about and type in order to open and buidl the solution in Visual Studio.
UPDATE
So I ended up using a batch file as a solution wide pre-build event as described here: Solution-wide pre-build event?, it checks to see if CommonAssemblyInfo.cs exists and if not copies CommonAssemblyInfo.cs.local to CommonAssemblyInfo.cs just using a simple batch file.
This is the solution I ended up with.
I have each project in the solution link to a CommonAssemblyInfo.cs which is automagically generated for me by my build scripts (rake + albacore).
Since I cannot check CommonAssemblyInfo.cs into source control, I create a CommonAssemblyInfo.cs.local.
Simple solution: create go.bat which copies CommonAssemblyInfo.cs.local to CommonAssemblyInfo.cs that devs must run the first time they check out the project before opening the solution in VS.
For purely political reasons, if I did this people would have had hissy fits about me doing "nonstandard" things. Complex solution follows:
I created a project in the solution called PreBuild which every project in the solution depends on. This forces the build order to be such that this project is built first. This project contains a pre-build event which calls the following batch file:
echo verifying CommonVersionInfo.cs exists
cd
IF NOT EXIST ..\..\..\CommonAssemblyInfo.cs COPY ..\..\..\CommonAssemblyInfo.cs.local ..\..\..\CommonAssemblyInfo.cs
So now any developers who choose to keep their heads in the sand may checkout the project and blissfully open it up in VS unaware that any build scripts exist at all.
Are you talking about compilation in the VS IDE, or compilation through team build? If you are talking about team build, then you can use the "AfterGet" event as a place to use the standard "copy" msbuild task. If you are talking about the VS IDE, then you can still use the "copy" msbuild task.

Compiling and deploying assemblies that are used as references for other projects

Okay so here is my situation:
Project A is in solution A, lets call it's output a.dll.
Project B is in solution B, lets call it's output b.exe.
Project B references a.dll
Both solutions are under source code control in different repositories.
My question is: how can i assure that Project A's output gets redirected to project B's "External references" folder, overriding the previous version of a.dll, regardless of what the local developers path structure looks like, is there a way to do this? alternatively could solution A, invoke the build of solution B and then copy it's output locally?
To be brief, automating builds accross solutions without a 'common directory structure' is possible through the use of:
commandline parameters
environment variables
I would encourage you however to consider the "Convention over Configuration" mantra and think up a convention about the relative positions of solutions A and B.
Furthermore it's possible to build projects and solutions using the MSBuild task. The binaries can be copied to your "External references" folder using the Copy task.