MACRO definition both for a number and a string [duplicate] - c++

I'd like to pass the name of an include file as a compiler argument so that I can modify a large number of configuration parameters. However, my C++ build is via a makefile like process that removes quotes from arguments passed to the compiler and pre-processor. I was hoping to do something equivalent to
#ifndef FILE_ARG
// defaults
#else
#include "FILE_ARG"
#endif
with my command line including -DFILE_ARG=foo.h. This of course doesn't work since the preprocessor doesn't translate FILE_ARG.
I've tried
#define QUOTE(x) #x
#include QUOTE(FILE_ARG)
which doesn't work for the same reason.
For scripting reasons, I'd rather do this on the command line than go in and edit an include line in the appropriate routine. Is there any way?

For adding quotes you need this trick:
#define Q(x) #x
#define QUOTE(x) Q(x)
#ifdef FILE_ARG
#include QUOTE(FILE_ARG)
#endif

You can do
#ifdef FILE_ARG
#include FILE_ARG
#endif
On the command line
$ gcc -DFILE_ARG="\"foo.h\"" ...
should do the trick.

You can also try the -include switch.
gcc manual:
-include file
Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is
the preprocessor's working directory instead of the directory
containing the main source file. If not found there, it is searched
for in the remainder of the #include "..." search chain as normal.
If multiple -include options are given, the files are included in the order they appear on the command line.*

Works for me. Maybe you forgot to quote correctly in your Makefile?
$ cat example.c
#include FILE_ARG
$ cat test.h
#define SOMETHING
$ gcc -Wall -Wextra -W -DFILE_ARG=\"test.h\" -c example.c
$
EDIT:
The reason you might not be able to get quoting to work is because the preprocessor works in phases. Additionally I used "gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2", results may vary between compilers.

Related

How to define DOBJC_OLD_DISPATCH_PROTOTYPES in Xcode?

I use Xcode 11 and need to replicate this compiler command:
cc -g -Wall -Wall -Wextra -std=c99 -pedantic \
-DOBJC_OLD_DISPATCH_PROTOTYPES -c -o example.o example.c
Adding OBJC_OLD_DISPATCH_PROTOTYPES as a user defined macro with no value to the Build Settings doesn't help. Also defining it in the source fails by telling me it already got defined by Xcode via the command line. Despite setting a few suspicious flags to No, it seems Xcode keeps executing #define OBJC_OLD_DISPATCH_PROTOTYPES 1. How can I disable that?
I don't know how Xcode works but I see two points.
In the image you post you ask for a define like DOBJC_OLD_DISPATCH_PROTOTYPES, but in the command line you show it is OBJC_OLD_DISPATCH_PROTOTYPES. Which one you want to define? (Note the first D in the image: it isn't in the command line.)
With the first D the command line parameter would be:
-DDOBJC_OLD_DISPATCH_PROTOTYPES
(The -D is to define, the rest is what is defined.)
Normally that define should be made in the preprocessor options, not the compiler. You can see an example here although I don't know if the example is outdated. (There should be an option somewhere to set preprocessor defines though.)
If Xcode, no matter what, defines that as 1, you can redefine it whenever you need it:
#ifdef OBJC_OLD_DISPATCH_PROTOTYPES
#undef OBJC_OLD_DISPATCH_PROTOTYPES
#define OBJC_OLD_DISPATCH_PROTOTYPES
#endif
(Or DOBJC_OLD_DISPATCH_PROTOTYPES.)
That will get rid of the 1.
You have more information here.

How to compile C++ for the same preprocesor variable

In main.c ++ I have several preprocessor variables defined.
#ifndef FIRST
#define FIRST "./path/for/output/files"
#endif
#ifndef SECOND
#define SECOND 0.0125
#endif
#ifndef THIRD
#define THIRD "./input_file.mesh"
#endif
I have to compile this .cpp by varying the three preprocessor macros. To do this, I tried to make a bash file with a for loop to vary the values that these macros took, that is:
#!/bin/bash
for i in *.mesh
do
g++ -Ofast -fopenmp main.cpp eig3.cpp vema.cpp -o main10 -DFIRST=\"\.\/$i\" -DSECOND=0.0125 -DTHIRD=\'\"\.\/$i\"\'
done
This loop constantly reports error, it does not recognize the input file and neither does the output folder. I imagine that I am making many mistakes, I am new to C ++ and I am still a bit lost.
I would like to know if there is any possibility to compile this code with many different values for each parameter. Thank you!
If you really don't want to change the program all that much, compile it once as follows:
g++ -Ofast -fopenmp main.cpp eig3.cpp vema.cpp -o main10 -DFIRST='getenv("OUTPUT")' -DSECOND=0.0125 -DTHIRD='getenv("INPUT")'
And call it as follows:
for i in *.mesh; do
INPUT=./$i OUTPUT=./path/for/output/files ./main10
done

G++ seems to be ignoring #ifdef for an #include

Environment
Ubuntu 16.04
G++ 5.3.1
I have a header file with the following intended to include a different .h file depending on platform:
#ifdef _WIN32
#include "curses.h"
#else
#include <ncurses.h>
#endif
This works fine in windows but in Ubuntu I get errors about the curses.h file:
In file included from /usr/include/unctrl.h:54:0,
from /usr/include/curses.h:1694,
from headers/command_window.h:8,
from command_window.cpp:1:
headers/curses.h:900:19: error: macro "clear" passed 1 arguments, but takes just 0
int clear(void);
This when compiling with:
g++ -g -lncurses -std=c++11 -Iheaders -c -o command_window.o command_window.cpp
Why is headers/curses.h, which is the windows specific file for PDCurses being involved here at all?
/usr/include/unctrl.h contains this line:
#include <curses.h>
And since you've told the compiler to look in your headers/ folder for header files with the -Iheaders flag , the compiler picks up curses.h in that folder.
So you need to drop the -Iheaders flag (and e.g. use #include "headers/header_name.h") or you need to rename your headers/curses.h to not collide with /usr/include/curses.h
In your version of g++, the -I option is not the correct way to add application-specific header files (those that shouldn't be found by #include in system headers) to the search path (this change surprised me as well).
Instead, you should use -iquote headers.
See this answer: How to tell g++ compiler where to search for include files? and this official documentation

Adding quotes to argument in C++ preprocessor

I'd like to pass the name of an include file as a compiler argument so that I can modify a large number of configuration parameters. However, my C++ build is via a makefile like process that removes quotes from arguments passed to the compiler and pre-processor. I was hoping to do something equivalent to
#ifndef FILE_ARG
// defaults
#else
#include "FILE_ARG"
#endif
with my command line including -DFILE_ARG=foo.h. This of course doesn't work since the preprocessor doesn't translate FILE_ARG.
I've tried
#define QUOTE(x) #x
#include QUOTE(FILE_ARG)
which doesn't work for the same reason.
For scripting reasons, I'd rather do this on the command line than go in and edit an include line in the appropriate routine. Is there any way?
For adding quotes you need this trick:
#define Q(x) #x
#define QUOTE(x) Q(x)
#ifdef FILE_ARG
#include QUOTE(FILE_ARG)
#endif
You can do
#ifdef FILE_ARG
#include FILE_ARG
#endif
On the command line
$ gcc -DFILE_ARG="\"foo.h\"" ...
should do the trick.
You can also try the -include switch.
gcc manual:
-include file
Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is
the preprocessor's working directory instead of the directory
containing the main source file. If not found there, it is searched
for in the remainder of the #include "..." search chain as normal.
If multiple -include options are given, the files are included in the order they appear on the command line.*
Works for me. Maybe you forgot to quote correctly in your Makefile?
$ cat example.c
#include FILE_ARG
$ cat test.h
#define SOMETHING
$ gcc -Wall -Wextra -W -DFILE_ARG=\"test.h\" -c example.c
$
EDIT:
The reason you might not be able to get quoting to work is because the preprocessor works in phases. Additionally I used "gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2", results may vary between compilers.

How to exclude certain #include directives from C++ stream?

I have this C++ file (let's call it main.cpp):
#include <string>
#include "main.y.c"
void f(const std::string& s) {
yy_switch_to_buffer(yy_scan_string(s.c_str()));
yyparse();
}
The file depends on main.y.c, which has to be generated beforehand by means of bison util. In other words, I can't compile main.c file if I forget to run bison main.y before it. And it's perfectly OK, this is how I want it. Now I'm trying to build .d file from Makefile, using this command:
$ c++ -MM main.c > main.d
main.cpp:2:10: error: main.y.c: No such file or directory
I fail here, since main.y.c is not ready yet. I think that I should somehow quote my #include directive in the main.c file to make it invisible for c++ -MM process.
This sounds like a job for a makefile. You can set the dependencies such that main.c depends on main.y.c, and main.y.c has a rule to build it from the bison code.
You can indicate in your makefile that main.c depends on main.y.c so that it'll run the bison process before it tries to compile main.c.
As an alternative (which I think is probably not what you want to do) is that you can have your makefile pass a macro to the compiler to indicate whether or not main.y.c exists and use an #if directive to include (or not) main.y.c.
#if EXISTS_MAIN_Y_C
#include "main.y.c"
#endif