When a solution has 20+ projects, which method should be used to:
minimize build order issues?
provided the fastest run time?
minimize issues when code is changing frequenty?
Reference
<Reference Include="Project2"><HintPath>..\..\Project2\bin\$(Configuration)\Project2.dll</HintPath></Reference>
ProjectReference
<ProjectReference Include="..\..\Project2\Project2.csproj"><Name>Project2</Name></ProjectReference>
First of all, here's the difference between adding a Reference and adding a Project Reference:
References reference an already built .dll and therefore there is
no way this .dll will be rebuilt.
Project References reference another project, which can be rebuilt
(if it has changes).
Now to your question specifically:
By referencing already built .dlls (read: using Reference) you
will not experience any build order issues (since they won't be
built again).
Apart from that, it shouldn't make any difference at runtime
whether you use References or Project References - however,
there will be differences in compile-time as References will not
be built.
For frequently changing code, you should use Project References
since they will be rebuild if changes occurred; already built .dlls
won't. You will have to manually rebuild and add a reference to them
again every time they change.
Related
We have a large, multi-project solution, that has a number of build configurations and output targets.
For various reasons, mainly to do with excessive references or additional files, I'd like to ensure that some of these projects are not updated to ever reference some of the other projects.
For example:
- Foundation.Common.Entities (Simple models, interfaces, etc.)
- Foundation.Common (References Entities, has additional logic)
- Foundation.XConnect.CustomTabs (More models, references Foundation.Common.Entities,
must not reference Foundation.Common)
- Project.Web (References all of the above)
I'd like to stop people referencing Foundation.Common in the CustomTabs project, as it has a number of additional references that must not be deployed to some of the targets that the CustomTabs DLL is deployed to.
As CustomTabs is also referenced further down the chain, I can't just create a separate solution for the CustomTabs tree.
I'm not adverse to dropping StyleCop or similar in, but would prefer a slightly more lightweight solution initially.
A simple target does the trick; add this into the CustomTabs project file:
<Target Name="BeforeBuild">
<Error Condition="'%(ProjectReference.Name)' == 'Foundation.Common'"
Text="Please don't reference Foundation.Common"/>
</Target>
This loops over all project references checking if the name matches and raises an error if so. The same principle works for Reference.Identity as well.
For example this happened to me when I added configuration (IConfigurationRoot) in the Startup.cs file, to be able to access appsettings.json file which has a connection string.
So the first time I write IConfigurationRoot it is obviously marked as not recognized, so I put my mouse over it and expand the Visual Studio suggestions from the light bulb, which are:
using Microsoft.Extension.Configuration:
Microsoft.Extension.Configuration.IConfigurationRoot
Generate Type
Add package Microsoft.Extension.Configuration.Abstractions 1.1.0
So if I pick "using Microsoft.Extensions.Configuration",a using directive is added at the top of my file and VS recognices IConfigurationRoot, everything works fine. But checking the References in my project, this library was not added to it:
No Reference Added
So if instead of picking the using directive, I pick "Add package Microsoft.Extensions.Configuration.Abstractions 1.1.0", Visual Studio also adds the using directive but additionally it adds a new Reference:
Reference Added
I'm not understanding why this happens, why adding the using directive (first suggestion) works fine, is it because the reference is already contained in another library?, if so, why should I add the package individually?. Is it better to add it individually?, what happens if I do, am I adding a reference to the same library twice?
Thanks in advance.
...is it because the reference is already contained in another library?
Yes, look under the Microsoft.Extensions.Configuration.FileExtensions or Microsoft.Extensions.Configuration.Json and you eventually get to the Abstractions package.
If so, why should I add the package individually?
There is no need. The light bulb tooling might not quite up to speed with the whole package dependency stuff.
Is it better to add it individually?
Not really, but if your ever removed some of those base package then adding it individually from Nuget would ensure that it would remain.
What happens if I do, am I adding a reference to the same library twice?
In an indirect way, yes, but there's no harm. The Dependency tree view drills down into each layer of dependencies. You will see lots of "duplicates" if start expanding those nodes.
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.
I had to change the xmltree.cs file and now i need to move the dll of the compiled code into another project to update the project. There are a ton of dlls in the presentation bin. I wanted to know if anyone would know which specific ones would need to be moved.
Thanks,
Corey
Assuming that you have created your project from the Umbraco source, you will need to get a clean set of the source (same version) and compile it without your change. Then make your change and recompile. The affected DLLs will have changed their modified dates, and these will be the ones that are dependent on your code change.
You should never base your project directly on the source, especially if you don't know what you're doing. If you need to modify the source, keep it separate (and under source control) and build your project on the compiled version.
I have a project where I have added a compile symbol (MYSYMBOL) in the project properties. When building from VS it works just fine and the application acts accordingly.
Other projects has various symbols defined this way.
When building from MSBUILD, MYSYBOL is for some strange reason ignored and the application acts as if it was never set.
I tried adding /p:"DefineConstants=MYSYMBOL" to the msbuild call, but then the build fails as it seems to replace the other symbols of each project with this one alone, so one assembly e.g. requires MYSYMBOL + OTHERSYMBOL but now only gets MYSYMBOL.
This is strange since it actually does use OTHERSYMBOL for those projects that have it, when building via msbuild.
Does anyone have a clue what could be causing MYSYMBOL on the project properties not to be used when building via msbuild?
Turned out that the build script has stated a set of compiler symbols on its own, overwriting the ones in the separate project settings which in turn caused this issue.
As far as I understand, you can't add one or more compiler symbols since anything you state replaced the symbols of the projects.
Ended up having to pass every symbol every project in the entire solution uses.
Too bad :(
You will want to add a new symbol to the list of DefineConstants (as opposed to overriding the entire list of DefineConstants). This will do what you want:
<PropertyGroup>
<DefineConstants>MYSYMBOL;$(DefineConstants)</DefineConstants>
</PropertyGroup>