TFS 2013 build - class library build output path doesn't mean anything? - c#

I'm hoping someone can help me with this. I have a solution that consists of two Web sites and two class libraries. One of the class libraries is a shared library for use within many of our projects so its output is stored a shared location (D:\Applications\SharedLibraries\Bus_logic) so we can reference the dll from there. We have this directory structure on our local machines and build server.
This works perfectly fine on my local machine. Building the solution locally pushes the updated dll to the local D:\Applications\SharedLibraries\Bus_logic folder. Our old CCNet builds would do the very same on the build server.
However, with TFS the output path of a class library doesn't seem to matter. I have a CI build for the solution and the class libraries never get outputted to that path. They're just grouped together in the drop folder.
Is there any easy way to make sure the build copies those dlls to their rightful locations, or do I have to create a custom build template for every one of my solutions that compiles shared libraries so that the dlls get copied to the right directory?

I've been doing a but with TFS builds recently so I hope the following helps.
Before you do any of the following I recommend you create a new build definition and new build template (via Edit Build Definition -> Process -> New Template -> Copy from existing) to test this works.
TFS provides a custom path for the OutDir argument to MSBuild, the variable passed for this is called outputDirectory. The step where this is set is deep within the default build template here, open it and navigate you way to Run On Agent -> Try Compile, Test and Associate -> Sequence -> Compile, Test and Associate -> Try Compile and Test -> Compile and Test -> For Each Configuration -> Compile and Test -> Initialize Variables, once there you'll find a task called Initialize OutputDirectory which by default is set to the 'BinariesDirectory/Platform/Configuration' folder. You could change this to your own custom logic.
It might be an easier way be to set the OurDir argument to nothing on the Run MSBuild task as I assume this will then use the projects default paths. This can be found here in the template, Run On Agent -> Try Compile, Test and Associate -> Sequence -> Compile, Test and Associate -> Try Compile and Test -> Compile and Test -> For Each Configuration -> Compile and Test -> If BuildSettings.HasProjectsToBuild -> For Each Project -> Try to Compile the Project -> Compile the Project.
There is probably a more elegant way via tinkering with the solution or project files but I am not aware of that just yet.

There are really two good ways to make this light up.
Check the dll's in - you can create a folder in source with the files that you depend on checked in. Then add a mapping in the build to get them to a well known location.
You can have the DLL's packaged as a NuGet package and take a dependency on that.
1 is cheap and cheerful and proan ro error, but not as much as your current solution. #2 is the right way to do things. NuGet was designed to solve these sorts of issues.

Related

Multiple Projects in .Net Solution - Combine Build Artifacts from all projects

I have 2 solutions that contain test related code. One is for UI automation and another for API. I combined both solutions and I am able to build and run tests from both but:
Each one of those contains similar configs that I would like to combine under one project. No need to have the same thing in both obviously. I removed configs from project2 and created references from Proj1 to Proj2. I build Project1 and artifacts are generated fine from Project1, but it does not contain all artifacts from Proj2.
Previously, when I build projects separately, It would generate say 60 files in the build folder, but now its much less.
Question:
If I decide to add project #3 and add configs to it. How can I build project 3 and combine artifacts from all of them in bin folder of project #3.
I hope I'm making this clear.
Essentially I want to be able to build 1 project which will trigger builds for remaining 2 and pull all artifacts to together.
As Ziggler suggests, you can change the build output folder to combine all artifacts from all of them in bin folder of project #3.
And you can do this by passing $(OutputPath) property in command-line. It seems that you're using something like TeamCity, Azure Devops or what in your environment.
For these tools, we can add msbuild parameter like: /p:OutputPath="Path to project3's bin folder" if you're using msbuild to build whole solution(msbuild xx.sln). See Global Property.
And about the build order, you can add project dependency to control the build order. Msbuild will recognize project dependency and project reference and then choose the right order automatically. Hope it helps :)

Add reference to local folder

I'm adding my dll file to my reference and set Copy local to true
Everything is OK and after I build application, my dll added to output folder
Now my question is how do Ι change the local path?
For example:
my application path is C:\myproject, I want to put dll into C:\myproject\libs
How can I set dll path to {applicatonpath}\libs NOT {applicationpath} ?
When you compile you project, visual studio will put everything that has been compiled and set to copy locally to the "output folder", which depends on your current compile configuration. If you are compiling in Debug mode then this folder will be:
c:\your_solution_path\your_project_path\bin\Debug
If you use Release mode, it will be:
c:\your_solution_path\your_project_path\bin\Release
However, sometimes we reference a lot of assemblies (DLLs if you will) and those assemblies have dependencies of their own. In order to make everything "point and click" for our convenience, we must tell visual studio how we would like it to act for a particular project build.
So, as TotPeRo said, you should go do project properties and use the functionality of Pre-build and Post-build events. As the name suggests, Pre-Build happens before the actual build, while Post-Build takes place immediately after it. Please refer these links for further information: link1 and link2.
Lets assume the following scenario:
You have one solution.
that solution holds 2 projects (let's call them Project A and Project B). Project A is the actual GUI. Project B is just a helper project, that compiles into a DLL.
Let's say, that project B is doing some heavy matrix calculations, so you also have to include some MatLab libraries. NOTE: only Project B uses these libraries.
Project A references project B so that you can use the calculated information from B and show it in gui in A.
In order to compile this, the compiler is smart enough to determine, that Project B should be compiled first. If everything checks, the project is compiled into ProjectB.dll. Then, the compiler proceeds to compile Project A. It check all the dependencies and finds out, that you have already compiled Project B (which is a dependency for Project A) and that it can continue. Everything is then copied to the output folder (bin/Debug or bin/release) and should be in working order.
However, during runtime, something goes wrong and the application crashes. You find out, that Project B does not have the appropriate library to work with (namely MatLab libraries). And then you conclude, that MatLab should be included in the bin/debug (or bin/release) folder at compile-time. Since the MatLab library is a dependency library for Project B but not for Project A, it does not get copied and hence the exception. You can mitigate this behavior with the aforementioned Pre and Post-Build events. You can tell the Visual Studio that you want it to manually copy MatLab.dll to the output folder when it is doing a compile. This comes super handy when you come into situations like these. Build events can also trigger a lot of other things so be sure to check it out. I'm using this a lot and it's a time saver at least.
in the Visual Studio you can go Project > [project name] Properties > Reference Path
change the path/create folder or else you want
First make folder lib new project source code then use relative address
in post-build event on visual studio go to properties in your project and add this:
copy "c:\pathtolibrary\bin\debug\namelibrary.dll" "$(SolutionDir)\bin\Debug\libs"

Visual Studio : How to manage code shared between projects

This has probably been posted before, but I'm not sure what search terms to look for!
Quick explanation.
I have code that is shared between a few projects. This code is still work-in-progress itself. The issue is that whenever I need to update this code for whatever, I don't want to have to do it 3 times, this will become a nightmare.
Is there a way to add it to a project, without copying it into the project folder?
i.e. I want the shared class to be linked into my 3 projects as
C:\code repository\sharedclass.cs NOT \eachproject\bin\sharedclass.cs
Do I have to create it as it's own library project? It would be much better if the compiler could compile it as 'external' code.
Cheers.
As others have said, you can simply right-click on your solution in the solution explorer, select Add > Existing Project, and browse to the common project's .csproj file, and it will be included in the solution from its original location.
There are two problems with this however, which may or may not be an issue, depending on the size of your team:
The common project will be included in each solution with a relative path to the solution file (i.e.: ...\CommonProject\Common.csproj). This means all developers have to have the same working file structure or they will get errors when they try to open the main project.
In the scenario that the common project is referenced by multiple projects (say two - A and B) and a developer working on project A has to make changes to the common project as part of their task, there is no way for that developer to know if the changes they have made will break project B without them actually checking out project B and compiling it. As more and more projects reference the common project, the risk of this happening increases to the point where it becomes unmanageable.
Again, as others have said, there is no 'correct' way to do this. However, the approach I have taken is as follows:
Use continuous integration such as Cruise Control to manage the building of the projects and put the common project as a standalone project on the server.
Create a directory under your source control to house built common DLLs. Have this directory checked out on your build machine and whenever the common project builds, it copies the output DLL into the DLL folder and commits these changes to source control.
Use environment variables on all developers' machines and the build server to control the location of the common DLL folder and reference the DLLs using that variable rather than the hard-coded path. (i.e.: rather than C:\Source\MyCommonProjectDLLS\Common.dll, use $(MyCommonLocation)\Common.dll with the variable 'MyCommonLocation' set to C:\Source\MyCommonProjectDLLS)
For any project which references the common DLL, set up a CI trigger on the build server for that project to watch the common DLL folder. Whenever changes are committed to it, the build server should then build all consuming projects.
This immediately lets you know if you are committing breaking changes for any other project. The only drawback is that, in this model, consuming projects are forced to take updates to the common DLL as soon as they are made. An alternative is to version the Common DLL from the source control revision when it is built, and place each version in its own sub directory under the common DLL folder. So you would end up with:
Common DLLs
-1.0.0.1234
-1.0.0.1235
-1.0.0.1236
And so on. The advantage of this is that each project can then choose when to take updates to the common DLL by simply referencing the new version of the code. However, it cuts both ways as this can mean that some projects are left with older versions of the common code for longer than they should, which can increase the work involved when the time comes to finally bring in those changes.
Yes.
You can add a project from anywhere on your hard drive to a solution. So put the shared code into a class library and add that to your three projects.
Microsoft has been supporting an open source project which comes built into VS now, its called NuGet, you can output your shared project as a nuget file and consume it in your other projects.
It will actually deploy all the files you specify in the package upon build.
This is how .Net supports dependencies now. You will notice that even things like EF come through NuGet packages. You can even host it for free on places like MyGet.org I use this and it works quite well.
http://nuget.org/
I use git submodules to achieve this.
Create a new git repository for each module (project) that you want to share between solutions. I usually also include unit tests for that project in a separate project but in the same git repository.
Add a submodule to the git repository of the solution that will use the shared code. Adding a submodule creates a link to a specific commit of an external repository. When the code in the submodule is updated you will be able to pull the updates to your parent solution, which is essentially the same as updating the reference to the submodule commit. I find that the process is easier to visualise using an app like SourceTree.
Adding the submodule and pulling the latest commit will create a copy of the shared project inside the parent solution folder. Import the project into the parent Visual Studio solution by right-clicking on the solution and selecting "Add existing project".
Add a reference to the shared project in the other projects that will be using it by right-clicking on the project and selecting "Add Reference" and finding the shared project in the "Solution" tab.
Now that the shared project is included in the solution you will be able to push and pull changes to the submodule and these changes will automatically be incorporated into the solution. You will also be able to see the changes in other git repositories that reference the submodule.
Yes, put the code which need to be shared in a separate class library project, build it and reference the DLL created from this build into your other projects.
It is better to extract common part into a separate project library and add reference of this project to all the solutions/dependent projects.
Otherwise you can Add code/file/item as Link.

Visual Studio 2010 -- selected Solution Configuration affecting Batch Build output

Summary
I'm having a very strange behavior with Visual Studio 2010, and I'm not sure if it is a bug or if there is some twisted logic to why it is behaving in this way.
The executive summary is that when I use Batch Build->Select All->Rebuild to build all the configurations for all my projects, VS2010 produces differing output binaries depending on what is the currently selected Solution Configuration. This is really annoying because some of the project outputs fail to run correctly (giving a "[Project name] has stopped working" error dialog on startup) depending on which Solution configuration was selected during the batch build.
More details
I have a Solution with 3 C# projects in it (1 .dll outputting project, referenced by the other 2 .exe outputting projects). Of the .exe outputting projects, Project A has Release and Debug Project configurations. Project B has a Debug, Release-x86, and Release-x64 configuration because it needs some different post-build scripts run to give it the correct version 3rd party libraries.
I have 4 Solution Configurations: Debug, Release, Release-x86, and Release-x64. Release-x86 and -x64 are set to build only Project B. Release and Debug build Project A and the shared dll project.
If I select the Debug Solution configuration from the current configuration drop-down box, and the Batch Build all, then when I try to run the Release configuration of Project A it fails to run. If I select any other Solution configuration from the drop down, and then Batch Build all, then it runs successfully. When I diff the produced .exe file, I can see that it is different between these two cases.
Question
Is this some known intended behavior of VS2010? If so, can someone give a hint as to why this problem may be occurring and how I can fix it? Is this a bug in VS2010?
Follow-Up Clue? [Edit]
Could this have something to do with how VS2010 handles "Project references"? As I mentioned, both .exe projects reference the dll Project, call it Project D. I added that reference (to Project A, say) by selecting Add Reference -> Project -> Project D. But of course the different configurations of Project A want to use different configurations versions of Project D. When I examine the Project A -> Project D reference under Properties, I see a Path field that is not editable. Depending on which Solution configuration is selected, I either see ...\Project D\bin\Release\Project D.dll or ``...\Project D\bin\Debug\Project D.dll, and I don't see any way to control this so I guess VS2010 is trying to be smart about picking the details of Project configurations. But even more strangely, if I select Batch Build -> Select All -> Clean to remove all compiled files, than these reference paths change to ...\obj\... instead of ...\bin\... when I inspect them, and I can't seem to change them back except by removing and re-adding the project reference.
Follow-Up 2 [Edit2]
I lied a little bit earlier, I actually have 2 .dll projects (Projects D and E, say) where D references E through a project reference.
I'm pretty sure something broken or bizarre with Project References in VS2010 is the culprit, and think I have found the root cause of the selected-Solution-Configuration-dependent behavior, with the following steps
1) I Batch Build -> Select All -> Clean, to remove all previously compiled binaries.
2) I select a Debug Solution Configuration from the drop-down.
3) I Batch Build -> Select Only Project A Release -> Rebuild.
By watching the Output window, I see that VS2010 knows that Project A depends on D, and D depends on E, so it attempts to build them in reverse order. It successfully builds the Release configuration of project E. But then it tries and fails to build the Release configuration of project D, because it complains about missing the missing Debug version of E dll file. And likewise A fails to build because of the absence of the Debug version of D.
So it seems that the selection Solution Configuration is overriding the configuration of referenced projects in Project to Project references.
Is that supposed to be the case???
After some further searching, I've found that this is a known bug in VS2010, marked as "Wont Fix" by Microsoft. Batch Build in VS2010 is simply broken. If you think that's as dumb as I do, go ahead and express yourself to them.
https://connect.microsoft.com/VisualStudio/feedback/details/556158/batch-build-links-to-wrong-referenced-projects

Binary dependencies in Visual Studio projects

I've a native binary dependency for my c# solution which comes in Debug and Release variants, and I'm trying to figure out how to best organize this such that
(1) It ends up in the build output, and is found when running unit tests
(2) It lives under the checkout directory in source control
(3) The correct variant (debug/release) is copied for each build configuration
I'm looking at
Solution
Libs
MyLibrary
Debug/x86/foo.dll
Release/x86/foo.dll
MyProject
src/com/acme/MyApplication.cs
MyProject references MyLibrary
and I'd like the build folders to look like:
Solution/MyProject/bin/Debug/
x86/foo.dll <-- copied from MyLibrary/Debug
MyApplication.exe
Solution/MyProject/bin/Release/
x86/foo.dll <-- copied from MyLibrary/Release
MyApplication.exe
I'm trying to do this without a custom msbuild file - everything would ideally build from the solution and project files.
Anyone have ideas how to do this? (or suggestions how to reorganize the sources to achieve something similar?)
I have a few libraries like this, so splitting them all into two (Library_Debug, Library_Release) isn't really an option.
any help appreciated ;)
You can add pre- and post- build steps to your solution. I can't remember off the top of my head the mechanics of determining if you're doing a debug or release build, but you should be able to set up the dependencies so they point to a temp directory, and copy in the appropriate set of dlls.

Categories