Protobuf use option GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - c#

I'm trying to generate a .cs file from a proto file, however the generated file has code that my compiler does not support. I'm not able to upgrade compiler thus I've researched this option, though I'm not sure on how to transform my proto file using this option:
GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
Details of the option can be found in this link.

Try either adding DefineConstants XML node to .csproj:
<PropertyGroup>
<DefineConstants>GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE</DefineConstants>
</PropertyGroup>
Or passing it as parameter to build: /p:DefineConstants="GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE"

Related

VS2017 Directory.Build.props doesn't load for whole solution

OK here is my problem I have 2 library and 2 project that include their .csproj (1 for Dev, 1 for Client Delivery).
I need a Defined constant to set accessible most of my class when we are with the Dev purpose (internal -> public).
I used a Directory.Build.props in my dev project directory that defined a variable and my Libraries .csproj define a constant if this variable exists.
<PropertyGroup Condition ="$(ActiveIHMMode)=='true'">
<DefineConstants>$(DefineConstants);DEV_IHM_MODE</DefineConstants>
</PropertyGroup>
I can see everything work well for my dev proj but it doesn't for my Libraries (they don't see my .props variable)
I assume there is a simple reason for it, it's because of dependencies compile order.
My directory Hierarchie is the following :
LibA
LibB
ProjectDelivery
ProjectDev
My LibA is compiled first and doesn't find any Directory.Build.props because my file is in my ProjectDev Directory, but my ProjectDev as the last element to compile finds it, but it's too late for my Lib.
First time using .props and I can't see a way to resolve it. Thanks for your future help.
First of all, to clarify a possible confusion inferred from your title, automatically importing Directory.Build.props is not a Visual Studio 2017 feature, but a MSBuild 15 feature (which is included with VS2019).
With my nitpicking out of the way, let's get technical:
The problem is not your build order. The reason Directory.Build.props is only picked up in your ProjectDev project, is because MSBuild looks in the directory of the .csproj for a file called Directory.Build.props and imports it if it finds it. If it is not found, the file is searched in the parent directory. And it keeps looking for the Directory.Build.props in the parent directory until it reaches the root, or it actually finds that file and then stops, so it only automatically imports the first Directory.Build.props found.
Your project structure, as described above, looks like this:
/LibA/
/LibA/LibA.csproj
/LibB/
/LibB/LibB.csproj
/ProjectDelivery/
/ProjectDelivery/ProjectDelivery.csproj
/ProjectDev/
/ProjectDev/ProjectDev.csproj
/ProjectDev/Directory.Build.props
Only ProjectDev gets the Directory.Build.props automatically imported; none of the other projects have a Directory.Build.props neither in their directory nor in any of their parent directories.
To fix your issue you can either move the Directory.Build.props one folder up, so that it gets automatically imported by all of your projects,
or you may import the Directory.Build.props manually by adding an Import element to your .csproj:
<Project>
<Import Project="..\ProjectDev\Directory.Build.props" />
</Project>
You can read up on more details about Directory.Build.props in the documentation.

Is there a way to override attributes from AssemblyInfo.cs (e.g. AssemblyVersionAttribute)?

I'm using dotnet core. This is for a CI process, not local builds. I'd like to allow devs to create AssemblyInfo.cs files for things like title etc but I'd like my build process to have control over the assembly's version.
Currently I'm using the "dotnet build ... /p:Version=1.2.3.4" command, but as soon as an AssemblyInfo.cs file is present this version number is superseded, even if the AssemblyInfo.cs doesn't specify any version properties.
The only way I can control the version from the CLI is to remove the AssemblyInfo.cs file. Is there any way of doing this without resorting to manually altering the AssemblyInfo.cs file before build?
The tooling generates a custom .cs file containing assembly attributes. The compiler only allows each attribute to be defined just one. Usually you'd turn off the automatic assembly info generation completely, but the SDK enables you to control the generation of each attribute individually.
So if you edit the csproj file to contain these property group (inside the <Project> element):
<PropertyGroup>
<!-- true is the default here -->
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
</PropertyGroup>
These properties won't be auto-generated during compilation and you can define them in a custom property. The complete list is available in the dotnet/sdk repo.

Conditional compilation symbols not being defined for non asp.net project

I have a C# Library Project. I have defined a Conditional Compilation Symbol: SHOULDWORK
But the problem is that this symbol is NOT being defined. I have no idea why.
This is not an asp.net project. I am using VS 2013. I have used Preprocessor Definitions extensively in c++ so it is nothing new to me. But I just can't figure out what the problem is.
I tried rebuilding, restarting VS but to no avail.
I tried using the SHOULDWORK symbol on different source files in that same project but the symbol is not defined.
HELP!!!
Just as sidenote, the DEBUG symbol works as expected. It is defined for Debug builds and not defined for Release builds.
** EDIT
The symbol is correctly stored in the *.csproj file:
** SOLVED
The csproj had several PropertyGroup entries where DefineConstants was being defined.
I manually added the symbols I needed to define to those PropertyGroups and then it worked.
It seems the project file was edited manually in the past, which could have led to this. It will need to be cleaned up but at least for now I can move on.
If using properties panel doesn't work you can modify manually the project file.
Right-click on the file project from vs
Unload project
Right-click again
Edit project file
Now you can modify the project. Find all the propertygroup you are interested in: if you want to add the conditional compilation symbols far all compilation types, you should add the symbol in every single PropertyGroup related to compilation.
This is an example of a propertygroup for compilation:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Inside the group you'll find the tag <DefineConstants> :
Add here your constant and reload the project.
Sure, you can simply modify le prj outside vs, as a simple text file.

how to configure all C# project in a solution

I have a solution which contains a lot of C# projects, how can I change the configuration of all projects very quickly, like I want to change the output folder from bin to MyBin. I know C++ property sheet can do the similar thing but C# doesn't have property sheet.
You can use a common 'partial' project file to store common stuff.
Move all the stuff that you want to be changed simultaneously into a stand-alone .proj file, e.g. common.proj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputPath>Debug</OutputPath>
<Platform>AnyCPU</Platform>
</PropertyGroup>
</Project>
Than use msbuild import declaration to 'include' common part into every project in your solution:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="common.proj" />
</Project>
MsBuild imports work more or less in the same manner as C++ includes: before a project is built all the import directives are replaced with the content of the imported file. Now you can change your common properties just in one file - common.proj
There's one important thing to mention: VS caches included project files, so you'd have to reload all the projects after applying a change to common.proj file (so I suggest building from command-line when you actively change commom.proj)
We use this approach to manage code-analysis settings (as they are supposed to be the same across all the projects in the solution).
You have to define new Build Configuration, which can be copied from Release or from Debug or constructed all manually. After you can customize for every project it's option in regard of that custom build you just created and you done. This is done, naturally, only once. After, whenever you choose that custom build all properties chosen for every single project in solution will be set with the properties you want.
Rightclick on ALL projects in the solution, one-by-one.
Click 'unload' on each
then click "edit XXX.csproj" again on all of them
You will now have many XMLs opened as text files.
Now use the Find&Replace (control-shift-H if you use default shortcuts), and set:
Find what: OutputPath>bin\Debug</OutputPath
replace with: MyBin\Debug
Look in: All open documents
and hit Replace All.
Then do the same with bin\Release and MyBin\Release.
Then save all XMLs, then right-click on every project and choose "reload".
You can do the same in any text editor or any command-line find&replace utility like sed. If you ave any, use them instead - it will save you from rightlicking/unloading all projects.
You can also exploit the fact that CSPROJs are just MSBuild files, so you can create a 'configuration' MSBuild script that will be included each of your C# projects, and which will define extra variables like 'common output path' etc. But while this certainly works (I've did it a few times), it will most probably screw up some PropertySheets in the VS UI in the most natural way, for example, if you use this to override/setup the OutputPaths, then the VS UI wil display empty or broken output paths and trying to use the VS UI to correct/change them will in turn overwrite your smart settings that read them from common config file. Obvious, isn't it.
EDIT: here it's quickly explained: Partial .csproj Files, however, please read my comments below too, just in case.

Conditionally compiling entire namespaces - C#

I was wondering if there is a way to conditionally compile entire namespaces in C#. Or am I left with having to explicitly decorate each source file within the namespace with the preprocessor directives to exclude it? In sub-versions of my application the code in various namespace is simply not required and I would like it excluded.
Thanks in advance!
If your namespace is in a separate assembly which doesn't contain anything else you can use the Configuration Manager for your specific sub-version and untick the "Build" check box.
If you've got other classes in the assembly though they will not be built or included obviously, and then the only way would be to decorate with pre-processor declarations.
You would need to put the conditional compilation directive in each file. There is no way to mark an entire namespace as conditionally compiled.
As Michael notes in his answer, a possible solution is to break out the conditional code into a separate project (assembly), and ship that assembly only for configurations that require it; but this will depend on the nature of the conditional code.
You can do this by decorating each file, or you could do it by choosing which files to include. Both MSBuild and csc have options for including all files under a path, and MSBuild additionally has the ability to conditionally include build items based on an attribute (rather than requiring a separate csproj per configuration).
But it is probably easier to decorate the files directly ;-p
I had the same problem, and using directives in each file eventually became too much work; so I started using conditional <ItemGroup> tags in the .csproj file.
For example, if I need to exclude some files from a build, I will move these files into a new <ItemGroup> section...
<ItemGroup Condition=" '$(SlimBuild)' != 'true' ">
...
</ItemGroup>
...and call msbuild.exe with a matching property parameter.
MSBuild.exe MyApp.msbuild /p:Configuration=Release /p:SlimBuild=true
You could probably also use wildcards to include future files.
<ItemGroup>
<Compile Include=".\SomePath\*.cs" />
</ItemGroup>

Categories