Use Project properties/ Macros in c++ code - c++

I am trying to use the OutDir Macro from the Project properties within my c++ file to build a path.
But I can't find a way to assign the OutDir content to a variable in my code.
I tried this:
#define OUTPUT_DIR $OutDir
I can't seem to use this correctly.

You can specify pre-processor definitions in the "Project Properties->C/C++->Preprocessor->Preprocessor Definitions" list as:
OUTPUT_DIR=$(OutDir)
and then you can use that macro in your source code. You may need to textify it first. i.e.
#define TEXTIFY(x) #x
then use it as
TEXTIFY(OUTPUT_DIR)
see this answer. Although looking at this answer, it is possible that VC++ 2017 has some issues with this.
I believe you can also add the quotes into the options itself which might be a way round it.
OUTPUT_DIR="$(OutDir)"

Related

Solution level preprocessor definitions in Visual Studio

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.

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));
}

Macro that is true only when the compiler starts a build [duplicate]

This question already has an answer here:
Hide a C++ code block from Intellisense
(1 answer)
Closed 3 years ago.
Is it possible to have a macro be set to true when building but otherwise is set to false? I realize there are macros to detect build configurations (e.g. debug/release) but I am looking for a macro that is set when the compiler starts building. It's okay if the macro is very specific to a particular compiler.
The use case is to help intellisense with some complex macros by simplifying them. The autocomplete does not work with the complex macros. However the simplified macros are very slow at runtime.
This one would probably work:
#define ONLY_TRUE_AT_COMPILE_TIME true
You can set a macro in your IDE and don't use it in the build process
#ifdef IDE_MACRO
#define SIMPLE_MACROS
#else
#define COMPLEX_MACROS
#endif
In Visual Studio Code you can set
"configurations": [
{
...
"defines":[
"IDE_MACRO"
]
}
]
in
.vscode/c_cpp_properties.json
defines A list of preprocessor definitions for the IntelliSense engine
to use while parsing files. Optionally, use = to set a value, for
example VERSION=1.
This only works if compileCommands is not set
compileCommands (optional) The full path to the compile_commands.json
file for the workspace. The include paths and defines discovered in
this file will be used instead of the values set for includePath and
defines settings. If the compile commands database does not contain an
entry for the translation unit that corresponds to the file you opened
in the editor, then a warning message will appear and the extension
will use the includePath and defines settings instead.
As you can read in the quote you can also use compile_commands.json to set macros and IntelliSense will consider them.
In Eclipse CDT it's in C/C++ Build -> Build Variables. There you can set a Variable IDE_MACRO. Now Eclipse CDT uses SIMPLE_MACROS instead of COMPLEX_MACROS. In the build process the macro IDE_MACRO is not defined and the compiler uses COMPLEX_MACROS.

Documenting preprocessor options with Doxygen

I have a C++ package that allows for different behavior if the user defines different pre-processor constants. For example, a user can use /D ALLOW_WIDE_CHAR in the makefile to change the behavior to support wide characters.
I would like to document these options with Doxygen, but Doxygen complains because there is no actual #define in the code. It is up to the user to do that.
Adding the definition to the PREDEFINED list in the configuration file doesn't help.
Suggestions?
One option I found is to create an extra source file, say Doxygen.h, that is not compiled, but is added to the Doxygen file list. This file can use #define to define those pre-processor constants. It seems like there should be a better solution, though.

How to view the content of a C++ macro?

I have a macro that is dynamically generated before compilation (it's supposed to contain the build number). However I think there's some error with the way it's generated so I would like to check the content of this macro. How can I do that?
I'm using the MSVC2008 compiler.
You can use /p option and write preprocessor output to a file. Or
You can use /E option and write preprocessor output to stdout
You can set the "Preprocess to a file" option on the project or file's properties to true. That will let you see exactly what the preprocessor emits.
(It's under Configuration Properties → C/C++ → Preprocessor.)