Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a value to Make, which gets passed to C code

Tags:

c

linux

makefile

I'm looking for help getting my Makefile to do what I want it to do.

I have figured out how to add preprocessing code to my C source which will compile only if I'm compiling for debug:

#if DEBUG
  printf("main()\n");

  {
    /* Pauses execution so gdb can attach. */
    int i=9;
    pid_t PID;
    char hostname[256];
    gethostname(hostname, sizeof(hostname));
    printf("PID %d on %s ready for attach.\n", PID=getpid(), hostname);
    fflush(stdout);
    while (i>0) {
      sleep(5);
      i--;
    }
  }
#endif

And I've figured out that if I add -DDEBUG=1 to my compile statement, that the above code will be compiled (otherwise it's not compiled).

Next, I want to pass a flag to my Makefile which will either include, or not include the -D option. Currently, I have two separate compile lines which I comment and uncomment as appropriate. Here is my Makefile (which I inherited from someone and am having a difficult time understanding). See the lines that say CFLAGS?:

SHELL = /bin/sh

prefix       = /home/schwarz/sundials/instdir
exec_prefix  = ${prefix}
includedir   = ${prefix}/include
libdir       = ${exec_prefix}/lib

CPP         = cc -E
CPPFLAGS    =
CC          = cc
# CFLAGS      = -Wall -g
CFLAGS      = -Wall -g -DDEBUG=1
# CFLAGS      = -g -O2
LDFLAGS     =
LIBS        = -lm
MPICC       = /usr/local/mpi/bin/mpicc
MPI_INC_DIR = /usr/local/mpi/bin/../include
MPI_LIB_DIR = /usr/local/mpi/bin/../lib
MPI_LIBS    =
MPI_FLAGS   =

INCLUDES = -I${includedir} -I${MPI_INC_DIR}
LIBRARIES = -lsundials_cvode -lsundials_nvecparallel ${LIBS}
LIBRARIES_BL =

EXAMPLES = FPU          # cvAdvDiff_non_p cvDiurnal_kry_bbd_p cvDiurnal_kry_p


OBJECTS = ${EXAMPLES:=.o}

# -----------------------------------------------------------------------------------------

.SUFFIXES : .o .c

.c.o :
        ${MPICC} ${CPPFLAGS} ${CFLAGS} ${MPI_FLAGS} ${INCLUDES} -c $<

# -----------------------------------------------------------------------------------------

all: ${OBJECTS}
        @for i in ${EXAMPLES} ; do \
          echo "${MPICC} -o $${i} $${i}.o ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL}" ; \
          ${MPICC} -o $${i} $${i}.o ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL}; \
        done

clean:
        rm -f ${OBJECTS}
        rm -f ${EXAMPLES}

I have searched the web - I swear! - but cannot figure out how to pass a parameter into the makefile. How can I set up my Makefile so that it does different types of compiles of the same code for different compile needs? Even better would be if I could pass a specific value to the Makefile, which would pass a specific value to the compile, which I could use to initialize i in the code. (IOW, I compile as make 8 and the C is compiled as int i=8;). Is any of that even possible in Make?

As an aside, I've read about Makefiles and how they work by listing files with labels (colons), followed by their dependencies. But I can't understand how this Makefile works or why it issues two compile statements. So a brief explanation would also be helpful.

like image 793
Jeff Avatar asked Aug 27 '12 09:08

Jeff


2 Answers

To choose between debug and release versions:

ifeq($(debug),1)
  CFLAGS      = -Wall -g -DDEBUG=1
else
  CFLAGS      = -Wall -g
endif

and then invoke make:

make debug=1

to compile with DEBUG, or:

make

to compile without debug.

For initializing i:

#include <stdio.h>

#ifndef INIT_I
# define INIT_I 9
#endif
int main() {
  int i = INIT_I;
  return 0;
}

and makefile:

ifneq ($(init_i),)
CFLAGS = "-DINIT_I=$(init_i)"
endif

all:
  gcc d.c $(CFLAGS) -E

to set initial i:

make init_i=10

or use default value:

make
like image 60
perreal Avatar answered Oct 05 '22 00:10

perreal


Example Makefile:

...
CFLAGS = whatever
....
ifeq ("$(DEBUG)","yes")
CFLAGS += -DDEBUG=1
endif

With this, you could run make as:

make "DEBUG=yes"

Basically, you can set makefile variables on the make command line. You can use these like any other variables in the makefile, so you could also use them directly.

EDIT: you have to be careful, though. Unless you take care to name your object files appropiately, or use different build dirs, running make with different "DEBUG" settings isn't going to recompile things automatically.

like image 24
Christian Stieber Avatar answered Oct 05 '22 02:10

Christian Stieber