I have a C# project that has some solution wide defines in Conditional compilation symbols, see here
I now want to unit test that code and I need to undefine some of those variables.
For Unit testing I have a xUnit project that references the solution with the defines.
Is it possible in VS2019 to disable those defines?
Edit
In my specific case I have a Unity project added to my solution. Unity has Unity-specific code that cannot be executed in unit tests such like xUnit.
In order to cope with that, I wrap Unity-specific code (like Logging via Debug.Log) into a define UNITY_2020 that is automatically defined by the Unity project-file.
Now on the unit test side I want to undefine said preprocessor UNITY_2020. As I have the source code (no DLL or nuget), I hope that there is a way to compile and run my unit tests without having troubles with Unity-specific code.
So far, putting #undef UNTIY_2020 at the top of my test files does not help.
"Disable" is not quite the correct terminology, but that's ok. It is possible to undefine symbols by using the #undef preprocessor directive. You can read about it on C# preprocessor directives.
For example, you can place an #undef at the top of a file (actually anywhere really):
#undef CSHARP_7_OR_LATER
...
#if !CSHARP7_OR_LATER
// some code that can now be tested...
#endif
Also, preprocessor symbols apply to files (technically, to a compilation unit), and just happen to be commonly defined (or not) in your .csproj. At compile-time, these and passed to the compiler. So... they are not solution-wide unless you define them for all of the projects.
If the referenced projects are referenced via assembly or NuGet references, you will not be able to affect the compiled code, because, well, it's already compiled.
If, instead, you are referencing the projects directly, or the code directly (e.g. with add or add link) you can either modify the files as I stated, or you could create a new build configuration for each project and the solution, and then define (or not) the preprocessor symbols there.
Related
I would like to build a version of an application of mine without use of some features provided by a class library but avoid deleting the actual code (the code using the feature and the corresponding using directive).
Normally the whole application is going to fail to be built as soon as I unreference the assembly but I would like the dependent code parts to be excluded from compilation process instead.
Is this possible?
You can use preprocessor directives to control this - not on the basis of your references, but on the basis of symbols:
#if USE_SOME_LIBRARY
// Code that uses the library
#endif
Then just make sure that you define USE_SOME_LIBRARY in any build configurations where you have the reference.
I hava a quite complex solution, containing 10 projects aside from Test projects.
It is a network of distributed applications & services that communicate using remoting; therefore having the proper referenced assemblies (& versions) is crucial. That's why I want the whole thing to be compiled and schrink-wrapped in ONE build.
One of the applications is a demo/analysis-tool that runs a subprocess of another - much bigger - application based on the user's input and displays the results; That way engineers have a tool to help tweak their settings for "the big computation". Obviously that subprocess is contained in another assembly, and a big part of te results presented to the engineers is generated by
#if ENABLE_TRACE_MATCHING
Trace.WriteLine("Some engineering output");
#endif
My problem is that Conditional Compilation Symbols in the project settings are limited to that project's assembly, and do not propagate over referenced assemblies.
How can I configure my build in such a way that all projects will be built without ENABLE_TRACE_MATCHING being defined, except for the one debug/analysis-app project where all referenced projects/assemblies must be compiled with ENABLE_TRACE_MATCHING being defined
I also cannot replace #if ENABLE_TRACE_MATCHING by #if DEBUG, since that would enable a whole lot of different output our engineers wouldn't know how to handle.
Thanks in advance.
PS: If you think my code smells, then I agree. Additionally: It's mostly not my code ;)
You need to learn more about Microsoft Build, which is an out-of-the-box Microsoft .NET tool present in any framework's installation.
Using MSBuild you can define these "symbols" (properties) and a batch of commands (targets).
That's you can create a MSBuild script that imports default Visual Studio targets from all projects in your solution, and declare in the script these properties ("symbols").
In fact, the property to set such symbols already exists: "DefineConstants".
So, since you have it, you can have that MSBuild script that provides that property value, re-declaring it there, so, ALL MSBuild targets will be knowing about these symbols.
EDIT:
Check this other question too:
msbuild, defining Conditional Compilation Symbols
I have two projects A and B. A depends on B. I would like the following to happen
If B define a conditional compilation symbol, I would like A also define it automatically. Can I achieve this?
No, basically. Compilation symbols are applied on a per-project basis in the project settings, and on a per-file basis depending on #define pragmas. There's no way of making the project you're compiling against determine your compilation symbols - they vanish after compilation, effectively.
It would be simplest to create appropriate solution-wide configurations, and project configurations within them which define the appropriate symbols.
If you have lots of project files,
Use custom MSBuild script
Or write a "project file generator" that will create all your project files for you (they are just XML after all)
(It is a real pity you can't selet more then one project file then "multi edit" them)
I think this is a simple question so I assume I'm missing something obvious. I don't really ever use preprocessor directives but I was looking at someone's code which did and thought it was something I should be familiar with.
So I looked at the msdn example here it has the code:
#define DEBUG
// ...
#if DEBUG
Console.WriteLine("Debug version");
#endif
My two questions are:
in the example above why do they define DEBUG? I was under the impression that was set if you compile in debug v. release mode?
looking at the other example which has #define MYTEST and then writes to the console dependent on if it 'defined', but how does this differ from just using a variable? What am I missing here?
I would actually recommend using the Conditional Attribute instead of inline #if statements.
[Conditional("DEBUG")]
private void DeleteTempProcessFiles()
{
}
Not only is this cleaner and easier to read since you don't end up having #if, #else within your code. This style is less prone to errors either during normal code edits and well as logic flow errors.
Generally, the optional/conditional compilation symbols will be provided by the build script. It is pretty rare to see #define, except for very debug code (if you see what I mean).
Re using a variable; I often use such conditions to handle code that must run on different runtimes (mono, cf, silverlight, etc). A variable cannot suffice because the code cannot be compiled against the wrong platform (missing types/methods etc).
In the example presented I would probably just have used Debug.WriteLine; since this is decorated with [Conditional("DEBUG")], all calls to it are automatically removed if DEBUG is not defined at build.
in the example above why do they define DEBUG? I was under the impression that was set if you compile in debug v. release mode?
Probably because it is example code. It is meant to demonstrate how #ifdef and friends work. I wouldn't expect you to define symbols like that in source files, unless it is for a quick test.
looking at the other example which has "#define MYTEST" and then writes to the console dependent on if it 'defined', but how does this differ from just using a variable? What am I missing here?
If MYTEST is not defined at compile time, the compiler will not actually emit the code between the #if and #endif blocks. Therefore the resultant IL will be smaller.
Also, note that these are not preprocessor directives in C#.
If you use variable all your code is compiled, when you use preprocessor directives only part of code included in executable/dll.
I would like to give one example where I have used preprocessor directive in my project.
My program creates lot of intermediate files on disk. I used #DEBUG directive to delete those files only if my project is in release mode, otherwise I keep those file so that we can view those intermediate files and determine whats happening inside.
When my app is working on production server, I build project in release mode so those files are deleted after processing is complete.
#if (DEBUG==false)
deleteTempFiles()
#endif
I have some code which needs a different handling when using the Mono environment instead of the CLR - thus I have a Mono directive in some of my modules. I think this is a better example than debug
I've used it for a lot of things. Debug messages that I only want in debug builds; clean up temp files; include diagnostic functions or actions.
I have a large application that I can build through the command line. I want to specify a flag that enables me to compile it into either one of two modes, Actual or Simulated.
So the main issue is, how can I use the preprocessor to programmatically add a reference?
For example:
#if SIMULATED
include SimulatedFiles;
myFactory = new SimulatedFiles.simFactory();
#else
myFactory = new realFactory();
#endif
I don't want any simulated files to compiled into my "actual" application. Since there is no "include" directive in C#, I am stuck on how to accomplish this.
You cannot do this via a C# preprocessor statement because the language doesn't support the notion of references via preprocessor macros.
What you can do is use a msbuild file and alter the set of references added based on msbuild parameters.
nant/msbuild and dependency injection tool with xml configuration?
In C#, there is no real preprocessor, as you can read on the C# Preprocessor's documentation.
From the documentation (emphasis mine):
While the compiler does not have a separate preprocessor, the directives described in this section are processed as if there was one; these directives are used to aid in conditional compilation. Unlike C and C++ directives, you cannot use these directives to create macros.
Are the include files your own source code, or third-party assembly dlls?
If they are your own sources, then you can easily use conditional compilation to remove the "simulated" code from your release build, exactly as you have done in your example (just replace 'include' with 'using'). This is common practice with debugging classes for example.
If you don't "control" the source code for the includes, then you can still add a project reference, but if you conditionally compile all the code that uses the assembly, your applicaton won't ever attempt to access the assembly, so it doesn't need to be be present when the code is running.
(Another possiblity that seems less useful for you is to write a "dummy" version of the referenced assembly that you ship in place of the "real" one, or a proxy that calls the real third-party dll in simulated builds only. If it supplies the public classes and methods that you call, you can ship the dummy instead of the simulated assembly to your customers)