0

How to rewrite Makefile paragraph-pairs like this, into one single paragraph? I have:

$(BUILD_DIR_DEBUG)/args.o: \
        $(SRC)/args.c \
        $(SRC)/args.h \
        $(SRC)/something_else.h
    $(CC) $(CFLAGS) $(CFLAGS_DEBUG) -c -o $@ $<

$(BUILD_DIR_RELEASE)/args.o: \
        $(SRC)/args.c \
        $(SRC)/args.h \
        $(SRC)/something_else.h
    $(CC) $(CFLAGS) $(CFLAGS_RELEASE) -c -o $@ $<

I'd be happy to get something like this (do not assume correct syntax), but I don't know how to define such:

# ${BUILD_TYPE} to be iterated as "DEBUG" and "RELEASE" to get two current
# runtime rules from one actually written rule.
$(BUILD_DIR_$(BUILD_TYPE))/args.o: \
        $(SRC)/args.c \
        $(SRC)/args.h \
        $(SRC)/something_else.h
    $(CC) $(CFLAGS) $(CFLAGS_$(BUILD_TYPE)) -c -o $@ $<
1737973
  • 159
  • 18
  • 42
  • I can figure out several ways to do such iteration from a Python script processing some kind of custom extra syntax, but I don't want to do that. – 1737973 Apr 13 '20 at 15:27
  • Does this answer your question? [How can I configure my makefile for debug and release builds?](https://stackoverflow.com/questions/1079832/how-can-i-configure-my-makefile-for-debug-and-release-builds) – uzsolt Apr 13 '20 at 20:15
  • [There is a single very interesting answer there](https://stackoverflow.com/a/20830354/1737973) meriting an upvote; but no, none of those posts answers this question. – 1737973 Apr 13 '20 at 20:23
  • https://stackoverflow.com/a/35893827/412080 – Maxim Egorushkin Apr 13 '20 at 22:55

2 Answers2

1

You don't really describe how you want to use these rules so there may be simpler solutions, such as using recursive make. However if you want just the most basic answer to exactly the question you asked, then the answer is eval.

First you write a variable containing your rule:

define RULE
$(BUILD_DIR_$(BUILD_TYPE))/args.o: \
            $(SRC)/args.c \
            $(SRC)/args.h \
            $(SRC)/something_else.h
        $$(CC) $$(CFLAGS) $$(CFLAGS_$(BUILD_TYPE)) -c -o $$@ $$<
endef

$(foreach BUILD_TYPE,DEBUG RELEASE,$(eval $(RULE)))

Note carefully the escaped $$ in the recipe of the rule variable. This is needed because this variable is expanded once before being parsed by eval, and you don't want these recipe variables to be expanded there, you want to defer their expansion until the recipe is actually run.

You might find the set of blog posts here (start with the last one in the list, which was the first one written) to learn more about this: http://make.mad-scientist.net/category/metaprogramming/

1737973
  • 159
  • 18
  • 42
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • I'll take a time to process all of your blog posts, but this was immediate help. Thank you very much. – 1737973 Apr 14 '20 at 11:35
  • Haven't read the blog posts **yet**, but I think this is working well: https://hastebin.com/tefudobewo.makefile – 1737973 Apr 14 '20 at 13:19
-1

short answer:

ifeq ($(DEBUG), 1)
BUILD_DIR = $(BUILD_DIR_DEBUG)
CFLAGS = $(CFLAGS_DEBUG)
else
BUILD_DIR = $(BUILD_DIR_RELEASE)
CFLAGS = $(CFLAGS_RELEASE)
endif

$(BUILD_DIR)/args.o: \
        $(SRC)/args.c \
        $(SRC)/args.h \
        $(SRC)/something_else.h
    $(C) $(CFLAGS) -c -o $@ $<

and set the variable DEBUG as you see fit. for example make DEBUG=1

see also:

How can I configure my makefile for debug and release builds?

https://www.gnu.org/software/make/manual/html_node/Conditional-Example.html

Lesmana
  • 25,663
  • 9
  • 82
  • 87