Solution level preprocessor definitions in Visual Studio - c++

I have a large solution (100 projects) and a lot of them rely on a preprocessor definition (NEWGUI) in a header file (shared.h) to switch between two valid states of code (old gui and new gui).
I'm trying to add a compile guard around this macro
#ifndef OLDGUI
#define NEWGUI
#endif
so that we don't have to comment out or delete that line in shared.h to build the old gui, which slows down incremental builds. Then, I'm hoping to find a way to set OLDGUI outside cf the configuration. With CMake we could do this with cmake .. -DOLD_GUI
I'm doing the building in an MSBuild task in azure pipelines.
My first attempt to get OLDGUI set on the solution was use the -p flag to set the preprocessor definition, but I realized that that overrides all existing preprocessor definitions.
My second attempt was to create a new configuration that just overrode the project that has the shared.h and add a preprocessor definition there, but that doesn't affect all the other projects that depend on shared.h, and the build ends up producing a chimera of old gui and new gui.
I'm not at all sure what the proper way to do this is, and I'm hoping I don't have to manually add configurations to 100 projects to add OLDGUI to each one individually. With MSBuild this looks increasingly cumbersome. So my question is: how can I do this? Initial thoughts:
Is there some way to use something like -p:PreprocessorDefinitions=OLDGUI to add to existing preprocessor definitions at compile time?
Is there some way to add a global property page to all the projects just under a single configuration so that I can define OLDGUI there?
Is there some way to add a global property page to all the projects at compile time to do the same thing as (2)?

The solution was found in this answer from 2013. It's a hack, but it'll do.
https://stackoverflow.com/a/14206134/9691276
The approach I took was this:
Add $(ExternalPreprocessorDefinitions) to C++>Preprocessor in a global property page inherited by every project (this is pre-existing).
In the build pipeline, just set the environment variable ExternalPreprocessorDefinitions=OLDGUI.
Voila.

Related

Is it possible to define preprocessor directives for an Unreal project at build time?

I am looking for a way to easily define macros / preprocessor directives at project build/cook time for an Unreal Engine project.
For example, if I want a defined C++ macro MY_BUILDTIME_VAR to be 0 in certain builds, and 1 in others, without having to modify source code every time, in a similar approach to environment varibles in many tools (i.e. NODE_ENV in node.js), or to the command-line approach of i.e. g++ (see here).
I am aware it's possible to define target-wide macros in a project's target.cs with GlobalDefintions.Add("MY_TARGET_VAR=0") or module-wide macros in a module's Build.cs with PublicDefinitions.Add("MY_MODULE_VAR=0"). It helps to have all things defined in one place, but those definitions are still baked in the source file, and can't be changed at build time.
The official documentation mentions several ways of building/cooking an Unreal project with custom parameters, such as the Project Launcher tool and the RunUAT script file. Do any of them allow for build-time macro definitions?
Note: I am not using MS Visual Studio, but JetBrains Rider with .uproject only, so I can't define them in an .sln solution file.
Use an environment variable and read it in your build.cs file. Based on the environment variable set the value of your macro.
This is a handy utility method I use for this purpose:
private void AddEnvironmentVariableDefinition(string variableName, string defName, string defaultValue = "0")
{
string value = System.Environment.GetEnvironmentVariable(variableName) ?? defaultValue;
PublicDefinitions.Add(String.Format("{0}={1}", defName, value));
}

How do I conditionally compile c++ source files in Visual Studio 2019?

I need to conditionally compile C++ source files based on either environment variables or other input parameters. Is there a mechanism in VS2019 to do this?
This solution works with VS2017 but I don't know of any reason why it wouldn't also work with VS2019.
You can "import" environment variables as preprocessor definitions. In your Visual Studio project's properties go to Configuration Properties -> C/C++ -> Preprocessor. Click in the Preprocessor Definitions field, hit the down arrow at the far right and select Edit.
Here, you can add preprocessor definitions that include environment variables. Each line represents a definition with the notation [name]=[value] which defines a preprocessor definition named [name] which will be substituted by [value]. Environment variables should be wrapped in a $() to be resolved. So, for example, to import the environment variable MY_ENV_VAR you would add the definition MY_ENV_VAR=$(MY_ENV_VAR). If MY_ENV_VAR had say 5 at the time of compilation, this definition would be equivalent to having a #define MY_ENV_VAR 5 available across the project.
In your source file, you can then wrap your code with a #if/#endif guard to conditionally compile that code. Using the same example, to only compile a source file if MY_ENV_VAR is exactly 1, you would write :
#if MY_ENV_VAR == 1
// Entire source file
#endif // #if MY_ENV_VAR == 1
Note that environment variables are loaded when Visual Studio launches. You may need to restart Visual Studio if you want recent changes to the environment variables to be visible.
This can actually be accomplished directly by editing the project's .vcxproj file by adding a "Condition" attribute to the CLCompile element for the file in question.
Note that if you do add a Condition attribute then change the properties specifically for that file VS may remove the attribute (I am not sure whether VS does so or not, but it is something to keep in mind).

How to make Visual Studio ignore some lines of code when compiling for one config but does not ignore when in other configs

I have a Visual Studio project in C++ where I need to build for 2 different configs/platforms. Each build config (let's say A and B) is using a different library. There is one cpp file in my project that uses one particular function (1 line of code) that is only available in config A and not config B. This causes compilation error when compiling config B.
I have checked out the use of #ifdef but that would need some edits whenever build config is switched.
Can anyone advise an elegant way to enable config B to ignore only this line while config A compiles this as usual? Thanks!
In project properties, under C++/Preprocessor, introduce some config specific #defines - say, AY and BEE. Make sure you add them for both Debug and Release flavors.
Then use #ifdef...#endif in the source for config specific lines.
Example:
#ifdef BEE
int a = 0;
#else
int a = 1;
#endif
An alternative approach involves introducing multiple, configuration specific source files, and excluding some of them from build in one configuration, but not in the other.
In other environments, the same can be achieved by providing extra #defines via the compiler command line - -D MYSYMBOL for GCC. MSVC internally supports that, too.

Multiple main C++ files in a single project in Code::Blocks?

I do not regularly write code. There are times I write code daily for 6 months, and then do not code for up to 2 years. This approach has forced me to keep a bunch or reference code that I (and other much, much better programmers) have written. I refer to this "library" when writing code after a long period; I read it, I execute it, and that is a massive help in refreshing myself. This system has served me very well with Eclipse & Java over the past 5 years.
I am now learning C++ and am using Code::Blocks. I would like to somehow stuff a bunch of C++ files that have main methods into a single Code::Blocks project. I am willing to rewrite the code to achieve this task (if it's reasonable...)
I am not the first to look for a meaningful answer for this issue: https://stackoverflow.com/questions/35917504/how-can-i-make-multiple-programs-in-a-single-project-in-codeblocks and https://www.reddit.com/r/learnprogramming/comments/3opp5r/how_to_run_multiple_cpp_files_separately_in_same/
I do not want to change the IDE or compare it to other IDEs. What I am looking for, is the ability to execute one of hundreds of tiny programs that are in a well organized in an expandable file tree in C::B quickly and easily. If I put each C++ file with a main in it's own project I will have so many C::B projects that it will be unreasonable.
I do understand that C::B is not Eclipse and C++ is not Java, and that C::B is intended to have a single c++ file with a main function per project.
Any answers, and even very creative answers would be very appreciated! Scripts, settings, how to rewrite my code, whatever - if you have a suggestion I would love to hear it so I may consider it.
In the interest of full disclosure, currently I am keeping all my tiny programs in directories and use the O/S to drill through the directories and simply double click on the .cpp file which C::B opens. I am willing to dramatically modify my code to be able to achieve the objective.
Thanks for your time.
To compile and run a single main() file in a Code::Blocks project with multiple main() files:
In the "Projects" tab on the left, right-click on a file that you do not want to compile.
In the menu that appears, point to Options, and uncheck both Compile file and Link file.
This has to be done for all the files that you do not want to compile.
Now, when the project is built and run with F9, only the desired file will be compiled; the others will be ignored.
Note: It is not necessary to create a project in Code::Blocks to compile and run single file. To compile and run single files (without creating projects)
Just click on File -> Empty -> New file.
Save the file with .cpp extension anywhere (not in a project).
To compile and run the file, just press F9 or Build -> Build and run
However, such files (without projects) cannot be debugged. The most appropriate thing would be to just have a project with multiple main() files, as explained in the early part of this answer.
I've learned Java before, and am starting to learn C++ now.
When using Code::Blocks as my primary C++ IDE, I met the same problem as you. Although I found nothing useful on the Internet, I managed to figure it out on my own. Here is my solution.
In your Management panel, find your current project and right click, choose Close Project. (We won't use project to manage our code for this purpose.)
Still in the Management panel, find the Files tab, navigate to your working directory, right click on it and choose Make Root.
And we are done!
When you want to add a new code file, right click on your folder and choose New file..., enter your file name with the extension of .cpp. Then you can just use your C::B as before. Without the limit of project, C::B will just compile your current C++ file and run it on its own. Keyboard shortcuts F9 and the Run and Build button still works.
The only disadvantage is that you can see .exe and .o files in your file list, which is a little untidy. I'm still trying to find how to hide them in the list.
Hope this will help you.
How about using the precompiler? You can surround each main with:
#ifdef EXECUTE_EXAMPLE_1
int main() { return 0; } // example of one of the "mains" in one cpp
#endif
#ifdef EXECUTE_EXAMPLE_2
int main() { return 0; } // another "main" in an other cpp
#endif
#ifdef EXECUTE_EXAMPLE_3
int main() { return 0; } // yet another "main" somewhere else
#endif
And creating a header, included by all "mains" where you can define one to run:
#ifndef _EXECUTION_HEADER_H_
#define _EXECUTION_HEADER_H_
// Uncomment one and only one
#define EXECUTE_EXAMPLE_1
//#define EXECUTE_EXAMPLE_2
//#define EXECUTE_EXAMPLE_3
#endif // _EXECUTION_HEADER_H_
This could be a quick and dirty "build system" for your usecase.
I think this is what they were trying to accomplish.
No, you can't have two main files in the same Project, but you can have a lot of smaller project programs saved to a workspace which allows you to run and test them each individually.
https://www.youtube.com/watch?v=cHGIIp3rGO8

One source with multiple objects

One source with multiple objects
I am using MSVS 2010 and I have a C++ source-file which must compile into 2 object-files.
The diiference between those compilations is a "#define UNICODE" for one of them but not for the other.
I can't (and don't want to) use templates for a this.
Currently ,I use 3 source files for this in my project.
The actual source is excluded from build ,while the other 2 are wrappers around it.
Like this :
file = wrap-UNICODE.cpp
#ifndef UNICODE
#define UNICODE
#endif
#include "actual-source.cpp"
// eof
file = wrap-ANSI.cpp
#ifdef UNICODE
#undef UNICODE
#endif
#include "actual-source.cpp"
// eof
When using makefiles i can easily avoid the use of wrapper soucrces ,using different output
switches.
My question is ,I would like to know if (and how) i can do this directly in a MSVS project.
If i correctly understand what you want to do, this is possible.
I have MS Visual Studio 2005 Standard Edition; here is how i can do this (you might have to adjust this if you have a different version, or possibly it might even not work in your version; i hope your computer doesn't explode :) ).
The first step requires manual editing of the project file. Open the project file (it is called stuff.vcproj on my machine) and replicate the lines that mention your file:
<File
RelativePath=".\actual-source.cpp"
>
</File>
<File
RelativePath=".\actual-source.cpp"
>
</File>
Then, load the project into MSVS. Go to the Solution Explorer (Ctrl+Alt+L on my machine); the project will show two files with identical name. Open the Property Pages of each one (Alt+F7 on my machine) and add any differences you want (e.g. Preprocessor Definitions).
You must also set different names for object files: choose Output Files, Object File Name in the same window (Property Pages), and add different names (e.g. actual-source-unicode; MSVS will add the .obj extension when compiling). If you don't do that, the two obj-files will have the same name, and one will overwrite the other.
AFAIK you can create multiple builds in your solution. Just go in the configuration manager of the solution (should be accessible from contextual menu on the solution).
In this way you can also avoid to have two versions of your file. It is sufficient to set the define options differently in the two configurations.
Visual Studio defines _UNICODE for you if you intend to build unicode apps.
Why don't you simply use different configurations for your two builds (as Luca Martini mentions) and then use Batch Build? You can then compare the compiled outputs any way you want.