views:

132

answers:

3

In my project, a number of paths to various directories, files and other components of the system are stored as #defines in a filenames.h, a file included by all that need them. It works well for all the various binaries generated by compilation, but the project also includes a few shell scripts that use the same paths. Currently this means that as a path changes, all I have to do is edit filenames.h and recompile to get the set of executables to understand the new path, but I have to edit each shell script by hand.

So the question is, how to make the #defines into shell variables, for example generating some filenames.sh script that would be called from other scripts to initialize them. So for example:

#define TMP_PATH      "/ait/tmp/"
#define SYNCTMZFILE   TMP_PATH "sync_tmz"

would create

TMP_PATH="/ait/tmp/"
SYNCTMZFILE="/ait/tmp/sync_tmz" 

Of course it would be possible to write a C program that creates it (even prints it out to stdout and then to execute it in backticks in the shell) but I'd prefer a simpler, more robust method, say, writing a half-C half-shell like thing that run through cpp would create the right output, or something alike.

+1  A: 

The reverse -- keeping the master as a shell script and generating an header from that -- would be easier. If your header is very stylized, you can write a shell script (or use awk/sed/perl/...) to parse it and generate the shell fragment.

AProgrammer
A: 

Put this in your Makefile:

filenames.sh: filenames.h
        awk '/^#define/{print;printf "_%s=%s\n",$2,$2}' $< \
        | cpp -P \
        | sed 's/^_//;s/" "//;' > $@
mouviciel
unfortunately it doesn't do a very good job of compound statements like in the second #define.
SF.
My edited answer should work better.
mouviciel
+1  A: 

If you build your program using make and the shell scripts are executed by make as part of your build process, you could turn it around:

  • Single-source the variables in your Makefile.
  • Export them to the environment for the shell scripts.
  • Pass them to the C compiler as command line options. (This assumes your compiler supports the -D parameter or something similar.)

Example (untested):

export TMP_PATH := /ait/tmp/
export SYNCTMZFILE := $(TMP_PATH)sync_tmz
CFLAGS += -DTMP_PATH="$(TMP_PATH)" -DSYNCTMZFILE="$(SYNCTMZFILE)"

If you don't use make, the -D option still may be useful to you: you could single-source the variables in a shell script instead of in a header file.

bk1e