1

We have a project that builds one application but uses different sources depending of some parameter. Simplified example looks like this:

app1.c

int main() {
    printf("1\n");
}

app2.c

int main() {
    printf("2\n");
}

Makefile

ifeq ($(PARAM),true)
OBJ=app1.o
else
OBJ=app2.o
endif

all: app
app: $(OBJ)
    $(CC) $< -o $@

The problem:

$ make app
cc    -c -o app2.o app2.c
cc app2.o -o app
$ ./app
2
$ PARAM=true make app
cc    -c -o app1.o app1.c
cc app1.o -o app
$ ./app
1
$ make app # I want 2 again
make: `app' is up to date.
$ ./app
1

Is there a sane way to properly rebuild everything without deleting the output?

1 Answer 1

1

The problem is that app depends on different inputs depending on the value of that variable. Make does not remember the values of variables between invocations. You effectively get different makefiles with different value of that variable.

One solution is to unconditionally build two apps:

all: app1 app2

app1: app1.o
    $(CC) -o $@ $< 

app2: app2.o
    $(CC) -o $@ $< 

And then if you only need to build one you do:

$ make app1

To build another:

$ make app2

To build all:

$ make

You may also like to add a dependency on Makefile, so that your applications get rebuilt when you change Makefile, e.g.:

app1: app1.o Makefile
    $(CC) -o $@ $(filter-out Makefile,$^)

And generate dependencies automatically:

%.o: %.c Makefile
    $(CC) -o $@ -c ${CPPFLAGS} ${CFLAGS} -MD -MP $<
-include $(wildcard *.d)
2
  • This will work in simplified case I provided. In reality application is much larger and it is linked using several libraries, some of those depend on parameter, others don't. It took me quite a time to actually figure out that the problem is with incorrect dependencies.
    – aragaer
    Commented Mar 20, 2015 at 9:50
  • 1
    @aragaer When you set that variable you effectively get a different Makefile. Commented Mar 20, 2015 at 9:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.