How to access another project's VS macro $(TargetFileName)? - c++

In Visual Studio 2019 I have two C++ projects contained in the same Solution: ProjectA and ProjectB.
How to define a C/C++ Preprocessor Definition in ProjectB ( let's call it: THE_OTHER_FILE_NAME ), which is equal to the string returned by the VS macro $(TargetFileName) in the ProjectA ?
NOTE: Hardcoding paths in the C/C++ source files is outside the scope of this question.

To access another project's VS macro $(TargetFileName) create the following XML file:
<Project>
<PropertyGroup>
<TargetFileName_Global>__UNDEFINED__</TargetFileName_Global>
<TargetFileName_Global Condition="Exists('$(SolutionDir)TargetFileName.vsmacro')">"$([System.IO.File]::ReadAllText('$(SolutionDir)TargetFileName.vsmacro').trim())"</TargetFileName_Global>
</PropertyGroup>
</Project>
...and name it Directory.Build.props and place it into your Solution Directory (where your *.sln file resides).
Next, in Solution Explorer right-click on the ProjectA's Properties --> Configuration Properties --> Build Events --> Pre-Build Event --> Command Line and set it to:
set /P "_VSdmy=$(TargetFileName.Replace('"','').trim())" <nul> "$(SolutionDir)TargetFileName.vsmacro" ||(call,)
Next, in Solution Explorer right-click on the ProjectB's Properties --> Configuration Properties --> C/C++ --> Preprocessor --> Preprocessor Definitions and add the following code there:
THE_OTHER_FILE_NAME=$(TargetFileName_Global);
Restart Visual Studio.
Now, you can use the THE_OTHER_FILE_NAME preprocessor macro in in ProjectB's *.h, *.c and *.cpp source files at will. This macro will be defined as a string of the ProjectA's target file name.
Note, that the THE_OTHER_FILE_NAME preprocessor macro in ProjectB will have meaningful contents only after you build the ProjectA. Before that happens, this macro will be defined as __UNDEFINED__. After building ProjectA you may have to refresh the Intellisense and the syntax highlighting of this macro in your source files by performing Rescan --> Rescan Solution from the context menu. Forgetting to rescan the solution this way, affects only the Intellisense display - it does not affect the building of any of the projects.
It is possible to do this with any other macro in Visual Studio and with multiple macros in multiple projects as well.
However, this method of passing variables between projects will not work with MsBuild versions earlier than v15.0 (included in Visual Studio starting from version v2017), because older versions ignore the Directory.Build.props file. See the "Updates" section, in this article.
This method will also not work when the MsBuild property ImportDirectoryBuildTargets is set to false.
P.S.
It is also possible to instantly pass a value of an MSBuild variable between projects using the Windows Registry (even through volatile registry keys), however it is not possible to pass it so through an environment variable set by the set command, because environment variables set in this manner do not survive the termination of the process that had set them. ...and each project is built by a separate MsBuild process. The <SetEnv... task has the ability to permanently set an environment variable in the User Profile or the Local Machine through the <SetEnv Target=... attribute, and environment variables set in this manner survive even the reboot, but they are not visible to existing processes (i.e. already running VS) - only to newly spawned processes. Environment variables set by the <SetEnv... task without the Target=... attribute, do not survive the termination of the process that had set them, just like the set command.

You can include file witch you need example
my second project name is p2
path in same folder repo
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
#include "../p2/Header.h"
int main(){
print();
system("PAUSE");
}
header file code
#pragma once
#include <stdio.h>
void print() {
printf("Hello\n");
}
And you can cheek this question

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.

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).

Choosing which main function to use in Visual C++ 2010

I'm porting a C++ application from Unix and the original developer created several files with main() functions, then use Makefile to choose which main() to use.
How do choose which file contains the main() function in Visual C++ 2010?
Currently, when I compile I get a linker error due to duplicate main() symbols.
The only thing I can think of is macro conditional.
Any other ideas?
Multiple main functions mean that the original code does not create a single executable, but rather a set of them. You should figure out what parts belong to each one of the executables (read the Makefile) and then create different projects inside the solution one for each one of the executables (do the same for the libs). Then you can use the IDE to select which executable you want to compile/run.
in the Configuration Properties for each source file (right-click in Solution Explorer) you can select 'Excluded From Build'. As this is a per-configuration setting, you can add some configurations and mutually exclude the files with main(). For instance for configuration 'MainA' you include maina.cpp and exclude mainb.cpp and mainc.cpp, for 'MainB' include mainb.cpp and exclude maina.cpp and mainc.cpp, etc.
Another option would be to have only one main() and select the appropriate source using arguments or a configuration file. Or, maybe the best solution, create one project for each main file and put the common parts in a static or shared library.

How do I setup visual studio to register some #defines globally?

What I mean is, in each of my source files I have to insert #define NOGDI to stop windows.h from including GDI defines (since it's BITMAP define conflicts with mine).
e.g.
#define NOGDI
#include <windows.h>
Unfortunately, I have to do this in every seperate source file which includes windows.h, which I do not want to do.
I am using Visual Studio 2005, is there any way I can set it to #define something globally? (i.e. in all of the source files).
Project Settings -> C/C++ -> Preprocessor -> Preprocessor definitions
Here you can define symbols that are applied globally to all source code in your project.
I had set up the needed define for whole project, as described, in
Project Settings -> C/C++ -> Preprocessor -> Preprocessor definitions
But nevertheless this didn't work!
Eventually it turned out that problem was in checked NoInherit checkbox,
"Inherit from parent or project defaults"
In defines' line of Preprocessor Definitions Dialog it's seen as:
WIN32;_DEBUG;_WINDOWS;_MBCS;$(NoInherit)
Checked the thing back and the define finally recognized.
For VS2015 I edited the .vcxproj file and added a section such as this:
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>MY_VARIABLE=SOMETHING</PreprocessorDefinitions>

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.