How to get rid of warnings that precompiler definitions are not definied - c++

There is a file that I downloaded from the Unity web-site
#pragma once
// Standard base includes, defines that indicate our current platform, etc.
#include <stddef.h>
// Which platform we are on?
// UNITY_WIN - Windows (regular win32)
// UNITY_OSX - Mac OS X
// UNITY_LINUX - Linux
// UNITY_IOS - iOS
// UNITY_TVOS - tvOS
// UNITY_ANDROID - Android
// UNITY_METRO - WSA or UWP
// UNITY_WEBGL - WebGL
#if _MSC_VER
#define UNITY_WIN 1
#elif defined(__APPLE__)
#if TARGET_OS_TV //'TARGET_OS_TV' is not defined, evaluates to 0
#define UNITY_TVOS 1
#elif TARGET_OS_IOS //'TARGET_OS_IOS' is not defined, evaluates to 0
#define UNITY_IOS 1
#else
#define UNITY_OSX 1 //'UNITY_OSX' macro redefined
#endif
#elif defined(__ANDROID__)
#define UNITY_ANDROID 1
#elif defined(UNITY_METRO) || defined(UNITY_LINUX) || defined(UNITY_WEBGL)
// these are defined externally
#elif defined(__EMSCRIPTEN__)
// this is already defined in Unity 5.6
#define UNITY_WEBGL 1
#else
#error "Unknown platform!"
#endif
...
The problem is that when I try to include the file in my XCode project I got a warning (put them in comments)
...
#if TARGET_OS_TV //'TARGET_OS_TV' is not defined, evaluates to 0
#define UNITY_TVOS 1
#elif TARGET_OS_IOS //'TARGET_OS_IOS' is not defined, evaluates to 0
#define UNITY_IOS 1
#else
#define UNITY_OSX 1 //'UNITY_OSX' macro redefined
#endif
...
I tried to use #pragma warning(suppress: 4101) and a few similar approaches, but it doesn't help
UPD
...
#ifdef TARGET_OS_TV
#define UNITY_TVOS 1
#elif TARGET_OS_IOS //'TARGET_OS_IOS' is not defined, evaluates to 0
#define UNITY_IOS 1
#else
#define UNITY_OSX 1
#endif
...
Using ifdef helps to get rid of the first warning, but the second one is still in place
UPD2
...
#ifdef TARGET_OS_TV
#define UNITY_TVOS 1
#elifdef TARGET_OS_IOS //Invalid preprocessing directive
#define UNITY_IOS 1
#else
#define UNITY_OSX 1
#endif
...

You should not use #if to test an undefined macro. The warning implies that you should use #ifdef instead.
You may not define a previously defined macro. You could first undefined the old definition, but that's rarely a good idea.
Using ifdef helps to get rid of the first warning, but the second one is still in place
In c++23 you will be able to use #elifdef instead.
Otherwise, you can use #elif defined(the_macro).

Related

how to comment values under #ifdef in one place

let's imagine we have a C++ project that should work on several platforms (for example, arm/arm64) and we need to have target-specific values for each of them.
Right now we do:
#ifdef PLATFORM_ARM
#define TIMEOUT_VALUE 0
#define OUR_MAGIC_VALUE 1
#elif PLATFORM_ARM64
#define TIMEOUT_VALUE 2
#define OUR_MAGIC_VALUE 3
#endif
where could I place a comment for each defined name that it could be accessed from each definition?
Note: I can't define each value in its own #ifdef like
// a comment for TIMEOUT_VALUE
#ifdef PLATFORM_ARM
#define TIMEOUT_VALUE 0
#elif PLATFORM_ARM64
#define TIMEOUT_VALUE 2
#endif
// a comment for OUR_MAGIC_VALUE
#ifdef PLATFORM_ARM
#define OUR_MAGIC_VALUE 1
#elif PLATFORM_ARM64
#define OUR_MAGIC_VALUE 2
#endif
because I have lists and trees of such values.
Thank you.
Edit 1:
for example, we have 6 targets and 4 of them support a FEATURE,
so we write:
#if defined(ARM)
#define FEATURE 1
#elif defined(ARM64)
#define FEATURE 0
#elif define(MIPS)
#define FEATURE 1
etc... for other platforms.
then I have code that reads this define somewhere:
#if FEATURE
do something. Note that this part can't be described in a target specific file, because it can have the same implementation for several targets.
#endif
and now I want to have a place to describe in general what this FEATURE means and do.
You can define a proxy macro and write a single comment for macro to be used by end user:
#ifdef PLATFORM_ARM
#define TIMEOUT_VALUE_IMPL 0
#define OUR_MAGIC_VALUE_IMPL 1
#elif PLATFORM_ARM64
#define TIMEOUT_VALUE_IMPL 2
#define OUR_MAGIC_VALUE_IMPL 3
#endif
// a comment for TIMEOUT_VALUE
#define TIMEOUT_VALUE TIMEOUT_VALUE_IMPL
// a comment for OUR_MAGIC_VALUE
#define OUR_MAGIC_VALUE OUR_MAGIC_VALUE_IMPL
You may also consider using constants instead of macros.

error C1189: #error : Please define your platform

I have this err when I build on visual studio ultimate2010, can you have me fix this error, thanks so much!
Error 1 error C1189: #error : Please define your
platform. d:\dzz\src\flexengine\fxcore\platform.h 28 1 battleserver
#pragma once
// 平台定义
#if defined __APPLE__
#include "AvailabilityMacros.h"
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
/* if compiling for iPhone */
#define PLATFORM_IPHONE 1
#else
#define PLATFORM_MACOSX 1
#endif
#elif TARGET_OS_IPHONE
#define PLATFORM_IPHONE 1
#elif ANDROID
#define PLATFORM_ANDROID 1
#elif _WINDOWS
#define PLATFORM_WINDOWS 1
#elif (defined(__linux__))
#define PLATFORM_LINUX 1
#elif (defined(unix))
#define PLATFORM_UNIX 1
#else
#error Please define your platform.
#endif
// 64位检测
#if defined(__x86_64__) || defined(_M_X64) || defined(__LP64__) || defined(__POWERPC64__) || defined( _WIN64 )
#define PLATFORM_64 1
#elif defined(__i386__) || defined(_M_IX86) || defined(_M_PPC) || defined(__LP32__) || defined(__POWERPC__) || IPHONE || ANDROID
#define PLATFORM_32 1
#else
#define PLATFORM_32 1
// #error Please define your platform.
#endif
// 是否支持异常
#if PLATFORM_WINDOWS
#define PLATFORM_EXCEPTIONS 1
#else
#define PLATFORM_EXCEPTIONS 0
#endif
// Platform specific include.
#if PLATFORM_WINDOWS
#include "platform_windows.h"
#elif PLATFORM_IPHONE
#include "platform_iphone.h"
#elif PLATFORM_MACOSX
#include "platform_macosx.h"
#elif PLATFORM_ANDROID
#include "platform_android.h"
#elif PLATFORM_LINUX
#include "platform_linux.h"
#else
#error Unknown platform.
#endif
It appears that this platform.h attempts to use pre-defined macros to detect the target platform. However, it tries to use _WINDOWS macro to detect windows, which is apparently a pre-processor macro supported by the Watcom compiler.
Your options:
Since the library that you use apparently only supports the watcom compiler on windows, you could use that instead of visual studio. If you choose to use VS, there may be other issues down the line that need to be fixed to support it besides this one.
You could work around the issue by defining the macro yourself.
You could fix the header to work with visual studio by replacing #elif _WINDOWS with #elif _WIN32. See macros pre-defined by visual studio.
I recommend going with the latter approach, however porting the library to VS may (or may not) involve a non-trivial amount of work.

Determining when cross compiling for 32 bit from 64-bit in preprocessor?

I used the answer from Determining 32 vs 64 bit in C++ to make this:
#ifndef AVUNA_CFG
#define AVUNA_CFG
#if _WIN32 || _WIN64
#if _WIN64
#define BIT64
#else
#define BIT32
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define BIT64
#else
#define BIT32
#endif
#endif
#endif
However, this doesn't seem to work when specifying -m32 to GCC for cross compiling, so it always says BIT64. Is there any defines I can use for this purpose?
I ended up using an Eclipse-define because I have two different run configurations for 32/64-bit cross compile. Works well.

Error: `#elif with no expression` - happens only on Windows

I'm trying to compile a project using a library I made on Windows, using MinGW 4.8.1 x86. The project compiles fine on Linux.
Common.hpp is included before everything else, and defines some macros depending on the current OS. Then ConsoleFmt.hpp is included, and it includes a file depending on the previously defined macros.
I'm getting an error, however - here's the code and the error message:
Common.hpp
#if (__linux || __unix || __posix)
#define SSVU_OS_LINUX
#elif (_WIN64 || _WIN32)
#define SSVU_OS_WINDOWS
#else
#define SSVU_OS_UNKNOWN
#endif
ConsoleFmt.hpp
#include "Common.hpp"
#ifdef SSVU_OS_LINUX
#include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplUnix.hpp"
#elif SSVU_OS_WINDOWS
#include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplWin.hpp"
#else
#include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplNull.hpp"
#endif
Error:
error: #elif with no expression:
#elif SSVU_OS_WINDOWS
Is my code invalid or is there a bug in MinGW? I think I'm using #elif correctly.
#elif is a contraction of #else and #if, not #else and #ifdef, so your line should read:
#elif defined(SSVU_OS_WINDOWS)
Edit: Because undefined macros expand to 0 in #if expressions, you could also use the original variant and define the active macro with a value of 1. (As hvd has just posted and explained.)
The safe solution, IMO, is to define SSVU_OS_* in such a way that it doesn't matter whether you use #if or #ifdef.
#if (__linux || __unix || __posix)
#define SSVU_OS_LINUX 1
#elif (_WIN64 || _WIN32)
#define SSVU_OS_WINDOWS 1
#else
#define SSVU_OS_UNKNOWN 1
#endif
This lets your #ifdef/#elif work already as it is. For consistency, you can then clean that up to
#if SSVU_OS_LINUX
#include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplUnix.hpp"
#elif SSVU_OS_WINDOWS
#include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplWin.hpp"
#else
#include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplNull.hpp"
#endif
but it isn't strictly necessary.
Making sure your macros work without needing #ifdef/defined checks allows for simpler expressions if you combine multiple checks (like you already do with the macros of others: you check multiple using ||).
To explain why it works in Linux but fails in Windows:
#elif (_WIN64 || _WIN32)
If _WIN64 has been defined then it gets replaced, e.g. if these had been defined
#define _WIN64
#define _WIN32
then the first line expands to
#elif ( || )
which would generate an error. However, if those tokens were not defined at all, they get replaced by 0:
#elif (0 || 0)
which is OK.

C++ macros explanation

Can somebody explain the following code please?
#if 1
// loop type
#define FOR_IS_FASTER 1
#define WHILE_IS_FASTER 0
// indexing type
#define PREINCREMENT_IS_FASTER 1
#define POSTINCREMENT_IS_FASTER 0
#else
// loop type
#define FOR_IS_FASTER 1
#define WHILE_IS_FASTER 0
// indexing type
#define PREINCREMENT_IS_FASTER 0
#define POSTINCREMENT_IS_FASTER 1
#endif
#if PREINCREMENT_IS_FASTER
#define ZXP(z) (*++(z))
#define ZX(z) (*(z))
#define PZ(z) (++(z))
#define ZP(z) (z)
#define ZOFF (1)
#elif POSTINCREMENT_IS_FASTER
#define ZXP(z) (*(z)++)
#define ZX(z) (*(z))
#define PZ(z) (z)
#define ZP(z) ((z)++)
#define ZOFF (0)
#endif
I can understand what the functions are doing but for example
how does the pre-processor choose which ZXP will be execute if we call it later?
What do the 1 and 0 stand for?
The #if 1 triggers the first group of #defines, which set PREINCREMENT_IS_FASTER to 1. Because of this, #if PREINCREMENT_IS_FASTER triggers the first #define ZXP....
There is nothing exceptional about 1 and 0 in this context. The #if preprocessor directive succeeds if its argument is non-zero.
You can switch to the alternate form by changing the #if 1 at the top of the file with #if 0. (Thank you #rabidmachine for the tip.)
I'm probably inclined to agree with UncleBens and suggest that it's done so that you don't understand it, because the whole lot is totally useless.