什么是以下Makefile目标的DRY版本?

时间:2010-04-03 20:22:33

标签: makefile dry

我不知道如何执行存储为变量的命令或如何在目标内部使用ifeq,所以我现在有一个非常冗余的Makefile! / p>

理想情况下,我想只有一个目标(all)可以在Mac上运行存储的命令并在Linux上运行两次,一次使用-m32,一次使用-m64。

all:
    echo PLEASE SELECT OS, e.g. make linux
    exit 1

mac:
     gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME) $(SOURCE) $(LIBRARIES)

linux:
    gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME64) $(SOURCE) $(LIBRARIES64) -m64
    gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME) $(SOURCE) $(LIBRARIES) -m32

更新:这是我在阅读各种建议后最终得到的结果。 (是的,我知道我应该使用autoconf ......)谢谢大家的帮助!

ifeq($(PLATFORM), Linux)
    COMMON = -pthread -fPIC
    PLATFORM_CFLAGS = $(COMMON) -m32
    PLATFORM_CFLAGS64 = $(COMMON) -m64
endif

ifeq ($(PLATFORM), Darwin)
    PLATFORM_CFLAGS = -arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk
endif

all: $(PLATFORM)_all

Darwin_all:
     mkdir -p ../../../../tmp
     gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME) $(SOURCE) $(LIBRARIES)

Linux_all: Darwin_all
     gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS64) -o $(BUILD_DIR)$(BUILD_NAME64) $(SOURCE) $(LIBRARIES64)

3 个答案:

答案 0 :(得分:2)

这非常简单,但您应该可以通过更改运行的shell命令使其适应更复杂的事情。

PLATFORM := $(shell uname)

all:$(PLATFORM)

Darwin:
    echo Darwin

Linux:
    echo Linux

答案 1 :(得分:2)

你让宏完成大部分工作,注意你应该使用$(CC)而不是gcc。

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64

# We could do some fancy stuff here...
# Except that we will remove the commands momentarily
all:
    echo PLEASE SELECT OS, e.g. make linux
    exit 1

# Note that without a qualifier
# - MacOS X 10.5.x will build 32-bit
# - MacOS X 10.6.x will build 64-bit
# But why not build both anyway?
mac:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

linux:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

哦,看,现在Linux和MacOS X的命令是相同的......所以我们可以这样做:

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64

all:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

天哪,正如我通常在我的文件中所做的那样写作$(XXX)而不是$ {XXX}是一项艰苦的工作。

基本上,我们通过使名称系统化来应用DRY(不要重复自己)。 Makefile不应该令人兴奋。

如果你仍然希望平台之间有所不同,那么你可以按照Ivan Andrus建议的方式做点什么。 GNU Make允许您评估shell命令,所以:

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64

all:  $(shell uname)

Linux:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

Darwin:
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32)

如果你觉得你不能依赖GNU Make,那么:

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64
BUILD_32      = use_32_bit
BUILD_64      = use_64_bit
BUILD_TYPE    = $(BUILD_32) $(BUILD_64)

.PHONEY: $(BUILD_32) $(BUILD_64)

all:  $(BUILD_TYPE)

use_64_bit:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)

use_32_bit:
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

默认情况下,这将编译32位和64位版本。 如果只需要32位或64位,请运行以下两者中的相应一个:

make BUILD_TYPE=use_32_bit
make BUILD_TYPE=use_64_bit

答案 2 :(得分:1)

你有一些很好的建议(探索平台,使用变量),但是你也应该意识到你的运行非常接近于最好不再考虑支持平台,而是考虑到描述您的软件所需的功能,并使用autoconf(和系列)来发现实际存在的内容。

请注意,如果它是一个GUI应用程序,那么OSX代码和Linux / X11代码之间可能会有很多差异,通过平台检测是合理的。对于任何面向命令行的东西,你需要这样做是很少见的,因为OSX看起来很像普通的旧Unix。