I have Visual Studio 2008 SP1, two C++/CLI projects, lets say proj1 and proj2.
proj2 is dependent on proj1, but in a weird way (see below).
In Project Dependencies I specify that proj2 depends on proj1.
Also proj2 references include proj1.
Then I want proj1 to be a friend to proj2,
so, as MSDN page on "Friend Assemblies" says, I write somewhere in proj2 this code:
#using "proj1.dll" as_friend.
Compiling says that proj1.dll already referenced, and that I should remove project reference from proj2 project settings (thus removing /FU flag).
Here comes the bug(?):
If I remove proj1 reference from proj2, but still specify in solution Project Dependencies that proj2 depends on proj1,
everything compiles ok in VS2008. But MSBUILD parses project references, creates new temporary project for the proj2,
ADDS /FU:proj1.dll and BUILD FAILS!
Question 1: is there a way to disable this MSBuild behavior?
Then, if I remove dependency in Project Dependencies, MSBuild builds fine, but Visual Studio tries to compile proj1 and proj2 in parallel, and fails,
because proj2 is much smaller and compiles first... Setting max parallel builds option in Project and Solutions/Build and Run helps,
but I have to do it on every developer machine, I can't save this setting in the solution, this makes build slower etc...
Question 2: is there a way to make "Project Dependencies" a conditional option? I want it on for VS2008 and of for MSBuild...
As the OP has already found out, this is actually a bug. A bug was filed by the OP and acknowledged by Microsoft. It appears to affect VS2005, VS2008 and VS2010 (targeting VS2008).
The workaround that I used was a dummy intermediate project to "buffer" the references between the 2 dependent projects.
If ProjA depends on ProjB and ProjB depends on ProjA then I am surprised you can build it at all! This sort of circular build dependency normally kills clean builds. You often get away with it on dev machines where an old ProjA is still lying around when you build ProjB and vise-vera. But on a clean machine (build server), then this kind of dependency often breaks things.
Depending what the dependencies are, it might be simplest to move the common dependencies to a new assembly ProjC, that has no dependencioes of its own, but which both ProjA and ProjB depend on. This means you can then build ProjC, then ProjA and ProjB in any order afterwards. This kind of refactoring is often simplest when you are only depending on interfaces from ProjC rather than concrete classes.
Not sure this entirely answers your question, but it might give you an alternative way to fixing it.
Colin
Related
I am using Windows installer xml and now my project moves to Team Services.
However, my Paths wont work anymore and I need to update my setup.
On the local build machine I used this hardlink: C:\Projects\Solution\Project\bin\Release\Assembly.dll
My Question: What is the best way to build 4 projects and then run a 5th project, which uses the assemblies in the bin/release directory?
Add a reference to the project and then use $(var.Project.TargetPath) instead of the hardlink (or $(var.Project.TargetDir)Assembly.dll). The references will add dependencies on those projects to the wixproj which means they all must be build before the wixproj so all the binaries will exist. All the projects should be included in the same solution as the wixproj.
Here's a resource for all the automatically defined compile time variables you can use http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html
Alternatively if you can't do it this way you can define the variables in the <DefineConstants> of the wixproj. It would be something like "ProjectDir=$(MSBuildThisFileDirectory)..\Project\bin\Release\" and then in your wix component where you are using the SourceDir hardlink you would use SourceDir=$(var.ProjectDir)Assembly.dll
All of this stuff is taking advantage of MSBuild. It takes a long time to wrap your head around how MSBuild works but it is definitely worth it if you will be using Visual Studio to build all your projects.
I have a project file that should build another solution. I tried using the MSBuild task for this, like this:
<MSBuild Projects="MySolution.sln" Properties="Configuration=$(Configuration)"/>
I tried a lot of variants, like supplying hardcoded configuration, target Rebuild and so on. Building reports an error when I pass a wrong solution name, non-existing configuration or target and so on, so it definitely loads the solution and the project files. It exits relatively fast though and produces no output. According to documentation and examples, this should work though. I also tried passing an ItemGroup for the project, including project-specific properties as suggested by examples or in MSBuild - How to build a .NET solution file (in an XML task script) from pre-written command line commands , but that does not work either. It runs without error but no output.
When passing a list of project files instead (or a single project file), it builds correctly, but the problem is that dependencies between the projects are not properly resolved. At the end, I have to supply all project files in the solution and add them to the list, which is what I want to avoid.
So, why does solution building not work, even though it should? What is wrong here?
Is this a .net project? If so you probably need to pass in a platform as well as a configuration.
<MSBuild
Projects="MySolution.sln"
Targets="build"
Properties="Configuration=$(Configuration);Platform=$(Platform)" />
If the project just contains web sites and libraries then the platform should be Any CPU if your solution just contains executables then x86 or x64 or if it's a mixture of different types of platform then you can use mixed platforms
To check what are available open the solution in Visual Studio, right click on the solution in solution explorer and select "Configuration Manager" you'll then have a drop down for "Active Solution Platforms"
E.g. how should I build release and debug version at the same time? I guess the answer make use of cache variables and some kind of "collection" of them.
Is it common way to get configuration params from cache params, isn'it ? If the answer is yes, how should I use several "collections" of them in a best way ?
Thanks a lot!
You don't specify the platform you are talking about. The Makefiles based generators will only build one configuration at a time, and the normal way to build several configurations is to use separate build trees, e.g. one for 64-bit Linux on Intel, one for 32-bit Windows, etc. Most CMake projects advise out of source builds, and assuming you wrote your CMakeLists files correctly you could have ~/src/YourProject, and ~/build/YourProject-Release, ~/build/YourProject-Debug.
This is the advised way to do it, assuming your source tree does not have any CMakeCache.txt etc in it. You can then run cmake -DCMAKE_BUILD_TYPE:STRING=Debug ~/src/YourProject in the debug directory, and similar for the release. This has the advantage that you can point dependent projects at the appropriate configuration.
The Boost CMake project has also explored building all configurations in the same build tree using library name mangling to differentiate. This may be worth looking at if you must build all configurations in the same build tree.
(for fellow googlers)
Be careful of not confusing build types and build configurations.
If you really mean "build types" such as debug and release and want to build them at the same time, then Cmake FAQ gives an answer : How can I build multiple modes without switching
Basically it involves using several out-of-source builds.
Ok, so I've got a somewhat complicated problem with my build environment that I'm trying to deal with.
I have a solution file that contains multiple C# projects which is built by a NAnt script calling MSBuild - passing MSBuild the name of the solution file and a path to copy the binaries to. This is because I want my automated build environment (CruiseControl.Net) to create a folder named after the revision of each build - this way I can easily go back to previous binaries for any reason.
So idealy I have a folder layout like this
c:\build\nightly\rev1
c:\build\nightly\rev2
c:\build\nightly\rev3
...
c:\build\nightly\rev10
etc.
The problem that's arisen is I recently added the latest version of the Unity IoC container to my project, checking it directly out of MS's online SVN repository. What's happening is I have a Silverlight 3 project that references the Silverlight version of Unity but I also have other projects (namely my Unit testing project) that reference the standard (non-Silverlight) version of Unity.
So what happens is since MSBuild is dumping everything into one single folder the Silverlight version of the Unity assembly is overwriting the non-Silverlight version because they have the exact same assembly file name.
Then when CruistControl runs my unit tests they fail because they don't have the proper dependencies available anymore (they try to load the Silverlight specific Unity assembly which obviously doesn't work).
So what I want to do is:
keep my desired output directory
structure (folder\revision)
I don't want to have to manually edit
every single proj file I have as this
is error prone when adding new
projects to the solution
Idealy I would like MSBuild to put everything into a folder structure similar to this:
nightly\revision1\project1
nightly\revision1\project2
nightly\revision1\project3
...
nightly\revision2\project1
nightly\revision2\project2
nightly\revision2\project3
etc
I can't modify the Unity project to give it a different file name because it comes from another SVN repository I cannot commit changes to. I found a similar question posted here and the suggested solution was to use a "master" MSBuild file that used a custom task to extract all the project file names out of the solution then loop over each one building them. I tried that but it doesn't build them in the order of their dependencies, so it fails for my project.
Help?
Firstly I would always have the build server delete the old working copy and check out a fresh copy to avoid any problems with stale artifacts from the previous build.
Next I would have nant or msbuild build the solutions as before with the artifacts from each build going to their local working output folders.
After that I'd move the artifacts from their working paths to their output paths, this shouldn't require digging through the project files since you can just tell msbuild/nant to copy working\project1\bin\release\**\*.* to artifacts\project1\.
The script that does this should ideally be stored along with the source with the main file, e.g. build.nant or build.proj in top level of the trunk.
For third party libraries I would simple include the DLLs directory in your repository. Nothing worse than writing some code and having a third party dependency break your build because of changes on their end.
Simply document the versions of the libraries you are using, and if you must update them, you'll have a better sense of what breaks the build before you even check it in.
Also, doesn't CC.Net automatically handle the providing of releases based on revision? I'm using TeamCity and it keeps a copy of the artifacts of every build.
I highly recommend reading JP Boodhoo's Automating Builds with NAnt blog series. That's been my starting point and have made lots of changes for my own taste. I also highly recommend checking out the builds of many open sources projects for examples. I've learned a lot from the builds of the Castle/Nhibernate/Rhino-Tools stack.
Often times a developer on my team will create a new Visual Studio project and reference a DLL somewhere on their local machine (e.g., C:\mydlls\homersimpson\test.dll). Then, when I get the project from the source control repository, I cannot build the project because I do not have the referenced dll in the exact same location on my machine.
What is the best practice for storing and referencing shared libraries?
I typically create a lib folder in my project, where I put the referenced dll's. Then I point the reference to the dll in the lib folder. This way, every developer can build the project after retrieving from source control.
If it's a project that was built in house, you could also add that project to your solution.
If the assembly is not in the GAC, create a directory called dependencies and add all assemblies there. The folder and the assemblies are added to source control. The rule is that given any project in source control, all that is required to build is to do a checkout and build the project (or run some tool that is also checked into the project).
If you add a folder to the solution and add the assemblies to the solution folder, this also provides a visual cue to the devs that indicates what external dependencies are present... all dependencies are in that directory. Relative paths ensure that Visual Studio can locate the references without a problem.
For large solutions, with 20+ projects, this makes life much easier!
Best practice I would expect would have Your SC repository include and enforce the relative locations of referenced objects for you (usually via a shared path), so you aren't dealing with this issue directly. The original developer should check in this information.
If you check in the actual DLLs into source control, then you can reference them by relative path and all developers will automatically get any dependencies when they next update the project.
Adding a DLL reference by full path would be a developer error just as adding a source file by full path would be an error.
Rule of thumb: If the project isn't a part of the solution, reference released dlls from a source controlled /binshare or /lib directory that is under your solution's source control tree. All external dependencies should have versioned DLLs that go in this /binshare directory.
I understand what your co-worker is doing in regards to convenience. However, that developer's approach is diametrically opposed to proper configuration/build management.
Example: If you use the MS Data Application Block as a dependency in your application, you should reference a properly released binary, instead of getting latest from MS's dev source trunk.
I think this approach is quite the opposite of what I would consider best practice. I think it would be a much better approach to keep the third party binaries out of the source repository and reference them through something like a Maven repository in your build process. Putting the dlls in the source repository unnecessarily bloats the contents of the repository and results in gets of projects taking considerably longer then necessary. It also makes the independent management of the third party binaries' versions obfuscated by not referencing the version by name but rather implied by referencing the dll of a particular version stored in the projects lib folder.
Why not set up a private NuGet-feed? This way, there is only a single copy of a dependency (the NuGet repository) and multiple projects can reference it. Multiple versions of the dependency can coexist, and each project can reference a different version, if necessary. Also, TFS Build can restore the packages at build time.
Configuring VS: https://www.visualstudio.com/en-us/docs/package/nuget/consume