Compiling #define's *value* in a string

Jul 14, 2008 at 5:51pm
OK, I need to compile the *value* of a #define'ed symbol into a C++ program.
I would like to pass the symbol's value on the compile line without a lot of hideous quoting. (Partly to make it independent of any particular shell's quoting rules, and partly to reduce the magic involved so that others can maintain it.

I want a compile command line that looks something like this:

... compiler command ... -DFILENAME=foo.txt ... code.cpp

Inside code.cpp I want to construct the character string "foo.txt".

I've tried the stringify operator:

#define stringify(x) #x

But stringify(FILENAME) evaluates to "FILENAME".

I've tried lots of other quoting variations, but I either get "FILENAME" or foo.txt unquoted.

Is it even possible to do what I want with a #define symbol? Or am I just stuck with having to quote it on the command line?

Thanks,
Robert
Jul 14, 2008 at 6:42pm
Have you tried putting -DFILENAME="'foo.txt'" i.e. in single quotes inside double quotes?

It can be done from a #define in a file so you should be able to do it from the command line
Last edited on Jul 14, 2008 at 6:45pm
Jul 14, 2008 at 7:00pm
Well yeah, I can quote it on the command line. And it looks like I may have to do it there. I just wanted to do all the quoting in the cpp file.

BTW, aren't your quotes backward. Shouldn't it be -DFILENAME='"foo.txt"' ?
Jul 14, 2008 at 8:11pm
You may be right about the quotes, it's not something I do very often.

I've never seen anyone try to do it this way, it is usually done through reading a file or environment variable.

Why have you chosen to do it like this?
Jul 14, 2008 at 8:22pm
The CPP cannot do what you want... alas. It is possible that GPP might have some extension that will do it, but I don't remember it.

There shouldn't be any problem quoting as follows for win32 or posix shells. You may have troubles on older systems...

gcc ... -DFILENAME="\"filename.txt\"" ...


In any case, typically a makefile is executed by bash (or at least the old sh) anyway, so unless you expect your program to be heavily used on ancient OSes, you might as well just figure that it isn't worth your time to worry about it.

Sorry.
Jul 14, 2008 at 11:06pm
It's not like I had much choice in the matter. The program in question is a thin wrapper Setup.exe, so there isn't any environment set up when it executes.

The filename is set by an environment variable when the Setup.exe is compiled.
Jul 14, 2008 at 11:29pm
Ah, then you can make yourself a little include file that will do it for you. As part of your make requirements/targets, add a phony target that will build the include file. You can do something like:
1
2
3
4
5
.PHONY: filename-target

filename-target:
	echo const char* filename = "%FILENAME%"; > filename.inc

Then you can use it in your program easily enough:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main()
  {
  #include "filename.inc"

  cout << "The filename is \"" << filename << "\".\n";

  return 0;
  }

Hope this helps.

[edit]
If you can't guarantee command.com or cmd.exe will be available on the target, you can just compile an extra little utility program that will generate the include file, and use the phony target the same way to cause its generation
1
2
3
4
5
6
7
8
9
10
11
12
// genfname.exe
#include <cstdlib>
#include <cstdio>
using namespace std;

int main()
  {
  char* filename = getenv( "FILENAME" );
  if (filename == NULL) filename = "#error FILENAME is not defined";
  printf( "const char* filename = \"%s\";\n", filename );
  return 0;
  }

and
1
2
filename-target:
	genfname.exe > filename.inc


:-)
Last edited on Jul 14, 2008 at 11:35pm
Jul 15, 2008 at 3:58pm
Yeah, I thought about the include file solution.

It looks to me like quoting the string on the compiler command line is just about the simplest way to get it done.

Thanks all,
Topic archived. No new replies allowed.