5

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.

Jeff
  • 747
  • 3
  • 8
  • 17
  • 2
    Have you read [this section](http://sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/make_7.html) of the manual? Also, don't use `=` and prefer `:=` whenever possible. – Kerrek SB Aug 27 '12 at 09:34
  • @KerrekSB Good link, though not many examples. I still needed how to pass values into make. Thanks. – Jeff Aug 29 '12 at 22:15

5 Answers5

10

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
perreal
  • 94,503
  • 21
  • 155
  • 181
  • I believe you need a space after `ifeq` in your first code block (my Linux kicked out an error without it). I tried to add one for future reference, but my edit has to be lotsa characters! :( – Jeff Aug 29 '12 at 22:27
3

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.

Christian Stieber
  • 9,954
  • 24
  • 23
  • Can you clarify your "EDIT"? Do you mean that if you execute make with a different value for `DEBUG`, but the source hasn't changed, then it will not compile? For my next project, I will find a way to make Makefile a dependency (or something!). :D – Jeff Aug 29 '12 at 22:20
2

Yes it is.

You can use gcc's -D option to declare a macro, using it in your code :

> gcc -DMYINT=8 foo.c

with foo.c

int foo(void)
{
  int my = MYINT;
}

and in your makefile use :

CFLAGS    =    -DMYINT=$(MYINT)

and call make :

> make MYINT=8
Eregrith
  • 4,263
  • 18
  • 39
1

One way to achieve what you want is to pass the value of CFLAGS to your makefile from your shell.

CFLAGS='-Wall -g -DDEBUG=1' make -e 

for you debug version, or

CFLAGS='-Wall -g' make -e

for your non debug one

Stephane Rouberol
  • 4,286
  • 19
  • 18
  • Thanks Stephanie. See the other answers for how to set the value of `DEBUG` in Makefile. – Jeff Aug 29 '12 at 22:23
1

you can assign your CFLAGS variable in make like this : CFLAGS ?= -Wall -g -DDEBUG=1

if you run make command with no parameter, the CFLAGS will have a default value '-Wall -g -DDEBUG=1'

while if you run make like this: make CFLAGS='-DDEBUG=0'

this command will assign the CFLAGS value with the value '-DDEBUG=0' the assigned value will override the default value assigned in makefile

user1203650
  • 300
  • 2
  • 3
  • Thanks. I used the `?=` to set a delay, instead. E.g. `delay ?=0 CFLAGS = -DDELAY=$(delay)` (there should be a new line before "delay" and "CFAGS"). – Jeff Aug 29 '12 at 22:25