Is there a difference between:
#if defined(_WIN32) || defined(_WIN64)
and:
#ifdef _WINDOWS_
I know that it is necessary to use defined() when there is more than 1 condition.
Yes, there is a difference. The _WIN32 and _WIN64 tokens are defined (conditionally) depending on what platform is being targeted. The former (_WIN32) will be defined for x86, x64, ARM and ARM-64 architectures; the latter (_WIN64) will be defined only for the two 64-bit architectures.
However, the _WINDOWS_ macro will always be defined if the "Windows.h" header file is included by a given source file. It is used (in that header) as a 'guard', to prevent multiple inclusions of its body. A very trimmed-down version of that header is:
/* ...
Copyright (c) Microsoft Corporation. All rights reserved.
...
Master include file for Windows applications.
--*/
#ifndef _WINDOWS_
#define _WINDOWS_
// ...
// <body of Windows.h>
// ...
#endif /* _WINDOWS_ */
Also, when using the MSVC compiler (and, possibly, some others), the _WIN32 and _WIN64 macros are predefined by the compiler (i.e. no header needs to be included for them to be defined for their relevant target platforms).
Just to add to the confusion, MSVC also adds a _WINDOWS macro (note the lack of the trailing underscore) by default, when creating new projects that target Windows (this is not formally predefined, but is one of the default, per-project "Preprocessor Definitions" in the projects' properties.
Related
Please excuse my basic question and poor programming knowledge.
I have an implementation that I need to use in many of my projects. But the included header files are different for different projects.
Say I have spi.h header file to be used in projecta.c and projectb.c. But a particular include (definitions.h) is not required in projectb.c then how do I make this include project specific?
I have seen that is done through #ifdef and #ifndef and directives. But can someone please help me understand how is it done.
Thank you
Say I have spi.h header file to be used in projecta.c and projectb.c. But a particular include (definitions.h) is not required in projectb.c then how do I make this include project specific?
Like this:
// projecta.c
#include "spi.h"
#include "definitions.h"
// projectb.c
#include "spi.h"
There's no need for ifdef directive.
You can include a certain header depending on an #ifdef like that:
#ifdef INCL_DEFINITIONS
# include "definitions.h"
#endif
The in the project where you need definitions.h you have to add -DINCL_DEFINITONS to the compiler parameters
I have seen that is done through #ifdef and #ifndef and directives.
It can be done through #ifdef and #ifndef directives or #if directives.
The key part of this is you need some way to define preprocessor macros based on what project is being built. A common way this is done is:
Each project has its own build settings.
Those build settings include options to pass to the compiler.
The compiler has options to define preprocessor symbols.
For example, with GCC and Clang, you can use -Dsymbol to cause symbol to be defined (with no replacement tokens; it is defined, but the definition is empty) or -Dsymbol=replacement to cause it to be defined with the indicated replacement.
Once you have this, there are choices about how to use it. One choice is for a symbol to be defined if a feature should be included and undefined if not. Then you would have directives such as:
#if defined FeatureX
#include "HeaderForFeatureX.h"
#endif
Another choice is for a symbol to be defined to be 1 if the feature should be included and 0 if not. Then you would have:
#if FeatureX
#include "HeaderForFeatureX.h"
#endif
Historically, some people used the first choice and some people used the second. Because of this, it is common to write your settings and code to cover both of them. When defining a symbol with a compiler option, we will both define it (satisfying the first method) and define it to be 1 (satisfying the second method), as with -DFeatureX=1. When testing it, we will test with with #if defined FeatureX because that is true if either choice is used, whereas #if FeatureX is true only if FeatureX is defined to be 1, not just defined with empty replacement tokens.
(In a #if directive, if a token that could be a preprocessor macro name is not a defined preprocessor macro name, it is replaced with 0. So, if FeatureX is not defined, #if FeatureX becomes #if 0.)
A third choice is to define a symbol to have different values according to the features chosen. For example, we could define ProductLevel to be 10, 20, or 30, and then use directives such as:
#if 10 <= ProductLevel
#include "Level10Features.h"
#if 20 <= ProductLevel
#include "Level20Features.h"
#if 30 <= ProductLevel
#include "Level30Features.h"
#endif
#endif
#endif
My current goal is to create one (or as few as possible) line of code that will switch the remainder of the active compilation unit to an unoptimized, debug configuration. My first instincts were either:
FORCE_DEBUG;
// code below here will be forced to be unoptimized and in a debug environment
or
#include "ForceDebug.h"
// code below here will be forced to be unoptimized and in a debug environment
would be ideal. In my workspace, to convert to an unoptimized debug configuration requires I change the pragma optimize level, but also #undef some macros and #define other macros.
The FORCE_DEBUG macro doesn't work because it would need to execute preprocessor directives #undef and #define which I understand are not evaluatable within a macro.
Instead I have a working version of #include "ForceDebug.h". But I want to message the developer that they have disabled optimization on a given compilation unit (so they don't check it in, or if they do check it in that it can be caught and fixed). Ideally this message includes the filename of whichever file #includes "ForceDebug.h" or the current compilation unit.
Here's an approx ForceDebug.h
#pragma once
#pragma message("DISABLING OPTIMIZATION IN" COMPILATION_UNIT_FILE)
#undef _RELEASE
#define _DEBUG
#ifdef _MSC_VER
# pragma optimize("", off)
#else
# pragma GCC optimize("O0")
#endif
So a call site would look something like Foo.cpp:
// this messages "ForceDebug.h", I want to message "Foo.cpp"
//#define COMPILATION_UNIT_FILE __FILE__
// double macro also messages "ForceDebug.h"
//#define COMPILATION_UNIT_FILE COMPILATION_UNIT_FILE2(__FILE__)
//#define COMPILATION_UNIT_FILE2(x) x
// this works but requires doing it manually, which I'm trying to avoid
#define COMPILATION_UNIT_FILE "Foo.cpp"
#include "ForceDebug.h"
// code below here will be forced to be unoptimized, debug environment
I can't use __FILE__ because that messages about ForceDebug.h, when I want it to report about Foo.cpp.
If I could evaluate __FILE__ inside Foo.cpp and pass the evaluated version into ForceDebug.h that would be acceptable, but I tried recursive macro calls and it still reported ForceDebug.h
Is there any way to get it to pass "Foo.cpp" into the include or to derive that value by some other means for either clang or Visual Studio?
I was not able to find a way to emit the current compilation unit name from an included file.
However, your proposed syntax requires the user of "ForceDebug.h" to add another directive to expose its compilation unit name to the header file. Instead, you can turn it around and allow simple inclusion that defines a macro that allows for the message to be emitted.
While, generally speaking, macros cannot be used to generate pre-processor directives, there is a syntax for pragmas for the compilers you illustrated. MSVC and GCC each have their own syntax, but conditional compilation can make the syntax appear uniform.
In your source file:
#include "ForceDebug.h"
FORCE_DEBUG;
//... rest of source
In "ForceDebug.h":
#pragma once
#ifdef _MSC_VER
#define DO_PRAGMA(X) __pragma(X)
#define NO_OPT optimize("", off)
#else
#define DO_PRAGMA2(X) _Pragma(#X)
#define DO_PRAGMA(X) DO_PRAGMA2(X)
#define NO_OPT GCC optimize("O0")
#endif
#define FORCE_DEBUG \
DO_PRAGMA(message("DISABLING OPTIMIZATION IN " __FILE__)) \
DO_PRAGMA(NO_OPT) \
struct __force_debug
#undef _RELEASE
#define _DEBUG
You could use the __FILE__ predefined macro like below:
#pragma message("DISABLING OPTIMIZATION IN " __FILE__)
Live Demo
Edit:
Since you want to report about the .cpp file I would go the other way around. That is, I would change ForceDebug.h to:
#pragma once
#undef _RELEASE
#define _DEBUG
#define OPT_OFF
^^^^^^^^^^^^^^^
#ifdef _MSC_VER
# pragma optimize("", off)
#else
# pragma GCC optimize("O0")
#endif
And then I would put the potensial message in my .cpp file:
#include "foo.h"
...
#ifdef OPT_OFF
#pragma message("DISABLING OPTIMIZATION IN " __FILE__)
#endif
All project created with MSVC have stdafx, which is precompiled headers, which I know what they are but what about targetver.h ? It includes SDKDDKVer.h, and I can't find what is that header about.
What is this for ?
targetver.h and SDKDDKVer.h are used to control what functions, constants, etc. are included into your code from the Windows headers, based on the OS that you want your program to support. I believe that targetver.h sets defaults to using the latest version of Windows unless the defines are specified elsewhere.
SDKDDKVer.h is the header file that actually defines the #defines that represent each version of Windows, IE, etc.
Line 193 of the SDKDDKVer.h (in SDK 8.1) states:
"if versions aren't already defined, default to most current"
This comment is specifically referring to the _WIN32_WINNT and NTDDI_VERSION macros.
So..
SDKDDKVer.h applies default values unless the macros have already been defined
the following code can be used to explicitly define the macros
#define _WIN32_WINNT 0x0601
#define NTDDI_VERSION 0x06010000
Interestingly enough, the SDKDDKVer.h header file has 'constant' values defined for all of the SDK versions. For example:
#define _WIN32_WINNT_WINXP 0x0501
#define _WIN32_WINNT_WIN7 0x0601
#define _WIN32_WINNT_WIN8 0x0602
One convention is to define _WIN32_WINNT and NTDDI_VERSIONin a header file called TargetVer.h, which you would reference in your pre-compiled header StdAfx.h.
#ADDTIONAL READING#
Update WINVER and _WIN32_WINNT
Using the Windows Headers
What does the Target Platform Version mean for a VS C++ project?
I am including a third party header and source file into my project.
At the top of the header there is this:
#if defined(WIN32) || defined(WIN16)
#ifndef MSDOS
#define MSDOS
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#ifndef MSDOS
#include <unistd.h>
#endif
#include "des.h"
The problem is that #if defined(WIN32) fails and the compilation fails when trying to #include unistd.h which I don't want to do.
I have third party project that works with this header file i.e. WIN32 is defined and it doesn't try to include In Visual Studio I did "Go To Definition" on "WIN32" and was taken to the following definition in WinDefs.h.
#define WIN32
I'm not sure this is where its getting WIN32 definition from, as the third party project does not appear to include "WinDefs.h".
So my problem is, how can I get WIN32 to be defined in my current new project?
Depends on your project setup. WIN32 is defined inside the windows header files, but you can pass it to the compiler as well ("-DWIN32" for gcc for example). Try it and see whether it compiles.
Visual Studio has the built-in define _WIN32. mingw-gcc has WIN32 and _WIN32 built-in so the project was likely tested using gcc. You might add
#if defined(_WIN32) && !defined(WIN32)
#define WIN32
#endif
or just add a -DWIN32 to the CFLAGS.
Check your includes. I am guessing that the third party header is included prior to the windows.h. So, in your main.cpp or equal it should be
#include <windows.h> // this will also include windefs.h
#include <thirdParty.h>
and not the other way around.
Hope that helps.
You can simply include the windows header files (windows.h) before including the third party header - as you already found out WIN32 is defined there but technicaly it could be defined anywhere (so if the third party project is not including the windows headers check if it's being defined in the compiler project settins directly).
BTW there is also a _WIN32 define that is set by the compiler, it's possibly a better idea to look for this define if checking if the code is being compiled under windows;
For those seeking answers to the
where is WIN32 defined
part of the questions, I've found it defined in:
minwindef.h
ole2.h
Note, I have no confidence that these are the only places it's defined. I expect there are probably other files where it's defined. Nevertheless, I thought this might help some people.
Some WIN32 defined in the compiler . Just like this,If you use the gcc for windows , WIN32 is defined . If you use the gcc for linux , WIN32 is not defined :)
So , the macros is a switch. You can define it to use somethine , and not define it to unuse something.
I'm building a commercial app, and we are using some GPL code to help us along.
How can I add #warning or #error statements so that when the code is built for debug, it warns, but when we build for release it throws errors?
I can do:
#warning this code is released under a CCL licensing scheme, see Source_Code_License.rtf
#warning this code is not LGPL-compliant
#warning this code was copied verbatim from a GP Licensed file
at the beginning of files, but can I do better? Is there a better way of tagging a file if it's included?
I'm using Objective-C++ with gcc or clang.
#ifdef SOME_SYMBOL
#error "foobar"
#else
#warning "foobar"
#endif
NDEBUG has a slightly different purpose (controlling assert) and may be #undef and re-defined selectively (reincluding assert.h to effect the change), so it probably wouldn't be the right symbol. But it is a standard macro and could be used.
Note that #error is standard, but #warning is an extension.
Use #pragma message instead.