Reputation: 3991
I've got the following situation in my makefile:
SDLINC_NOVA = -I/usr/local/lib/sdl_2.0.5/include/SDL2 -D_REENTRANT
SDLLIB_NOVA = -L/usr/local/lib/sdl_2.0.5/lib -Wl,-rpath,/usr/local/lib/sdl_2.0.5/lib -Wl,--enable-new-dtags -lSDL2 -lSDL2main
SDLINC_MAC = -I/usr/local/SDL/include -D_REENTRANT
SDLLIB_MAC = -L/usr/local/SDL/lib -Wl,-rpath,/usr/local/SDL/lib -Wl,-install_name,--enable-new-dtags -lSDL2 -lSDL2main
....
.PHONY: all nova mac clean
all: nova
nova: SDLINC = $(SDLINC_NOVA)
nova: SDLLIB = $(SDLLIB_NOVA)
nova: build
mac: SDLINC = $(SDLINC_MAC)
mac: SDLLIB = $(SDLLIB_MAC)
mac: build
build: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) $(SDLLIB) -o $@
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) $(SDLINC) -c $< -o $@
It feels like I'm doing something wrong.. Basically the SDLINC
and SDLLIB
variables should contain different value based on the rule that is called, and then the build
rule should be called.
What is the right convention to achieve that in a makefile?
Upvotes: 1
Views: 245
Reputation: 24738
The problem is that the build
target is a common prerequisite of both nova
and mac
. Therefore, the rule for the target build
is only matched once. That is, it is matched for the first target that requires it, then it remains updated for the second target that requires it.
You can set up your makefile, so that those targets above depend on different prerequisites:
nova: SDLINC = $(SDLINC_NOVA)
nova: SDLLIB = $(SDLLIB_NOVA)
nova: build-nova
mac: SDLINC = $(SDLINC_MAC)
mac: SDLLIB = $(SDLLIB_MAC)
mac: build-mac
With this new setup, mac
depends on build-mac
and nova
depends on build-nova
.
Then, by adding the following rule:
build-nova build-mac:
$(MAKE) --no-print-directory $(TARGET)
its recipe will be executed for each target (i.e.: build-nova
and build-mac
) separately.
What the recipe of that rule does is to call make
recursively for the target specified (i.e.: the result of expanding TARGET
). You need however to export both SDLINC
and SDLLIB
variables in your makefile, so that the new process which runs make
obtains them:
export SDLINC
export SDLLIB
Upvotes: 0
Reputation: 2079
Basically, the right approach would be not to have two different rules for Mac and Linux. This is because both of those are Unix-based systems and are quite common.
The approach is to automatically detect the system you are running on, this can be done using uname
shell command:
OS := $(shell uname)
ifeq ($(OS), Darwin)
OS := mac
else ifeq ($(OS), Linux)
OS := linux
else
$(info Warning: unknown OS, assuming linux)
OS := linux
endif
And then just add ifeq
conditions to assign your variables:
ifeq ($(OS), linux)
SDLINC = $(SDLINC_NOVA)
SDLLIB = $(SDLLIB_NOVA)
else ifeq ($(OS), mac)
SDLINC = $(SDLINC_MAC)
SDLLIB = $(SDLLIB_MAC)
endif
and remove your rules for mac
and nova
, now you only need one build
rule.
You can check what is the output of uname
command on your Nova machine and adjust it accordingly in your makefile, but I'm pretty sure it will be Linux
.
Upvotes: 1