Maybe I'm missing something, but could some please explain the "logic" behind the following code?
#ifndef _PTRDIFF_T
#ifndef _T_PTRDIFF_
#ifndef _T_PTRDIFF
#ifndef __PTRDIFF_T
#ifndef _PTRDIFF_T_
#ifndef _BSD_PTRDIFF_T_
#ifndef ___int_ptrdiff_t_h
#ifndef _GCC_PTRDIFF_T
#define _PTRDIFF_T
#define _T_PTRDIFF_
#define _T_PTRDIFF
#define __PTRDIFF_T
#define _PTRDIFF_T_
#define _BSD_PTRDIFF_T_
#define ___int_ptrdiff_t_h
#define _GCC_PTRDIFF_T
#ifndef __PTRDIFF_TYPE__
#define __PTRDIFF_TYPE__ long int
#endif
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#endif /* _GCC_PTRDIFF_T */
#endif /* ___int_ptrdiff_t_h */
#endif /* _BSD_PTRDIFF_T_ */
#endif /* _PTRDIFF_T_ */
#endif /* __PTRDIFF_T */
#endif /* _T_PTRDIFF */
#endif /* _T_PTRDIFF_ */
#endif /* _PTRDIFF_T */
Why is this preferred over a simple:
#ifndef xyz
#define xyz
#endif
???
I can see they are nested, but it is very confusing. ...and btw, just what are they defining, as there are no values after the identifiers???
The logic is to only define the macros if none of them is defiend. However, I would certainly refactor it into:
#if !defined(_PTRDIFF_T) && !defined(_T_PTRDIFF_) && //... well, you get the idea
#define _PTRDIFF_T
#define _T_PTRDIFF_
//...
#ifndef __PTRDIFF_TYPE__
#define __PTRDIFF_TYPE__ long int
#endif
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#endif
As to the second question: you can define a macro without a replacement text (it would just expand to nothing if used). Such macros are often used for conditional inclusion of code based on #ifdef or #ifndef.
They're checking that all these identifiers have been defined which would be in other already included headers. If they're all defined then we define a few new identifiers.
You don't need to give a value to the identifier, for example you wouldn't give a value to your #include guards.
Related
So i have been trying to learn unrealengine4 and wanted to use vim as my editor.
As an autocompletion engine i wanted to use CoC with clangd.
After some fiddling around to get my compile_commands.json almost everything works as expected.
But i get the following two errors in every document i open.
(Just for clarification, when i use VSCode i also get the same errors if i use the clangd completion engine)
In included file: Exactly one of [UE_BUILD_DEBUG UE_BUILD_DEVELOPMENT UE_BUILD_TEST UE_BUILD_SHIPPING] should be defined to be 1[clang: pp_hash_error]
Incomplete type 'UOpenDoor' named in nested name specifier[clang: incomplete_nested_name_spec] ( assuming i open a module named OpenDoor.cpp)
The first error i was able to trace back to the Unrealengine Build Tool, as the file that contains the definition of this error is located in UnrealEngine/Engine/Source/Runtime/Core/Public/Misc/Build.h
The file is as follows:
#pragma once
/*--------------------------------------------------------------------------------
Build configuration coming from UBT, do not modify
--------------------------------------------------------------------------------*/
// Set any configuration not defined by UBT to zero
#ifndef UE_BUILD_DEBUG
#define UE_BUILD_DEBUG 0
#endif
#ifndef UE_BUILD_DEVELOPMENT
#define UE_BUILD_DEVELOPMENT 0
#endif
#ifndef UE_BUILD_TEST
#define UE_BUILD_TEST 0
#endif
#ifndef UE_BUILD_SHIPPING
#define UE_BUILD_SHIPPING 0
#endif
#ifndef UE_GAME
#define UE_GAME 0
#endif
#ifndef UE_EDITOR
#define UE_EDITOR 0
#endif
#ifndef UE_BUILD_SHIPPING_WITH_EDITOR
#define UE_BUILD_SHIPPING_WITH_EDITOR 0
#endif
#ifndef UE_BUILD_DOCS
#define UE_BUILD_DOCS 0
#endif
/**
* Whether compiling for dedicated server or not.
*/
#ifndef UE_SERVER
#define UE_SERVER 0
#endif
// Ensure that we have one, and only one build config coming from UBT
#if UE_BUILD_DEBUG + UE_BUILD_DEVELOPMENT + UE_BUILD_TEST + UE_BUILD_SHIPPING != 1
#error Exactly one of [UE_BUILD_DEBUG UE_BUILD_DEVELOPMENT UE_BUILD_TEST UE_BUILD_SHIPPING] should be defined to be 1
#endif
/*--------------------------------------------------------------------------------
Legacy defined we want to make sure don't compile if they came in a merge.
--------------------------------------------------------------------------------*/
#define FINAL_RELEASE_DEBUGCONSOLE (#)
#define FINAL_RELEASE (#)
#define SHIPPING_PC_GAME (#)
#define UE_BUILD_FINAL_RELEASE (#)
/*----------------------------------------------------------------------------
Mandatory bridge options coming from UBT, do not modify directly!
----------------------------------------------------------------------------*/
/**
* Whether we are compiling with the editor; must be defined by UBT
*/
#ifndef WITH_EDITOR
#define WITH_EDITOR 0 // for auto-complete
#error UBT should always define WITH_EDITOR to be 0 or 1
#endif
/**
* Whether we are compiling with the engine; must be defined by UBT
*/
#ifndef WITH_ENGINE
#define WITH_ENGINE 0 // for auto-complete
#error UBT should always define WITH_ENGINE to be 0 or 1
#endif
/**
* Whether we are compiling with developer tools; must be defined by UBT
*/
#ifndef WITH_UNREAL_DEVELOPER_TOOLS
#define WITH_UNREAL_DEVELOPER_TOOLS 0 // for auto-complete
#error UBT should always define WITH_UNREAL_DEVELOPER_TOOLS to be 0 or 1
#endif
/**
* Whether we are compiling with plugin support; must be defined by UBT
*/
#ifndef WITH_PLUGIN_SUPPORT
#define WITH_PLUGIN_SUPPORT 0 // for auto-complete
#error UBT should always define WITH_PLUGIN_SUPPORT to be 0 or 1
#endif
/**
* Whether we are compiling with Slate accessibility and automation support
*/
#ifndef WITH_ACCESSIBILITY
#define WITH_ACCESSIBILITY 1
#endif
/** Enable perf counters */
#ifndef WITH_PERFCOUNTERS
#define WITH_PERFCOUNTERS 0
#endif
/**
* Whether we are compiling a PGO instrumented build.
*/
#ifndef ENABLE_PGO_PROFILE
#define ENABLE_PGO_PROFILE 0
#endif
/**
* Unreal Header Tool requires extra data stored in the structure of a few core files. This enables some ifdef hacks to make this work.
* Set via UBT, do not modify directly
*/
#ifndef HACK_HEADER_GENERATOR
#define HACK_HEADER_GENERATOR 0
#endif
/** Whether we are compiling with automation worker functionality. Note that automation worker defaults to enabled in
UE_BUILD_TEST configuration, so that it can be used for performance testing on devices */
#ifndef WITH_AUTOMATION_WORKER
#define WITH_AUTOMATION_WORKER !(UE_BUILD_SHIPPING || HACK_HEADER_GENERATOR)
#endif
/**
* Whether we want a monolithic build (no DLLs); must be defined by UBT
*/
#ifndef IS_MONOLITHIC
#define IS_MONOLITHIC 0 // for auto-complete
#error UBT should always define IS_MONOLITHIC to be 0 or 1
#endif
/**
* Whether we want a program (shadercompilerworker, fileserver) or a game; must be defined by UBT
*/
#ifndef IS_PROGRAM
#define IS_PROGRAM 0 // for autocomplete
#error UBT should always define IS_PROGRAM to be 0 or 1
#endif
/**
* Whether we support hot-reload. Currently requires a non-monolithic build and non-shipping configuration.
*/
#ifndef WITH_HOT_RELOAD
#define WITH_HOT_RELOAD (!IS_MONOLITHIC && !UE_BUILD_SHIPPING && !UE_BUILD_TEST && !UE_GAME && !UE_SERVER)
#endif
/**
* Whether we include support for text archive formats. Disabling support allows de-virtualizing archive calls
* and eliminating string constants for field names.
*/
#ifndef WITH_TEXT_ARCHIVE_SUPPORT
#define WITH_TEXT_ARCHIVE_SUPPORT WITH_EDITORONLY_DATA
#endif
/*----------------------------------------------------------------------------
Optional bridge options coming from UBT, do not modify directly!
If UBT doesn't set the value, it is assumed to be 0, and we set that here.
----------------------------------------------------------------------------*/
/**
* Checks to see if pure virtual has actually been implemented, this is normally run as a CIS process and is set (indirectly) by UBT
*
* #see Core.h
* #see ObjectMacros.h
**/
#ifndef CHECK_PUREVIRTUALS
#define CHECK_PUREVIRTUALS 0
#endif
/** Whether to use the null RHI. */
#ifndef USE_NULL_RHI
#define USE_NULL_RHI 0
#endif
/** If not specified, disable logging in shipping */
#ifndef USE_LOGGING_IN_SHIPPING
#define USE_LOGGING_IN_SHIPPING 0
#endif
#ifndef USE_CHECKS_IN_SHIPPING
#define USE_CHECKS_IN_SHIPPING 0
#endif
/** If not defined follow the CHECK behavior since previously ensures were compiled in with checks */
#ifndef USE_ENSURES_IN_SHIPPING
#define USE_ENSURES_IN_SHIPPING USE_CHECKS_IN_SHIPPING
#endif
#ifndef ALLOW_CONSOLE_IN_SHIPPING
#define ALLOW_CONSOLE_IN_SHIPPING 0
#endif
/** Compile flag to force stats to be compiled */
#ifndef FORCE_USE_STATS
#define FORCE_USE_STATS 0
#endif
/**
* Optionally enable support for named events from the stat macros without the stat system overhead
* This will attempt to disable regular stats system and use named events instead
*/
#ifndef ENABLE_STATNAMEDEVENTS
#define ENABLE_STATNAMEDEVENTS 0
#endif
#ifndef ENABLE_STATNAMEDEVENTS_UOBJECT
#define ENABLE_STATNAMEDEVENTS_UOBJECT 0
#endif
/*--------------------------------------------------------------------------------
Basic options that by default depend on the build configuration and platform
DO_GUARD_SLOW If true, then checkSlow, checkfSlow and verifySlow are compiled into the executable.
DO_CHECK If true, then checkCode, checkf, verify, check, checkNoEntry, checkNoReentry, checkNoRecursion, verifyf, checkf are compiled into the executables
DO_ENSURE If true, then ensure, ensureAlways, ensureMsgf and ensureAlwaysMsgf are compiled into the executables
STATS If true, then the stats system is compiled into the executable.
ALLOW_DEBUG_FILES If true, then debug files like screen shots and profiles can be saved from the executable.
NO_LOGGING If true, then no logs or text output will be produced
--------------------------------------------------------------------------------*/
#if UE_BUILD_DEBUG
#ifndef DO_GUARD_SLOW
#define DO_GUARD_SLOW 1
#endif
#ifndef DO_CHECK
#define DO_CHECK 1
#endif
#ifndef DO_ENSURE
#define DO_ENSURE 1
#endif
#ifndef STATS
#define STATS ((WITH_UNREAL_DEVELOPER_TOOLS || !WITH_EDITORONLY_DATA || USE_STATS_WITHOUT_ENGINE || USE_MALLOC_PROFILER || FORCE_USE_STATS) && !ENABLE_STATNAMEDEVENTS)
#endif
#ifndef ALLOW_DEBUG_FILES
#define ALLOW_DEBUG_FILES 1
#endif
#ifndef ALLOW_CONSOLE
#define ALLOW_CONSOLE 1
#endif
#ifndef NO_LOGGING
#define NO_LOGGING 0
#endif
#elif UE_BUILD_DEVELOPMENT
#ifndef DO_GUARD_SLOW
#define DO_GUARD_SLOW 0
#endif
#ifndef DO_CHECK
#define DO_CHECK 1
#endif
#ifndef DO_ENSURE
#define DO_ENSURE 1
#endif
#ifndef STATS
#define STATS ((WITH_UNREAL_DEVELOPER_TOOLS || !WITH_EDITORONLY_DATA || USE_STATS_WITHOUT_ENGINE || USE_MALLOC_PROFILER || FORCE_USE_STATS) && !ENABLE_STATNAMEDEVENTS)
#endif
#ifndef ALLOW_DEBUG_FILES
#define ALLOW_DEBUG_FILES 1
#endif
#ifndef ALLOW_CONSOLE
#define ALLOW_CONSOLE 1
#endif
#ifndef NO_LOGGING
#define NO_LOGGING 0
#endif
#elif UE_BUILD_TEST
#ifndef DO_GUARD_SLOW
#define DO_GUARD_SLOW 0
#endif
#ifndef DO_CHECK
#define DO_CHECK USE_CHECKS_IN_SHIPPING
#endif
#ifndef DO_ENSURE
#define DO_ENSURE USE_ENSURES_IN_SHIPPING
#endif
#ifndef STATS
#define STATS ((USE_MALLOC_PROFILER || FORCE_USE_STATS) && !ENABLE_STATNAMEDEVENTS)
#endif
#ifndef ALLOW_DEBUG_FILES
#define ALLOW_DEBUG_FILES 1
#endif
#ifndef ALLOW_CONSOLE
#define ALLOW_CONSOLE 1
#endif
#ifndef NO_LOGGING
#define NO_LOGGING !USE_LOGGING_IN_SHIPPING
#endif
#elif UE_BUILD_SHIPPING
#if WITH_EDITOR
#ifndef DO_GUARD_SLOW
#define DO_GUARD_SLOW 0
#endif
#ifndef DO_CHECK
#define DO_CHECK 1
#endif
#ifndef DO_ENSURE
#define DO_ENSURE 1
#endif
#ifndef STATS
#define STATS 1
#endif
#ifndef ALLOW_DEBUG_FILES
#define ALLOW_DEBUG_FILES 1
#endif
#ifndef ALLOW_CONSOLE
#define ALLOW_CONSOLE 0
#endif
#ifndef NO_LOGGING
#define NO_LOGGING 0
#endif
#else
#ifndef DO_GUARD_SLOW
#define DO_GUARD_SLOW 0
#endif
#ifndef DO_CHECK
#define DO_CHECK USE_CHECKS_IN_SHIPPING
#endif
#ifndef DO_ENSURE
#define DO_ENSURE USE_ENSURES_IN_SHIPPING
#endif
#ifndef STATS
#define STATS (FORCE_USE_STATS && !ENABLE_STATNAMEDEVENTS)
#endif
#ifndef ALLOW_DEBUG_FILES
#define ALLOW_DEBUG_FILES 0
#endif
#ifndef ALLOW_CONSOLE
#define ALLOW_CONSOLE ALLOW_CONSOLE_IN_SHIPPING
#endif
#ifndef NO_LOGGING
#define NO_LOGGING !USE_LOGGING_IN_SHIPPING
#endif
#endif
#else
#error Exactly one of [UE_BUILD_DEBUG UE_BUILD_DEVELOPMENT UE_BUILD_TEST UE_BUILD_SHIPPING] should be defined to be 1
#endif
/**
* This is a global setting which will turn on logging / checks for things which are
* considered especially bad for consoles. Some of the checks are probably useful for PCs also.
*
* Throughout the code base there are specific things which dramatically affect performance and/or
* are good indicators that something is wrong with the content. These have PERF_ISSUE_FINDER in the
* comment near the define to turn the individual checks on.
*
* e.g. #if defined(PERF_LOG_DYNAMIC_LOAD_OBJECT) || LOOKING_FOR_PERF_ISSUES
*
* If one only cares about DLO, then one can enable the PERF_LOG_DYNAMIC_LOAD_OBJECT define. Or one can
* globally turn on all PERF_ISSUE_FINDERS :-)
*
**/
#ifndef LOOKING_FOR_PERF_ISSUES
#define LOOKING_FOR_PERF_ISSUES (0 && !(UE_BUILD_SHIPPING))
#endif
/** Enable the use of the network profiler as long as we are not a Shipping or Test build */
#ifndef USE_NETWORK_PROFILER
#define USE_NETWORK_PROFILER !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
#endif
/** Enable UberGraphPersistentFrame feature. It can speed up BP compilation (re-instancing) in editor, but introduce an unnecessary overhead in runtime. */
#define USE_UBER_GRAPH_PERSISTENT_FRAME 1
/** Enable validation of the Uber Graph's persistent frame's layout, this is useful to detect uber graph frame related corruption */
#define VALIDATE_UBER_GRAPH_PERSISTENT_FRAME (!(UE_BUILD_SHIPPING || UE_BUILD_TEST)) && USE_UBER_GRAPH_PERSISTENT_FRAME
/** Enable fast calls for event thunks into an event graph that have no parameters */
#define UE_BLUEPRINT_EVENTGRAPH_FASTCALLS 1
/** Enable perf counters on dedicated servers */
#define USE_SERVER_PERF_COUNTERS ((UE_SERVER || UE_EDITOR) && WITH_PERFCOUNTERS)
#define USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING 1
#define USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS (USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING && 0)
// 0 (default), set this to 1 to get draw events with "TOGGLEDRAWEVENTS" "r.ShowMaterialDrawEvents" and the "ProfileGPU" command working in test
#ifndef ALLOW_PROFILEGPU_IN_TEST
#define ALLOW_PROFILEGPU_IN_TEST 0
#endif
#ifndef ALLOW_PROFILEGPU_IN_SHIPPING
#define ALLOW_PROFILEGPU_IN_SHIPPING 0
#endif
// draw events with "TOGGLEDRAWEVENTS" "r.ShowMaterialDrawEvents" (for ProfileGPU, Pix, Razor, RenderDoc, ...) and the "ProfileGPU" command are normally compiled out for TEST and SHIPPING
#define WITH_PROFILEGPU (!(UE_BUILD_SHIPPING || UE_BUILD_TEST) || (UE_BUILD_TEST && ALLOW_PROFILEGPU_IN_TEST) || (UE_BUILD_SHIPPING && ALLOW_PROFILEGPU_IN_SHIPPING))
#ifndef ALLOW_CHEAT_CVARS_IN_TEST
#define ALLOW_CHEAT_CVARS_IN_TEST 1
#endif
#define DISABLE_CHEAT_CVARS (UE_BUILD_SHIPPING || (UE_BUILD_TEST && !ALLOW_CHEAT_CVARS_IN_TEST))
// Controls the creation of a thread for detecting hangs (FThreadHeartBeat). This is subject to other criteria, USE_HANG_DETECTION
#ifndef ALLOW_HANG_DETECTION
#define ALLOW_HANG_DETECTION 1
#endif
#define USE_HANG_DETECTION (ALLOW_HANG_DETECTION && !WITH_EDITORONLY_DATA && !IS_PROGRAM && !UE_BUILD_DEBUG && !ENABLE_PGO_PROFILE)
// Controls the creation of a thread for detecting hitches (FGameThreadHitchHeartBeat). This is subject to other criteria, USE_HITCH_DETECTION
#ifndef ALLOW_HITCH_DETECTION
#define ALLOW_HITCH_DETECTION 0
#endif
// Adjust a few things with the slack policy and MallocBinned2 to minimize memory usage (at some performance cost)
#ifndef AGGRESSIVE_MEMORY_SAVING
#define AGGRESSIVE_MEMORY_SAVING 0
#endif
// Controls if UObjects are initialized as soon as they are available or only after the module is "loaded". This only applies to monolithic builds; if there are DLLs, this is how it works anyway and this should not be turned on
#ifndef USE_PER_MODULE_UOBJECT_BOOTSTRAP
#define USE_PER_MODULE_UOBJECT_BOOTSTRAP 0
#endif
#define USE_HITCH_DETECTION (ALLOW_HITCH_DETECTION && !WITH_EDITORONLY_DATA && !IS_PROGRAM && !UE_BUILD_DEBUG)
// Controls whether shipping builds create backups of the most recent log file.
// All other configurations always create backups.
#ifndef PRESERVE_LOG_BACKUPS_IN_SHIPPING
#define PRESERVE_LOG_BACKUPS_IN_SHIPPING 1
#endif
#ifndef ENABLE_RHI_VALIDATION
#define ENABLE_RHI_VALIDATION (UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT)
#endif
// Controls whether FPlatformMisc::GetDeviceId() is available to be called.
// When set to 1, calls to this API will be hardcoded to return an empty string
// to avoid running afoul of calling device APIs that platform owners may restrict
// access to without waivers or special steps. Code that uses GetDeviceId() should
// expect to receive empty strings in these cases and response appropriately with
// fallback logic.
#ifndef GET_DEVICE_ID_UNAVAILABLE
#define GET_DEVICE_ID_UNAVAILABLE 0
#endif
When i manually change the option UE_BUILD_DEVELOPMENT to 1 then the first error just gets replaced by all other errorsdefined later. e.g.In included file: UBT should always define WITH_EDITOR to be 0 or 1
I suspect the problem is, that i am using the UBT wrong, but i have no idea, how to use it correctly.
For the second error when i look into the header file at the definition of UOpenDoor which is :
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class BUILDINGESCAPE_API UOpenDoor : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UOpenDoor();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
//Door Opening Function
virtual void OpenDoor(float DeltaTime);
//Door Closing Function
virtual void CloseDoor(float DeltaTime);
private:
//Member Variable definition
FRotator StartingRotation;
FRotator TargetRotation;
float DoorLastOpened = 0.f;
//Exposed parameters
UPROPERTY(EditAnywhere)
float OpenAngle = 90.f;
UPROPERTY(EditAnywhere)
float DoorDelay = 2.f;
UPROPERTY(EditAnywhere)
float OpenVelocity = 2.f;
UPROPERTY(EditAnywhere)
float CloseVelocity = 2.f;
UPROPERTY(EditAnywhere)
ATriggerVolume* Trigger;
UPROPERTY(EditAnywhere)
AActor* TriggerActor;
};
I get the error Variable has incomplete type 'class BUILDINGESCAPE_API'
Since i am quite new to c++ i have no idea where to go from there.
Any help would be greatly appreciated, as this problem has beeen driving me insane for weeks now...
Thanks a lot in Advance!
There is a nice write-up on github targeted at QtCreator, but it could be abstracted to any tool.
In a nut shell:
Generate some intermediate files:
cd <project-dir>
make UE4Editor
Find the needed defines in Intermediate/Build/Linux/<build-id>/UE4Editor/Development/<project-name>/Definitions.<project-name>.h
Additionally will you need these:
#define UE_BUILD_DEVELOPMENT 1
#define WITH_EDITOR 1
#define WITH_UNREAL_DEVELOPER_TOOLS 1
#define WITH_PLUGIN_SUPPORT 1
#define IS_MONOLITHIC 1
#define IS_PROGRAM 0
#define UE_EDITOR 1
#define CORE_API
#define COREUOBJECT_API
#define ENGINE_API
#define SLATE_API
#define INPUTCORE_API
#define SLATECORE_API
#define MESSAGING_API
#define RENDERCORE_API
#define RHI_API
#define SHADERCORE_API
#define ASSETREGISTRY_API
#define ENGINEMESSAGES_API
#define ENGINESETTINGS_API
#define SYNTHBENCHMARK_API
#define RENDERER_API
#define GITSOURCECONTROL_API
#define EDITORSTYLE_API
#define SOURCECONTROL_API
#define CHAOS_API
#define PHYSICSCORE_API
#define APPLICATIONCORE_API
#define DEVELOPERSETTINGS_API
I also need #define UE_TRACE_ENABLED 0 on UE 4.26
In the linked gist, a Python script was used to parse the Definitions.<project-name>.h file and generate an output, that can be used by QtCreator. I have no knowledge of vim+clangd, but with the above information one should be able to find a similar solution.
I understand that this error is typically a syntax problem. I've gone through this with a fine toothcomb and can't spot it. The example below is whittled down to a couple of files which display the problem. The header files describe an API that is provided as a couple of lib files which I've referenced in the Eclipse project, but just trying to compile the following from the command line gives the same error.
I have several chained includes before getting to the first function declaration which throws an "expected initializer" error, along with every other declaration that follows.
main.cpp
#include <iostream>
#include <string>
#include <windows.h>
#include "defn.h"
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
defn.h
#ifndef GEO_DEFINITIONS_H_INCLUDED
#define GEO_DEFINITIONS_H_INCLUDED
#include <iostream>
#include <string>
#define C_MICROSOFT
#define _UNICODE
#include "gxlib.h"
#endif // GEO_DEFINITIONS_H_INCLUDED
gxlib.h
#pragma once
#include <windows.h>
#ifdef C_MICROSOFT
#define GX_WRAPPER_FUNC __declspec(dllexport)
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
#define GX_OBJECT_PTR void*
#define GX_VAR
#define GX_CONST const
#define GX_VOID void
#define GX_LONG long
#define GX_DOUBLE double
#define GX_HANDLE long
#define GX_LONG_PTR long*
#define GX_DOUBLE_PTR double*
#define GX_HANDLE_PTR long*
#define GX_ASTR_PTR char*
#define GX_WSTR_PTR wchar_t*
#if defined(GEO_UTF8)
#define GX_STR_PTR GX_ASTR_PTR
#elif defined( _UNICODE)
#define GX_STR_PTR GX_WSTR_PTR
#else
#define GX_STR_PTR GX_ASTR_PTR
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*---------------- Copy_3DN[_public] ----------------*/
GX_WRAPPER_FUNC GX_LONG GX_WRAPPER_CALL
Copy_3DN(GX_VAR GX_OBJECT_PTR,
GX_CONST GX_HANDLE_PTR,
GX_CONST GX_HANDLE_PTR);
#ifdef __cplusplus
}
#endif
The command line and exact error is
c:\Code\CPP>g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.cpp
In file included from defn.h:11:0,
from main.cpp:4:
gxlib.h:55:1: error: expected initializer before 'Copy_3DN'
Copy_3DN(GX_VAR GX_OBJECT_PTR,
As I mentioned above, this is just an excerpt from a larger project that I'm building in Eclipse Mars using the MinGW-64 5.3 toolchain. Within Eclipse I've defined all of the include files and linked to the libraries, but this simple commandline example with everything in the same directory demonstrates the error.
I was lead to the answer by #SamVarshavchik's comment and this thread. The problem is the MSVC specific syntax
#define GX_WRAPPER_FUNC __declspec(dllexport)
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL _cdecl
#define GX_STANDARD_CALL _stdcall
In my case the MSVC definitions are wrapped within the C_MICROSOFT #ifdef block, and that is the ONLY occurence of that definition, so the simplest solution is to remove the C_MICROSOFT define in defn.h and replace it with:
#ifdef __GNUC__
#define GX_WRAPPER_FUNC __attribute__ ((dllexport))
#define GX_STANDARD_FUNC
#define GX_WRAPPER_CALL __attribute__((cdecl))
#define GX_STANDARD_CALL __attribute__((stdcall))
#define _stdcall __attribute__((stdcall))
#define _cdecl __attribute__((cdecl))
#define GX_OBJECT_PTR void*
#define GX_VAR
#define GX_CONST const
#define GX_VOID void
#define GX_LONG long
#define GX_DOUBLE double
#define GX_HANDLE long
#define GX_LONG_PTR long*
#define GX_DOUBLE_PTR double*
#define GX_HANDLE_PTR long*
#define GX_ASTR_PTR char*
#define GX_WSTR_PTR wchar_t*
#define GX_STR_PTR GX_WSTR_PTR
#else
#define C_MICROSOFT
#endif
What is the difference between the C++ macro VERIFY() and ATLVERIFY() ? And which one is better to use for COM objects?
There is some difference in how the errors are reported. ATLVERIFY is defined as
#ifndef ATLVERIFY
#ifdef _DEBUG
#define ATLVERIFY(expr) ATLASSERT(expr)
#else
#define ATLVERIFY(expr) (expr)
#endif // DEBUG
#endif // ATLVERIFY
And ATLASSERT is
#ifndef ATLASSERT
#define ATLASSERT(expr) _ASSERTE(expr)
#endif // ATLASSERT
So it ends up in _ASSERTE (see https://msdn.microsoft.com/en-us/library/ezb1wyez.aspx )
While VERIFY is
#ifdef _DEBUG
#define VERIFY(f) ASSERT(f)
#else // _DEBUG
#define VERIFY(f) ((void)(f))
#endif // !_DEBUG
So it ends up in ASSERT (see https://msdn.microsoft.com/en-us/library/aa297139(v=vs.60).aspx )
I have a problem where I can't seem to get conditional #define preprocessors to work correctly. For example:
#define WIN32_BUILD
#ifdef WIN32_BUILD
#define PCH "stdafx.h"
#else
#define PCH "xyz.h"
#endif
#include PCH
If I use this form, the compiler tells me that it can't find 'stdafx.h'. OK, that seems odd, so if I change the code to....
#define WIN32_BUILD
#ifdef WIN32_BUILD
#define PCH "xyz.h"
#else
#define PCH "stdafx.h"
#endif
#include PCH
Then the file defined in PCH gets picked up and everything compiles fine. This seems odd to me, almost like the preprocessor is ignoring the #if directives and just using all the #defines that it encounters.
Obviously I am doing something wrong, and I was hoping that someone could help me understand this.
When a project has the precompiled header feature turned on the preprocessor ignores everything that comes before #include "stdafx.h"
So your #define statements are ignored.
TL:DR; #define defines the symbol, #ifdef tests if the symbol is defined not whether it has a value.
#define WIN32_BUILD
This defines a pre-processor token, WIN32_BUILD. The token has no value. Anywhere you use the token 'WIN32_BUILD' the pre-processor will substitute the empty string, i.e. nothing.
#ifdef WIN32_BUILD
This checks if the pre-processor token WIN32_BUILD is defined. It is, you just defined it.
#ifdef WIN32_BUILD
// true - this code is included.
#define PCH "stdafx.h"
This defines the pre-processor token, PCH, and assigns it the value "stdafx.h"
#else
#define PCH "xyz.h"
#endif
This code is ignored, because WIN32_BUILD was defined.
It looks as though you were expecting 'ifdef' to only evaluate to true if the expression was not defined /to/ something.
#define a
#define b SOMETHING
#ifdef a
// you are expecting this to be ignored
#endif
#ifdef b
// and expecting this not to be ignored
#endif
#ifdef and #if defined(...) do the same thing.
#define a
#define b SOMETHING
#if defined(a) && defined(b)
// this code will be evaluated, both tokens are defined.
#endif
This feature of pre-processor tokens is often used to support conditional functionality:
#if HAVE_CPP11_OVERRIDE_KEYWORD
#define OVERRIDE_FN override
#else
#define OVERRIDE_FN
#endif
struct A {
virtual void foo() {}
};
struct B : public A {
void foo() OVERRIDE_FN {}
};
In the above code, the override keyword is only added if the system supports it (determined outside of the code).
So a compiler with override sees
struct B : public A {
void foo() override {}
};
a compiler without it sees
struct B : public A {
void foo() {}
};
Note: The opposite of "ifdef" is "ifndef":
#define a
#define b SOMETHING
#undef c
//#define d // << we didn't define it.
int main() {
#ifdef a
#pramga message("a is defined")
#else
#pramga message("a is UNdefined")
#endif
#ifdef b
#pragma message("b is defined")
#else
#pramga message("b is UNdefined")
#endif
#ifdef c
#pramga message("c is defined")
#endif
#else
#pramga message("c is UNdefined")
#endif
#ifdef d
#pramga message("d is defined")
#endif
#else
#pramga message("d is UNdefined")
#endif
#ifndef d
#pragma message("d is not defined")
#endif
#ifndef a
#pragma message("a is not defined")
#endif
return 0;
}
You can assign a pre-processor token numeric values and test them with #if
#if _MSC_VER
#define WIN32_BUILD 1
#else
#define WIN32_BUILD 0
#endif
#if WIN32_BUILD
#include <Windows.h>
#endif
But, especially when doing cross-platform programming, people tend to use ifdef variants rather than numeric checks, because the value checks require you to explicitly ensure all of the tokens are defined with a value. It's a lot easier just to only define them when you need them.
When working with library ABC, it natural that all names are included into the same top level namespace. Is it possible to remove top level namespace from class names, but show inclosed namespaces?
There is no such option inside of Doxygen. Still you can use preprocessor to make it work.
#ifndef DOXY_PARSER
#define LIB_NAMESPACE_STARTS namespace lib_namespace { /##/
#define LIB_NAMESPACE_ENDS } /##/
#define LIB_NAMESPACE lib_namespace
#else
#define LIB_NAMESPACE_STARTS /##/
#define LIB_NAMESPACE_ENDS /##/
#define LIB_NAMESPACE
#endif
You should include this code into some common header and set predefined DOXY_PARSER macro in Doxygen options. This workaround makes using of library namespace less convenient but it is not so crucial.
LIB_NAMESPACE_STARTS();
namespace internal_namespace {
struct Trololo {};
}
LIB_NAMESPACE::internal_namespace::Trololo T;
LIB_NAMESPACE_ENDS();
There is a general problem with the previous solution, it is not valid when using Qt. The moc'ing process doesn't use the preprocessor and the namespace is not used (leading to a compile time error).
One possible solution would be to use a #define QT_NAMESPACE lib_namespace but it will move the whole Qt to that namespace.
The next solution is more general (I've kept the macros name for convenience):
#ifndef DOXY_PARSER
#define LIB_NAMESPACE lib_namespace
#define LIB_NAMESPACE_STARTS namespace LIB_NAMESPACE { /##/
#if (defined MOCED_FILE)
#define LIB_NAMESPACE_ENDS } using namespace LIB_NAMESPACE; /##/
#else
#define LIB_NAMESPACE_ENDS } /##/
#endif
#define USING_LIB_NAMESPACE using namespace LIB_NAMESPACE; /##/
#else
#define LIB_NAMESPACE_STARTS /##/
#define LIB_NAMESPACE_ENDS /##/
#define LIB_NAMESPACE
#define USING_LIB_NAMESPACE /##/
#endif
Where MOCED_FILE is a define exclusive for mocs. If you are using CMake, you can specify such option using:
QT4_WRAP_CPP(mocSources qt_file1.h qt_file2.h)
SET_SOURCE_FILES_PROPERTIES(${mocSources} PROPERTIES COMPILE_FLAGS "-DMOCED_FILE")