We have a relatively big C++ application with lots of dependencies. On our build server running msbuild 4.0.30319, we keep getting linker errors and failures when doing incremental builds using msbuild.
After further investigating this, it does appear to be that dependency libraries are not being picked up and built prior to building the application.
The question i have is as follows:
Are there best practices for building such a C++ project with dependencies? if yes, what is the correct way to do incremental builds using MSBUILD for a C++ application built using VS2008 with a fair amount of dependencies.
Just as Thomas comment "build servers should be making full builds, not incremental builds. "
When you create a new build definition on build server by default it does a clean build for you every time. That is to say that between builds all the source from the previous build is deleted along with the compiled outputs and then the source is downloaded fresh, built and you are good to go. There is a good reason for this to be the default – it is the safest option. If your build script messes around with the files in your source directory at all (perhaps baking in a build number into the AssemblyInfo files etc) then you want to get a clean workspace to ensure that you are back to a known good state.
However, if you want to enable the incremental builds in build Server, like TFS, you can refer to the Incremental Builds in Team Foundation Server for more detail.
but i am more interested how msbuild handles build dependencies on an incremental build and if it supports it
Dependencies between projects could result in inconsistent builds. Visual Studio does respect project-to-project references and builds the reference project before the referring project. However, if several projects have a shared reference, that reference is built only once and “cached” for the next times it is referenced. Also, errors and exceptions on one build do not affect the running of other builds, which may depend on the failing build. For the more info, please refer to Managed Incremental Build.
Related
I have a solution that contains both C++ and C# projects that is built in a nightly CI build on a remote machine. The build script checks out a clean copy of the source and builds both debug and release configurations of the solution using MSBuild and runs the test suite on each configuration.
About every other build, the release configuration fails to build properly. An analysis of the build log reveals that C++ Project Q, which depends on C++ Project D, tries to link before Project D is done. This error only happens for the release configuration on this particular build machine - the debug configuration builds without error. I have a separate nightly build process that runs on a separate machine where the release configuration is built with a similar script that uses MSBuild (it just does not run the test suite), and it builds the same source revision without issue. Multiple team members build the solution without issue either from update or clean checkout with one or both configurations, always from the Visual Studio 2019 IDE, on various operating systems.
Project Q is configured with Project D as a project reference and Project D is also listed as a hard-dependency for Project Q. As I mentioned, the build script is using MSBuild.
An additional item of interest from analysis of the release and debug build logs: The build of Project D is initiated differently between the two configuration builds. It is started by its own metaproject in the release configuration (as item 60, for instance), but started earlier (as item 44, for instance), by a different project in the debug configuration. Not sure why the dependency algorithm would run with such different results in the two cases since the solution and working source being built are the same.
Any ideas or suggestions would be appreciated.
Update: Inspection of differences between the release and debug build logs reveals some interesting facts. In the failure case I did a search for ") is building" in each log - should be an indication of how many projects were built, including metaproj entries. For the failure case, debug had 282 occurrences, whereas release had 175. For the success case, debug had 280 occurrences and release had a whopping 559! A similar search for "Done Building Project" yields similar results, only off by 1 or 2. That might partly explain the differences in build order between the solutions. I also need to check for conditional build entries.
Visual Studio 2019 Reference Project Not Built Before Dependent
Project Tries To Link in Release Configuration using MSBuild
It seems that project buid order was broken and Project D built later than Project Q which need the output content of Project D, so the whole build failed.
Not sure that if you use Project Dependency(Right-click on project-->Build Dependencies-->Project Dependencies), if so, only VS IDE Build Will recognize their build order while MSBuild command line will lose the relationship about them.
Besides, I wonder if your main project under Release mode references a dependency project under Release mode. If you did these, the build will definitely go wrong.
All of these above is that I think you made some changes to your project.
You could follow these steps:
1) I suggest you could try to use Project Reference and it will add these xml node in ProjectQ.csproj file to strongly specify build relationship:
<ItemGroup>
<ProjectReference Include="..\ProjectD\ProjectD.csproj">
<Project>{26c26cdd-a5e0-40c7-b0c9-4563f969424f}</Project>
<Name>ProjectD</Name>
</ProjectReference>
</ItemGroup>
Also, check if there are any conditions that distinguish between Debug or Release mode when referring to a project like this:
<ProjectReference Include="..\ProjectD\ProjectD.csproj" Condition="'$(Configuration)'=='Debug'">
If so, please remove that condition Condition="'$(Configuration)'=='Debug'" to make sure it is the same between Debug and Release mode.
2) close VS Instance, delete .vs hidden folder under solution folder.
3) check your CI Build and cloud build server and ensure that cloud parameters are consistent with other servers. And examine any of your xxx.csproj files to check if you have any other operations which causes this bahavior.
In addition, if necessary, you can share your xxx.csproj file and the build script with us to troubleshoot it.
I have a dot-net project build with VISUAL STUDIO 2015 4.6.1 framework and I have two independent program folders in the source code which has some build errors. There are no references to these programs from the main program.
When I push the whole source code onto VSTS I get build errors. So now I need a way to exclude those two folders from the manual build for now but may need them later after they are debugged so I don't want to delete them from VSTS too.
Can someone suggest?
Use an MS Build project file. Create an MSBuild project file from scratch
And the at the build solution step in VSTS, select or type the project file path instead of the solution file.
You will have to remove it down the road though. The maintenance tasks tend to be hard and counter-intuitive whenever the code base grows quickly. Visual Studio will not warn you if you have build errors (like obsolete path) in the MS Build project file.
I've been redesigning my custom VC++ build to be compatible with the new TFS 2015 Build solution.
The issue is running msbuild. I can post perhaps a simplified version, but my solution contains two items:
1 Makefile Project designed to build all of the libraries required, and
1 .exe project.
I have a reference in the .exe project to the makefile project, so that the build of the .exe forces the build of the library if needed.
The issue we are seeing is that when we do a rebuild with msbuild of the solution, it first rebuilds the library, and then when it gets to the .exe, it cleans the library project, causing some of the rebuilt files to be deleted and then preventing the link of the .exe file because the .lib file was deleted.
Why is it cleaning the makefile project again? It seems like when it gets to the .exe project, it re-resolves the dependency, and does not know that the library project was already rebuilt.
Thanks in advance. Larry
If multiple projects are in the same folder, Visual Studio attempts to erase output folder (typically Debug or Release) when the next project will be compiled. The best solution is to put each project in the separate folder.
I didn't go through all details but the reason this happens is that when building on the command-line, rebuilding the exe project results in Clean + Build of the exe project, and the Clean target for the exe project eventually calls the CleanReferencedProjects Target which results in Clean being called on your Makefile project (and later on, Build as well).
This CleanReferencedProjects is conditional on the properties BuildingInsideVisualStudio and BuildProjectReferences, so building inside VS skips this step anyway because BuildingInsideVisualStudio is true, and it's even documented:
When building the project directly from the command-line, clean those referenced projects
that exist on disk. For IDE builds and command-line .SLN builds, the solution build manager
takes care of this.
The BuildProjectReferences property is documented as follows:
By default we will build (and if applicable, clean) all project references. But this can be used to disable that
So one possible solution is calling msbuild some.sln /t:Rebuild /p:BuildProjectReferences=False. In the case with only 2 projects this will work properly, but I cannot guarantee this will always work in more complicated situations with more inter-project dependencies.
Now one thing got me wondering: how come I've never seen this behaviour myself? The answer lies in that I don't use makefile projects often, and the C++ projects which I do use are slightly different: there, the Rebuid target is defined in terms of Clean+Build (while for a Makefile project it is a standalone, separate target). As such when the exe project calls BuildProjectReferences, it will call Clean in the C++ project, but that results in
Target "Clean" skipped. Previously built successfully.
because when the C++ project's Rebuild was called it called Clean and Build already.
So another possible solution is doing the same for the Makefile project. You say that your Rebuild has additional requirements; I don't know what they are nor why they are needed (and arguably it is wrong that Rebuild does not have the same effect as Clean + Build) but this might work anyway, for example with this in the makefile project (all the way at the end of the file):
<Target Name="Rebuild" DependsOnTargets="Clean;Build">
<!--additional requirements here perhaps?-->
</Target>
everything beaves properly and Clean/Build is called once only.
If none of these solutions apply I don't immediately see another way than removing the makefile project from the solution, and manually building it before the solution both locally and in TFS.
I have a Visual C++ solution with multiple projects. One of the projects (let's name it Project 1) depends on both x86 and x64 versions of another Project 2. It means that when doing a rebuild of Project 1, no matter which architecture is selected I want both x86 and x64 versions of Project 2 to be compiled, prior to Project 1.
Standard Project Dependency feature doesn't allow to specify dependency on multiple architectures. Is there any way to accomplish this task?
Visual C++ has a command line compiler.
You can execute it on the project you need built, or split your code into multiple slns and tell the command line to build the slns.
This dependency can be set up as a custom build step, or you could go and write a makefile that describes your project dependencies and replace your sln build with that.
You can use a Custom Build Step or Custom Build Event to call msbuild twice, once for each architecture. This is how Visual Studio builds projects, so you are effectively recursively calling the build system.
Here's more detailed information:
Understanding Custom Build Steps and Build Events
https://msdn.microsoft.com/en-us/library/e85wte0k.aspx
I'm trying to build a project with TeamCity Professional 6.5.2
I have a MVC Visual Studio 2010 project using a visual foxpro dll.
The build fails because the dll is not registered.
How can I register that dll in the build machine, as part of the build process?
Thanks!!
There are two different scenarios Rodrigo, your scenario will fall into one of these:
Assemblies which can be referenced by the project: Wherever possible, include dependent assemblies in your source control repository (the 10th Commandment), usually in a "libs" folder which is referenced by the necessary projects. This centralises all your dependencies, makes it easy for new developers to get started and solves your TeamCity build problem.
Assemblies which need GAC installation: There are times when the assembly simply has to be installed in the GAC (i.e. RightFax). Frankly, the easiest thing to do in this case is just to install the damn thing in the GAC. It's an exception and whilst some people will philosophically argue against it, alternatives can get a bit complex (i.e. automating installation as part of the build), and for money I'd rather invest the time elsewhere.
Installing assemblies on each machine (dev, build, prod) will make future updates and any continuous integration system difficult to maintain in the future.
It would be better to create a folder in your working directory (I call it "Resources") which contains a folder for each group of DLLs. Then you just reference the assembly directly from the Project each time. You get duplicate DLLs across different projects, but it keeps everything very clean and simple.
In Visual Studio 2010 you can download a little utility called NuGut which I believes helps to manage assemblies in a better way.
It is a bad idea to register all DLLs on build agent machine, sometime you can find out that you have to install Visual Studio on a build agent machine, for instance ;)
I would suggest to place such libraries along with your code base in Source Control system (I assume you are using it), and just reference lib's folder by declaring a MSBUild property like
<PropertyGroup>
<LibFolder>$(PathFromCommandLineOrJustHardCodedPath)</LibFolder>
</PropertyGroup>
And then before doing a Build/Compile just copy files from $(LibFolder) into the build $(OutputFolder) using standard MSBuild command Copy by specifying source and destination files, and thats it.
To force TeamCity to pickup Lib (dlls) files from VCS folder just add path mapping into the:
TeamCity Configuration Settings -> Edit Build Configuration -> VCS Root settings -> Client Mapping
EDIT:
In your case looks like you have integration test which depends on external COm Server which you need to launch, so you can programatically registr this DLL, for instance in TestSetup, and then do not forget to unregister it in test TearDown.
Anyway you have to just reference this DLL as
VS Project -> Add Existing Item -> Add as Link
+ set
Copy to Output Directory -> Copy if newer
How-To register COM dll: see this SO post
Finally I added a prebuild event in Visual Studio running the regsvr32 command. The dll was in a known location, so I referenced this way:
regsvr32 /s $(SolutionDir)Lib\ProjDataAccess\ProjDataAccess.dll
Agree with Troy Hunt.
For a Continuous Integration with TeamCity 8.0.2 where you need an assembly (custom made shared assembly) reference from GAC, do the following.
1. Add the assembly to the build pack (In my case its nuget package).
2. Before starting the build process (MSBuild, Visual Studio etc), register the assembly to GAC with the help of a command line build runner.
3. Continue with the build process.
By following the above steps, if you are using MSBuild, the build process can link to a valid reference from GAC, which can produce an expected build result.
In my case, where the code refers a custom component from GAC, MSBuild ignored the assembly reference and completed the build process without an exception. But the deployment with the build output failed. To overcome this situation, I've used the give steps.
Note: It is mandatory that the TeamCity agent needs to run under an elevated user account. Else the addition to GAC won't be permitted and the build process can fail.