Weijie Chen
Weijie Chen

Reputation: 164

C Makefile commands

I was trying to build a C project which has a rather unfamiliar way to define namespaces, eg. in file root.h

#define eval CRYPTO_NAMESPACE(eval)

And in the Makefile the following appears (rule for make all):

gcc -O3 -g -march=native -mtune=native -Wall -I. -Isubroutines -DKAT -DKATNUM='cat KATNUM' "-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x" -o kat nist/kat_kem.c nist/rng.c benes.c bm.c controlbits.c decrypt.c encrypt.c gf.c operations.c pk_gen.c root.c sk_gen.c synd.c transpose.c util.c -I${PWD}/subroutines -L${PWD}/libs/ -lXKCP -lcrypto -ldl

What do these options do:

"-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x"

I know that -DXXX=YYY is the same as #define XXX YYY. Now, why is it in double-quotes? Why it looks like a macro (may be it is)? Lastly, what does _##x mean?

Upvotes: 0

Views: 106

Answers (1)

Gene
Gene

Reputation: 46960

The macro in the header:

#define eval CRYPTO_NAMESPACE(eval)

Replaces every token eval with CRYPTO_NAMESPACE(eval). So if the code contains

void eval(char *expr) {
...

the preprocessor output - without any other definition - would be

void CRYPTO_NAMESPACE(eval)(char *expr) {
...

The -D parameters effectively add two more definitions:

#define DCRYPTO_NAMESPACE(x) x 
#define _CRYPTO_NAMESPACE(x) _##x

In our example, the first define causes the normal result to be re-written one more time:

void eval(char *expr) {
...

so we're back where we started. A different definition could be used to change the compiled name of the function. This definition makes the header definition a no-op.

The second macro uses the token concatenation operator ##. It adds a prefix underscore _ to the macro argument. E.g. if the code contained something like:

void _CRYPTO_NAMESPACE(foo)(int x) {

then the result is

void _foo(int x) {

At a higher level, these macros allow names of things (in the first case anything named eval and in the second, any name at all) to be transformed uniformly throughout the program. This is a fairly standard workaround for name collisions in big C programs. If you have two source code bases that have both defined the same public function name, macros like this can be used to add a prefix or suffix that changes one or both names in the compiled code without modifying either original code. This is an important capability for long-term configuration management where manually editing externally furnished code bases isn't a serious option.

A wild guess is that this treatment is given to eval because the likelihood of some other chunk of C also defining a function named eval is extremely high.

Upvotes: 1

Related Questions