1

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?

2
  • I suppose mac means that you are building in Mac OS, but what is Nova then? Commented Jan 30, 2018 at 7:49
  • A linux server which I need my project to work on, and don't have sanction there. So I want to make mac to debug on my machine, but make / make nova to work as default. Commented Jan 30, 2018 at 7:51

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, I thought about something like that, but on the Nova machine they don't have shell - I'm getting shell: Command not found through SSH. Kinda weird, but I gotta deal with that. Are there other known options? Ideally, I might want to add Windows in the future, but I don't want to deal with that right now.
so, you are not able to connect to Nova via SSH at all? Perhaps you don't have permissions, but build will still have access to shell, you should try.
Sorry if I wasn't clear enough. I am able to connect via SSH of course, it's just that the machine doesn't have the shell command. I don't know what variant of linux it is, but it just doesn't have it. And I cannot apt-get install shell there.
you don't need shell command, just type uname in the command line
My bad, I guess I'm not familiar enough with unix after all. Thank you.
|
0

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

2 Comments

Thanks, but I don't need them to run separately. Ideally, on one machine I would want to use make nova and on other make mac, where the only change is the inc and lib paths. Why would I want another makefile, and dealing with exporting make variables? Why would I want to separate the build command?
@galah92 If you are running make as you've just said (i.e.: by running make nova or make mac), then I see no problem with your current makefile.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.