Scons appending a random '1' to macro definition on OSX only - c++

I have a command line argument that defines the type to use for a Vector3 class. It is defined in the SConstruct file as follows:
EnumVariable('vector3_type', 'The type to use for Vector3\'s xyz coordinates', 'float', allowed_values=['float', 'double', 'long_double'], ignorecase=2)
This variable is added to the environment here:
if env['vector3_type'] != 'long_double':
env.Append(CPPDEFINES = ["BIGROCK_VEC3_TYPE %s" % env['vector3_type']])
else:
env.Append(CPPDEFINES = ["BIGROCK_VEC3_TYPE long double"])
This works fine on Windows 10, but when I try to compile on OSX, I get the following error:
In file included from src/octree.cpp:1:
In file included from src/octree.h:5:
src/vector3.h:15:9: error: expected member name or ';' after declaration specifiers
BIGROCK_VEC3_TYPE x, y, z;
^~~~~~~~~~~~~~~~~
<command line>:1:33: note: expanded from here
#define BIGROCK_VEC3_TYPE float 1
~~~~~ ^
Either scons or g++ is adding an extra '1' to the end of my macro, causing the rest of my code to break.
When I print env['vector3_type'] in scons, it doesn't have a 1 attached. I have no idea where this 1 is being added.

This makes me feel a bit foolish. Scons assumes that a lone string within CPPDEFINES is a flag name, and will append 1 to it for #ifdef and #ifndef directives. The proper way to pass this #define is:
if env['vector3_type'] != 'long_double':
env.Append(CPPDEFINES = [("BIGROCK_VEC3_TYPE", env['vector3_type'])])
else:
env.Append(CPPDEFINES = [("BIGROCK_VEC3_TYPE", "long double")])

Related

How do I convert a cmake variable to a string in C++ code?

For example, in CMakeLists.txt, I can define path:
add_definitions(-DMY_PATH="/my/path")
In C++ code, I can access the variable by
std::string my_path = MY_PATH
This works fine. Now, if I instead define a variable in CMakeLists.txt as follows:
add_definitions(-DMY_PATH=${CMAKE_BINARY_DIR})
Then, I get the following error:
error: expected primary-expression before ‘/’ token
/home/user/development/include/helper.hpp:33:32: note: in expansion of macro ‘MY_PATH’
const std::string path = MY_PATH;
^~~~~~~
<command-line>:0:10: error: ‘home’ was not declared in this scope
/home/user/development/include/helper.hpp:33:32: note: in expansion of macro ‘MY_PATH’
const std::string path = MY_PATH;
So, why is this different? How do I convert the cmake variable to a string in C++ code?
When you use this defintion:
add_definitions(-DMY_PATH=${CMAKE_BINARY_DIR})
you will get something like this in your code:
std::string my_path = /home/my_path
which obviously leads to a syntax error, you need to add double quotes:
add_definitions(-DMY_PATH="${CMAKE_BINARY_DIR}")

Veins 4.7 Omnet++ 5.3 build error in windows 7

I am new to vein and omnet++. I followed this tutorial http://veins.car2x.org/tutorial/ everything works up to step 3, for some reason veins 4.7 doesn't build in omnet++ 5 (IDE) and generates the following errors.
veins/modules/utility/TimerManager.cc
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:137:26: error: expected identifier
enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:137:36: error: expected identifier
enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:138:24: error: expected identifier
enum class EndMode { RELATIVE, ABSOLUTE, REPITITION, OPEN };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:138:34: error: expected identifier
enum class EndMode { RELATIVE, ABSOLUTE, REPITITION, OPEN };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:42:28: error: expected unqualified-id
start_mode_ = StartMode::RELATIVE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:48:28: error: expected unqualified-id
start_mode_ = StartMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:54:24: error: expected unqualified-id
end_mode_ = EndMode::RELATIVE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:60:24: error: expected unqualified-id
end_mode_ = EndMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:86:19: error: expected unqualified-id
case StartMode::RELATIVE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:88:30: error: expected unqualified-id
start_mode_ = StartMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:90:19: error: expected unqualified-id
case StartMode::ABSOLUTE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:98:17: error: expected unqualified-id
case EndMode::RELATIVE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:100:26: error: expected unqualified-id
end_mode_ = EndMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:102:17: error: expected unqualified-id
case EndMode::ABSOLUTE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:106:26: error: expected unqualified-id
end_mode_ = EndMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
15 errors generated.
make[1]: *** [Makefile:205: ../out/clang-debug/src/veins/modules/utility/TimerManager.o] Error 1
make[1]: Leaving directory '/c/Users/Abu/src/veins-4.7/src'
make: *** [Makefile:12: all] Error 2
I am also using sumo_win64_0.32.0. I am not sure what causes these errors.
Any help is greatly appreciated.
The issue has been fixed in this pull request and a new minor revision of Veins (i.e. Veins 4.7.1) has been released. Please download the new version to get the fix and also some additional improvements.
I just encountered that error as well and here is what happens:
The compiler cannot resolve the enum class definitions in TimerManager.h as there is a name ambiguity with the macros RELATIVE and ABSOLUTE within wingdi.h
enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE };
enum class EndMode { RELATIVE, ABSOLUTE, REPITITION, OPEN };
Quick fix is to rename the occurrences in TimerManager.h and TimerManager.cc to something else. E.g. Replace all occurrences of RELATIVE with RELATIVEINS and ABSOLUTE with ABSOLUTEVEINS etc... (or whatever you like). Worked fine for me with 4.7 and OMNet++ 5.2.1.
A patch is required to make Veins 4.7 compile with OMNeT++ 5.3 for Windows. The cleanest way may be something like on https://pastebin.com/ymzqMpEF
- enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE }
+ enum class StartMode { relative, absolute, immediate }
that is, renaming the all-uppercase enum class constants to lower case ones (something recommended by many coding styles as well).

Forcing preprocessor error with macro

Is there a way that I can force a preprocessor macro in C++ to emit an error? What I would like to do is define a macro UNKNOWN. I'm writing some code for a robot, and I don't yet know where all of the electronics are being plugged in. I'd like to be able to define the ports in some header file, like
const int MOTOR_PORT = 1;
const int FAN_PORT = 2;
//etc.
However, when I reach a port that I don't yet know, I want to be able to write something like
const int LED_PORT = UNKNOWN;
In debug mode, UNKNOWN would just be defined to some arbitrary value, like 0. However, when compiling in release mode, I want it to throw an error when UNKNOWN is used, so that unassigned ports don't end up in the final release. I know I can use the #error directive to force an error, but can I do something similar in a macro?
I've seen a solution using static_assert, but I unfortunately can't use C++11 for this platform.
Since #error can't result from a macro expansion, you can ensure that the macro expands to something that must be diagnosed, like a syntax error.
For example:
#ifdef RELEASE
#define UNKNOWN #Invalid_use_of_UNKNOWN
#else
#define UNKNOWN 0
#endif
const int MOTOR_PORT = 1;
const int FAN_PORT = 2;
const int LED_PORT = UNKNOWN;
int main(void) {
int x = LED_PORT;
}
The # character isn't part of C's basic character set, so its appearance outside a comment, character constant, or string literal should always result in an error message. ($ would work, except that accepting $ in identifiers is a common extension. ` would probably also work, but # stands out better.)
I've defined the macro so it produces a reasonable error message with gcc:
c.c:9:1: error: stray ‘#’ in program
c.c:9:22: error: ‘Invalid_use_of_UNKNOWN’ undeclared here (not in a function)
and with clang:
c.c:9:22: error: expected expression
const int LED_PORT = UNKNOWN;
^
c.c:2:17: note: expanded from:
#define UNKNOWN #Invalid_use_of_UNKNOWN
^
1 error generated.
(There's a _Pragma operator corresponding to the #pragma directive. It would be nice if there were an _Error operator as well, but there isn't.)
Well, this does not produce a complier error message like #error, but would compile in debug and fail in release:
#ifdef _DEBUG
# define UNKNOWN 1
#else
# define UNKNOWN
#endif
const int port1 = UNKNOWN; // fail in release
You could make a division by zero which will throw a compiler error:
#define UNKNOWN 0/0
The sizeof operator cannot be applied to an incomplete type, so try this:
// Declared, but not defined anywhere.
struct illegal_use_of_unknown_macro;
#define UNKNOWN (sizeof (illegal_use_of_unknown_macro))

GLM: Can't compile anymore

Does anybody use this library anymore?
Worked great for me last year but now my code isn't compiling:
(on MinGW with GCC 4.6.1):
In file included from ../include/glm/./core/func_packing.hpp:190:0,
from ../include/glm/glm.hpp:103,
from SmoothRenderer.cpp:11:
../include/glm/./core/func_packing.inl: In function 'glm::detail::uint32 glm::packUnorm4x8(const glm::detail::tvec4<float>&)':
../include/glm/./core/func_packing.inl:84:17: error: expected primary-expression before '(' token
../include/glm/./core/func_packing.inl:84:17: error: expected primary-expression before ')' token
../include/glm/./core/func_packing.inl:84:17: error: expected ';' before 'round'
../include/glm/./core/func_packing.inl:85:26: error: 'D' was not declared in this scope
../include/glm/./core/func_packing.inl: In function 'glm::detail::tvec4<float> glm::unpackUnorm4x8(const uint32&)':
../include/glm/./core/func_packing.inl:94:38: warning: statement has no effect [-Wunused-value]
../include/glm/./core/func_packing.inl:99:4: error: 'D' was not declared in this scope
This is with newest version 0.9.4.3.
Similar problems on my Mac with latest clang:
In file included from SmoothRenderer.cpp:10:
In file included from ../include/glm/glm.hpp:103:
In file included from ../include/glm/./core/func_packing.hpp:190:
../include/glm/core/func_packing.inl:84:33: error: expected '(' for function-style cast or type construction
detail::uint8 D((detail::uint8)round(clamp(v.w, 0.0f, 1.0f) * 255.0f));
~~~~~~~~~~~~~^
./util.h:330:15: note: expanded from macro 'D'
# define D(x) x
^
In file included from SmoothRenderer.cpp:10:
In file included from ../include/glm/glm.hpp:103:
In file included from ../include/glm/./core/func_packing.hpp:190:
../include/glm/core/func_packing.inl:85:26: error: use of undeclared identifier 'D'
return detail::uint32((D << 24) | (C << 16) | (B << 8) | A);
^
../include/glm/core/func_packing.inl:99:4: error: use of undeclared identifier 'D'
D * 1.0f / 255.0f);
^
../include/glm/core/func_packing.inl:94:30: warning: expression result unused [-Wunused-value]
detail::uint32 D((p >> 24) & Mask8);
~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~
./util.h:330:15: note: expanded from macro 'D'
# define D(x) x
^
In file included from SmoothRenderer.cpp:10:
In file included from ../include/glm/glm.hpp:108:
In file included from ../include/glm/./core/func_noise.hpp:85:
../include/glm/core/func_noise.inl:125:33: error: too many arguments provided to function-like macro invocation
detail::tvec4<T> const D(0.0, 0.5, 1.0, 2.0);
^
../include/glm/core/func_noise.inl:125:27: error: expected ';' at end of declaration
detail::tvec4<T> const D(0.0, 0.5, 1.0, 2.0);
^
;
This is a header-only library. Things like this shouldn't be happening...
I am only using this for some 4x4 matrix multiplication and inversion. Since the rest of my app uses LAPACK extensively there is nothing i really need that glm does. But I hate when my code which I try to make very portable randomly breaks like this.
Yeah it turned out to be an issue with the D macro. Damn it, answering my question 4 minutes after asking it. That's the beauty of explaining a problem. Half the time that's enough.
This is one more reason to avoid using the preprocessor. Mad errors. Though, to its credit, clang was nice enough to not only mention that something seemed iffy with a macro defined elsewhere, it even copied it in there to show me.

C++ Macro improperly terminated macro invocation

In C++ is there a mechanism to allow non terminated macros to be expressed?
This is a contrived example:
#define MACRO(x, y) x + y
#define MACROC1(x) MACRO(x,
#define MACROC2(y) y)
//...expecting 3
int foo = MACROC1(1) MACROC2(2);
I receive the error improperly terminated macro invocation from MSVC.
When I run cl -E file.cpp I see that the code below has been generated:
int c = 1 + 1 + 2);
In visual studio compilation fails with errors:
error C2059: syntax error : ')'
IntelliSense: improperly terminated macro invocation
I don't think this is possible. The C precompiler expands macros depth-first, so the MACROC1 will be full expanded before the MACROC2 is even considered. Then, it will find the MACRO with and incomplete argument list and throws an error.
Generally speaking, you should avoid defining macros that build other macro calls. Compilers tend not to agree in what those mean.
Your code would translate to :
int foo = MACRO(1, 2;
Which is wrong - it is an incomplete (improperly terminated) invocation of macro MACRO.