lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Enrico Tassi wrote:
> On Fri, Mar 08, 2013 at 01:08:52AM -0700, Spencer Parkin wrote:
>> define BUILD_OBJ_RULE =
>> $(1): $(2)
>>     $$(CPP) $$(FLAGS) -c $$< -o $$@
>> endef
>> $(foreach src, $(SRCS), $(eval $(call BUILD_OBJ_RULE, $(patsubst %.cpp,
>> $(BUILD)/%.o, $(notdir $(src))), $(src))))
> 
> Nobody would write a Makefile like this one.

I have. You're right, it's horrible and totally unidiomatic, but it's
one of the few ways to do abstraction. For example:

[Makefile A]

define BUILD_PROGRAM =
...long complicated set of rules to build a program using horrible
$(foreach) stuff
endef

[Makefile B]
$(call BUILD_PROGRAM, OBJDIR=optimised CFLAGS=-Os SRCS=foo.c)
$(call BUILD_PROGRAM, OBJDIR=debug CFLAGS=-g SRCS=foo.c)
$(call BUILD_PROGRAM, OBJDIR=windows CFLAGS=-Os CC=mingw-gcc SRCS=foo.c)
$(call BUILD_PROGRAM, OBJDIR=windows-console CFLAGS="-Os -DCONSOLE"
CC=mingw-gcc SRCS=foo.c)

GNU make does provide some built-in features to make this sort of thing
a little less painful, such as target-specific variables, but they've
got weird edge conditions that make them less useful than you might think.

The absence of any kind of code abstraction is one of the reasons why
makefiles tend to balloon into unmaintainable tangles. The best example
of a modular Make build system I've seen is the one used by the Android
platform build system and NDK. It uses include files rather than macros,
and a user-specific file looks like this:

include $(CLEAR_VARS)
LOCAL_MODULE := modulename
LOCAL_SRC_FILES := list of source files
...other LOCAL_ variable definitions...
include $(BUILD_<type of thing you want to build>)

This is slightly friendlier than the macro-based alternative above, but
is still nigh incomprehensible.

-- 
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────
│
│ 𝕻𝖍'𝖓𝖌𝖑𝖚𝖎 𝖒𝖌𝖑𝖜'𝖓𝖆𝖋𝖍 𝕮𝖙𝖍𝖚𝖑𝖍𝖚 𝕽'𝖑𝖞𝖊𝖍
𝖜𝖌𝖆𝖍'𝖓𝖆𝖌𝖑 𝖋𝖍𝖙𝖆𝖌𝖓.
│

Attachment: signature.asc
Description: OpenPGP digital signature