I'm having problems with cpp Preprocessor. I have this Input.h file like this:
#ifndef PLATFORM_MOBILE1111
#define MyTest WEB111
#endif
int MyTest;
I process it with this command (on OSX):
cpp -E -P Source/Input.h Generated/Output.h
I get this:
#define MyTest WEB111
int MyTest;
i.e. macro MyTest is not getting applied. Why?
After a bunch of experimentation, I found that if I insert an empty line, variable definition, a comment or any other line after #ifndef line - then it works fine.
#ifndef PLATFORM_MOBILE1111
#define MyTest WEB111
#endif
int MyTest;
So the input above gets processed correctly into:
int WEB111;
Can someone explain to me why that is happening? and how to solve that? Is there an option that I can pass?
Edit: I also found that ## (concatenation operator) doesn't work too!
Strange! You clearly found a bug in the clang preprocessor!
I can reproduce this as well (Apple LLVM version 8.1.0 (clang-802.0.42)) on OSX.
This also starts working as expected when you remove the spaces before #define (indentation), but leading spaces should not matter at all, and a lot of editors indent #defines inside #ifdefs.
One hint on what is going on is that in the bogus versions the #define is still present in the processed source code, while in the correct version it is not. So apparently the preprocessor did not recognize the #define as such at all.
Even this fails (note the leading space):
#define MyTest WEB111
int MyTest;
While this works as expected:
#define MyTest WEB111
int MyTest;
And this results in WEB222:
#define MyTest WEB111
#define MyTest WEB222
int MyTest;
While this results in WEB111:
#define MyTest WEB111
#define MyTest WEB222
int MyTest;
Crazy!1!! :-)
It seems that always the first indented #define gets ignored.
Now the 'solution': Use:
gcc -E Source/Input.cpp -P -o Generated/Output.cpp
This works as expected, although it is using the same LLVM.
So I assume the gcc executable initializes the preprocessor differently than the cpp. This is still a bug in cpp.
I found out that running preprocessor through c++ rather than cpp solves both of my problems:
c++ -E -P Source/Input.h Generated/Output.h
BTW.: you need to add -x c++ flag if you file is not using regular c/c++ extention for c++ command. cpp works fine without that.
Related
How can I expand or collapse the defines in the header file for example
#define IOC_IN 0x80000000
#define IOC_WS2 0x08000000
#define _WSAIOW(x,y)(IOC_IN|(x)|(y))
#define SIO_ASSOCIATE_HANDLE _WSAIOW(IOC_WS2,1)
I tried doing gcc -E file.h > output.h however this outputs an empty file. I am using MingW compiler.
I expect the defines to be subsituted like this:
#define IOC_IN 0x80000000
#define IOC_WS2 0x08000000
#define _WSAIOW(x,y)(IOC_IN|(x)|(y))
#define SIO_ASSOCIATE_HANDLE (IOC_IN|(IOC_WS2)|(1))
The defines "in the header" are not "expanded", what do you expect to happen?
Instead, places where they are used are going to be preprocessed to have the definitions inserted.
You typically preprocess a C file, not a header, i.e. something where a #define is used without being defined.
GCC (the preprocessor actually) ignores your defines because they are unused. Try appending int x = SIO_ASSOCIATE_HANDLE; and rerun the gcc.
I see this being done all the time for example in the Linux Kernel. What is the purpose of using the preprocessor commands vs just normal C++ if else block? Is there a speed advantage or something?
A preprocessor changes the C/C++ code before it gets compiled (hence pre processor).
Preprocessor ifs are evaluated at compile-time.
C/C++ ifs are evaluated at run-time.
You can do things that can't be done at run-time.
Adjust code for different platforms or different compilers:
#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
#include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
#include <windows.h>
#endif
Ensure header file definitions are included only once (equivalent of #pragma once, but more portable):
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example { ... };
#endif
You can make things faster than at run-time.
void some_debug_function() {
#ifdef DEBUG
printf("Debug!\n");
#endif
}
Now, when compiling with DEBUG not defined (likely a command line parameter to your compiler), any calls to some_debug_function can be optimized away by the compiler.
Preprocessor is run before the compilation pass, so the compiler won't even see anything that was in the not-taken #if branch.
#if DEBUG
int a;
#else
double b;
#endif
gcc -c -DDEBUG=1 file.c will see "int a"
gcc -c file.c will see "double b"
Preprocessor allows you to actually cut out or paste in to your source file, code to be compiled. If its cut out, its gone, its like a comment, does nothing, is not compiled, produces no code in the binary. Devs will often use this technique to add code only in debug build for debugging purposes or for adding or excluding code for specific operating systems.
I have a very trivial problem including a chain of C libraries into a C++ main project. I've experience with C but it's the first time that I'm programming in C++.
The structure of the project is a single folder with inside:
main.cpp
Mylib_1.c
Mylib_1.h
Mylib_2.c
Mylib_2.h
main calls -> Mylib_1.h that calls -> My_lib2.h
//main.cpp
#include "Mylib_1.h"
//Mylib_1.h
#include "Mylib_2.h"
main contains both Mylib_1 and Mylib_2 functions and typedef structs
Mylib_1 uses typedef structs and functions of Mylib_2
Everything inside each Mylib_x.h is wrapped between extern "C", like this:
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
#ifdef __cplusplus
extern "C" {
#endif
mycode
#ifdef __cplusplus
}
#endif
#endif
But when I try to compile it with eclipse kepler on Ubuntu 12.04 x64, I get:
Mylib_1.h error: Mylib_2_type_t does not name a type
main.cpp error: Mylib_2_function1 was not declared in this scope
...
Only the above sections are marked as error in eclipse, the header looks included fine.
Furthermore according to eclipse, the __cplusplus flag is false into Mylib_2.h but true into Mylib_1.h
Thinking of some eclipse error, I've tried to manually build the project via g++ (v4.6.3) but I got the same exact problem when I've tried to link the libraries .o with the main.cpp
Seems stupid but I can't figure out what could it be. Any suggestion?
Thank you
Have you checked that your lines
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
are really different for the two files,
e.g. _MYLIB1_H and _MYLIB2_H?
I'm trying to port a Linux library to run on VxWorks. I have successfully built binutils and gcc to target i486-wrs-vxworks and I can successfully build a simple C program. However, when I try to compile C++, things break.
I have a simple Hello World program:
#include <string>
#include <iostream>
int main()
{
std::string s = "Hello World";
std::cout << s << std::endl;
return 0;
}
To build it, I call:
i486-wrs-vxworks-gcc -I/home/kyle/vxworks-6.9/target/usr/h -I/home/kyle/vxworks-6.9/target/usr/h/c++ hello.cpp
This always fails with the message:
In file included from /home/kyle/vxworks-6.9/target/usr/h/c++/cerrno:4:0,
from /home/kyle/vxworks-6.9/target/usr/h/c++/xlocnum:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/ios:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/ostream:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/istream:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/string:4,
from hello.cpp:1:
/usr/local/lib/gcc/i486-wrs-vxworks/4.6.4/../../../../i486-wrs-vxworks/include/yvals.h:4:24: fatal error: yvals.h: No such file or directory
If I go look inside /usr/local/i486-wrs-vxworks/include/yvals.h, this is what I see:
/* yvals.h values header for conforming compilers on various systems */
#if (defined(__cplusplus) && defined(__GNUC__))
/* GCC C++ has it's own yvals.h */
#include_next <yvals.h>
#else /* __cplusplus && __GNUC__ */
#ifndef _YVALS
#define _YVALS
#ifdef _NO_WINDRIVER_MODIFICATIONS
#include <stdarg.h>
#endif
...
It appears that there is another yvals.h that needs to be included, but I can't find it anywhere. Did I just fail at building gcc correctly, or is there a way to fix this?
Which version of VxWorks are you using for this?
I have a fuzzy recollection that when upgrading VxWorks versions in the past there was a syntax error in yvals.h that was I needed to work around and it was fixed in a subsequent version.
Also, you can get the gcc cross compiler pre-built from WindRiver. Just login to windriver.com/support with your licence number and head to "Downloads" for your product version.
I went through a recent cross compiling nightmare myself (not VxWorks related) except that instead of yvals.h, I was having grief with stddef.h. The problem turned out to be that I needed to specify the include paths for the system header files.
Here are the steps it took me to solve my error messages. Feel free to modify as appropriate.
Create a file foo.c
#include <stddef.h> /* The problem header file (yvals.h for you?) */
int main (void) {
return 0;
}
Compile it with your compiler of choice
$(CC) foo.c -E
Note the include paths it uses and set them as your system header file list using the
-isystem <include path>
option.
Hope this helps.
As per this answer, I tried printing a uint64_t, but it gives me an error:
error: expected ``)' before 'PRIu64'
Following is the minimal code showing what I am trying to do:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <cstdio>
class X {
X() {
uint64_t foo = 0;
printf("%07" PRIu64 ": ", foo);
}
};
int main() {}
This minimal code compiles, but my actual code does not. However, I have tried with the 2 lines inside X::X() exactly the same in my actual code, and that does not work.
What should I look for to debug this further? My actual code also #includes other headers. Could that be causing the problem? Does order of including the headers matter?
Edit
PRIu64 is defined as follows on my machine:
# if __WORDSIZE == 64
# define __PRI64_PREFIX "l"
# define __PRIPTR_PREFIX "l"
# else
# define __PRI64_PREFIX "ll"
# define __PRIPTR_PREFIX
# endif
# define PRIu64 __PRI64_PREFIX "u"
In C++ the macros are not automatically defined just by including the file.
You need to add the following:
#define __STDC_FORMAT_MACROS 1
before
#include <inttypes.h>
How to printf uint64_t? Fails with: "spurious trailing ‘%’ in format"
One other possibility for this issue I just found in my own code is if another header already pulls in <inttypes.h> before you define __STDC_FORMAT_MACROS. For example:
Utils.h (Perhaps originally written for C, as it was in our case):
#include <inttypes.h>
// ... Function declarations
MyFile.cpp:
#include "Utils.h"
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
Since inttypes.h has already been included by Util.h, the compiler doesn't include it again, and doesn't see the declaration of __STDC_FORMAT_MACROS.
The solution is either to edit Utils.h to include #define __STDC_FORMAT_MACROS, or to make sure to define it before doing any includes in MyFile.cpp.
#define __STDC_FORMAT_MACROS
#include "Utils.h"
#include <inttypes.h>
The original setup actually compiled just fine on GCC 4.8 on Ubuntu, but failed with an old ltib GCC 4.3 toolchain for PowerPC, which made it all the more perplexing at first.
PRIu64 is not defined where you use it.
Replace it with the string "llu" and your code will compile (but that is not a fix, it just demonstrates the problem)
Maybe the include is missing. Maybe over zealos include guards and it being included without the magic token block the define. Maybe your pch is busted.
If you are on android JNI platform. Put this in your Android.mk:
LOCAL_CPPFLAGS := -D__STDC_FORMAT_MACROS