How can build independent dll's that depend on the same source? - c#

I am building a few different C# libraries that both depend on a single C# file we'll call Dep.cs, and these dll's need to be used together in a Unity project. I'd like to set up these projects in the following way:
The C# libraries can be built independently of one another using Visual Studio
C# libraries (i.e. dll's) can be imported into a Unity project without conflicting symbols
The C# library projects (i.e. the source code for each library via git submodule for example) can be imported into a Unity project without conflicting sources.
I've solved (1) by including Dep.cs in each library project that requires it, though this causes issue with (2). And I've solved (3) by putting the dependency in a folder like Dependencies~ so that Unity ignores the file (this way no duplicate classes are found).
I'm having trouble solving (2) however. I thought I'd be able to add Dep.cs as reference in the VS solution but This doesn't seem to work. I've heard of Assembly References but I am not sure if they do what I need.

You can use "Add File as Link" from Visual Studio "Add Existing File" screen. It also works well with git submodule, just place Dep.cs anywhere in a parent folder or in the solution's root directory.
To get the same result you can also directly edit the .csproj file and add a compile instruction:
<ItemGroup>
<Compile Include="..\..\Path\To\YourFile.cs" Link="YourFile.cs" />
</ItemGroup>
This method solves all the issues you mentioned.

To solve my problem I decided to modify the external scripts to be internal this way both dll's can compile with that source and not conflict with one another. The rest of the setup in my question remained the same so this solved (2) for me without compromising (1) and (3).

Related

Library proxy with intelisense

I have quite odd scenario. I have external library like one below:
Now I need to use it in other solution but in quite unnatural way (but it needs to be like that :/). So it is included in such fashion:
As you noticed we have here new project named ExternalLib (just like the one we've created before in different solution). It contains only .dll of that library and we reference this project in Consumer (Add reference -> Project -> ExternalLib). Also I had to add one postbuild action for this 'proxy' ExternalLib copy /Y "$(ProjectDir)/ExternalLib.dll" "$(TargetDir)". It builds without errors. Only errors are displayed by Visual Studio text editor (as it is visible on screenshot above).
My question: is there any way to make visual know about that 'real' contents of that library? (I also do not own .pdb files) I know it is really odd way including external library but it is some constraint I can't avoid :/

Getting a list of all dependencies from a .NET Standard project's csproj

Ever since I've been using the (relatively) new .NET Standard Library project type in Visual Studio, I've been having some problems getting a complete set of DLL files that are required by my project.
The problem is usually limited to 3rd-party libraries which I reference as NuGet packages. I've noticed that these don't get copied to the output folder of my project when I build it. This didn't use to be the case in classic project types.
While I can appreciate the de-cluttering effect that this change has brought for .NET Standard projects, I'm now faced with a problem. I sometimes absolutely need to be able to get the entire list of all files that my project depends on!
I have several different cases, where I might require this list for one reason or another, but the one I believe is most crucial for me, is when I want to gather these files from the csproj itself, right after it's built. In there, I have a custom MSBuild <Target> which should take all the files from the output dir and zip them together for distribution. The problem is, I'm missing all the files that come from NuGet dependencies, because they're not there!
How can I solve this in a general (i.e. not project-specific) way?
UPDATE
There's this deps.json file that contains basically all I'm after and then some. It's just a matter of extracting the relevant information and find the files in the local NuGet cache. But that would involve writing a specialized app and calling it from my target. Before I start writing one myself... Is there something like this already out there somewhere?
I followed this answer and it sort of works.
The suggested thing was to include the following into my csproj:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
My main concern is that it also outputs some other DLLs from the framework (such as System.Memory.dll and System.Buffers.dll, among others), which I didn't expect. But maybe that's a good thing. They do seem to be dependencies, just not direct ones. I'll see how it plays out.
If it turns out ok, my only wish would be that this directive was more prominently displayed in project settings (as a simple checkbox, maybe?) so I wouldn't have to hunt the web to find it.

Link compile-time created resources to a class library

I'm using Visual Studio Community 2017 and my projects are written in C#.
Project setup:
Let's assume I have a class library project, called (A).
And I have another project that creates an executable, called (B).
In Visual Studio (B) has a reference on (A). Library (A)'s dll gets automatically copied over to the output directory of (B).
Problem:
The class library (A) needs some additional files, that are created while the project compiles.
(So I can't just add them to visual studio as resources and set them up as "copy if newer")
Project (A) has a pre-build command set up to create these resources.
This command invokes a content processor to process a bunch of library related assets.
I want these processed asset files to be linked to my library (A).
So if another project references (A), I want these asset files to get copied over as well.
Copying the processed assets into the output directory of (A) apparently did not do the trick.
My actual question is:
How do I tell Visual Studio to also copy the compile-time created files of project (A)
into project (B)'s output directory?
I know it looks kinda stupid to answer my own question like an hour later but...
Maybe someone else might find my solution useful:
As Alexan commented on my initial question, creating a custom nuget package and hosting it locally might be a relatively easy and elegant solution. I will definetly try that out as well. I think by following this blog post I might be able to achieve this:
https://www.wiliam.com.au/wiliam-blog/creating-a-nuget-package
But, I also figured out another way, which relates to this question:
How do I “Add Existing Item” an entire directory structure in Visual Studio?
As it turns out, by manually editing the csproj file of my class library, I can define a directory to include as linked content. All the files within this directory get fetched automatically when the projects gets compiled. All the files within this directory are copied over to project (B) automatically. (My compile-time generated assets as well)
<ItemGroup>
<Content Include="$([System.IO.Directory]::GetFiles("PathToFolderToInclude","*",SearchOption.AllDirectories))">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
So, I would call this topic solved. If somebody else has another idea how to solve this problem I would like to know.

Single Visual Studio C# project, multiple DLLs versions?

We have one master project that creates a single DLL with FEATURE_1, FEATURE_2 and FEATURE_3 as three conditional compilation symbols that enable those respective features.
MyLib.dll => has FEATURE_1, FEATURE_2 and FEATURE_3 compiled in
We now wish to have the same master project spit out 3 different DLLs as follows:
MyLib.1.dll => has only FEATURE_1 compiled in
MyLib.2.dll => has only FEATURE_2 compiled in
MyLib.3.dll => has only FEATURE_3 compiled in
At present we build within VS2013 and those compile constants are defined inside the .csproj file (within the <DefineConstants> </DefineConstants> tags), which hard-codes them.
Is it possible to pass them via a command line so we can still maintain one master csproj but build the 3 different flavors in the RELEASE configuration just by changing the command line (eg: gcc's -D<buildFlag> style) ? The solution has other projects and they're designed to work with the RELEASE configuration. I'm also open to any other technique that is easy to use and maintain.
We're really trying to avoid creating pseudo-projects or affecting other projects in the solution (21 projects in the solution) - seems like an overkill/hackish for something very simple.
I haven't done anything with the command line, but to solve similar problems, I created separate projects (that define the Framework Target and any conditional compilation symbols), and then add all the project files as LINKED files. In this way, I only have to modify a single set of source files, but each project compiles into its own DLL.
To add a file to a project as a linked
Right click the project and click Add Existing Item...
Select the file (or files) you want to Add.
Instead Of clicking the Add button, click the arrow next to the Add button, and click Add as Link.
I'm not sure if this will work for your case, but it sure has saved me lots of time when developing libraries for different .NET framework versions.
Is it possible that you have a complete turnaround?
Instead of defining all features in a single library and then disable some of them, you can create individual projects for each features, and then at packaging phase merge the smaller assemblies into a single one.
Microsoft has ILMerge, while ILRepack is an open source alternative,
https://www.nuget.org/packages/ilmerge
https://www.nuget.org/packages/ILRepack/
Then you are free of conditional compilation, which is too difficult to manage, and the complexity is moved to your packaging scripts, which can be easily managed and checked into source code management.

C# - Code compiler for .NET & CF.NET

I've a same project that need to be compiled with .NET and Compact .NET Framework.
It is possible to create a C#
compiler that will compile my
project with both framework ?
Some feature aren't present in
CF.NET Framework so I created it by
myself (creating classes having
exactly the same name & options that
in .NET Framework. If I decore this
classes with an attribute like
[CF35] it's possible to parse the
project and :
Use this class when compile the
project using CF.NET
Ignore this class when compile the project using
.NET
?
Thanks for all constructive answers.
[EDIT]
I know the solution that consists to create two projects referencing the same files.
Problem is, you should every time compile both manually.
Moreover, when you add a file to one, you need to open the second and reference it too, that it's just borring to do and according that we are many people to work on the same project, I would like to do this part automatically.
Seems to be possible?
[EDIT 2]
All works fine except ... resources files !
So, to resume, I've three project :
the development project (CF.NET)
the release project (CF.NET 3.5), including all files via ""
the release project (NET 3.5), including all files via ""
As said, all works fine, but now my problem is using Resources files.
What's the method to apply to use it?
When I use the development project, Resource file is correctly retrieved
When I use the two other projects, ResourceManager throws MissingManifestResourceException
Any idea?
You'll need to create different build configurations for each and define a custom flag like USE_CF. Then wrap your custom classes with #if USE_CF and #endif so they get ignored when compiling without that flag
The basic idea would be to decorate your code with #if compiler directives for each framework version?
#if CFNET
// .net CF code
#else
// .net code
#endif
From here one you have two options:
A) 1 project file with custom build configurations
If you would like to have everything in 1 csproj file you'll need to modify it manually. Since this is a msbuild file this is more of a msbuild problem. I figure you would need to do the following things:
Use 2 platform names say "NET" and "CF" (instead of the default Any CPU or x86)
Define CF constant (From now on Edit csproj):
<PropertyGroup Condition="'$(Platform)' == 'CF'">
<DefineConstants>CF</DefineConstants>
</PropertyGroup>
Import correct build targets depending on selected platform:
<Import Condition="'$(Platform)' == 'NET'" Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Condition="'$(Platform)' == 'CF'" Project="$(MSBuildToolsPath)\<CFtargets>.targets" />
I don't know the targets file name of CF since I don't have it installed. It sould be somewhere in C:\Windows\Microsoft.NET\**.targets
B) 2 project files each containing the appropriate build configuration
As I initially pointed out, and also some commenter pointed out, the best solution is to have 2 project files, that you keep in sync. You can have the same source files in both project files.
So an idea would be (instead of copying the file list manually each time) to
think about using T4 templates, to keep the source files in sync (and have 2 solutions, so you wouldn't be prompted to reload the whole solution each time) or to
modify the two csproj files and use a wildcard compile tag like this:
<Compile Include="**/*.cs"/>
There's only one C# compiler, it emits the exact same IL for whatever platform. What's different are the reference assemblies, you have to use the CF versions for the project that targets CF, the desktop versions for the project that targets .NET. Which requires two projects. They can reference the same source code files. Adding CF-only source code files is now of course no longer a problem.
Keeping projects in sync is a feature available in VS2010. Intended for Silverlight, pointless for a CF project of course since it no longer supports it.
a better way is to create your normal project class library (.NET) and add all of your code. Then create your second class library project (.NET CF) but reference the code files from the first project (not copy, but reference). Then you end up with 2 DLL's and you don't have to deal with nasty ugly compiler directives. You get the result you want with no extra work to maintain both projects. Obvisouly you would need to be careful with what you put in the code since .NET CF is limited compared to .NET. I don't know how to add file references (shortcuts) using visual studio but I open the proj file in notepad and use relative paths to the files to include. I've used this method for .NET/.NET CF and also .NET/Silverlight
Also, have a look at Portable Library Tool CTP http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981/?localeName=ko-kr

Categories

Resources