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

发布于 2024-08-27 06:05:19 字数 1325 浏览 4 评论 0原文

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

理想情况下,我希望只有一个目标(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)

I don't know how to execute a command stored as a variable or how to use ifeq inside of a target, so I have a very redundant Makefile at the moment!

Ideally I'd like to have just one target (all) which would run the stored command on Mac and run it twice on Linux, once with -m32 and once with -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

UPDATE: This is what I ended up with, after reading the various suggestsions. (Yes I know I should use autoconf . . .) Thanks everyone for your help!

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

二智少女 2024-09-03 06:05:19

您让宏完成大部分工作,并注意您应该使用 $(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)

天啊,像我通常在 makefile 中那样编写 $(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

You make macros do most of the work, noting that you should use $(CC) rather than 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)

Oh, and look, the commands are the same for Linux and MacOS X now...so we can do:

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)

Gosh, it is hard work writing $(XXX) instead of ${XXX} as I normally do in my makefiles.

Basically, we apply DRY (Don't Repeat Yourself) by making names boringly systematic. Makefiles should not be exciting.

If you still want to have a difference between your platforms, then you can do something along the lines suggested by Ivan Andrus. GNU Make allows you to evaluate shell commands, so:

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)

If you feel you can't rely on GNU Make, then:

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)

By default this will compile both 32-bit and 64-bit versions.
If you want 32-bit only or 64-bit only, run the appropriate one of these two:

make BUILD_TYPE=use_32_bit
make BUILD_TYPE=use_64_bit
心碎的声音 2024-09-03 06:05:19

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

PLATFORM := $(shell uname)

all:$(PLATFORM)

Darwin:
    echo Darwin

Linux:
    echo Linux

This is pretty simple, but you should be able to adapt it to more complicated things by changing the shell command that you run.

PLATFORM := $(shell uname)

all:$(PLATFORM)

Darwin:
    echo Darwin

Linux:
    echo Linux
狼亦尘 2024-09-03 06:05:19

您在那里有一些好的建议(探索平台,使用变量),但您还应该意识到您已经非常接近这样的点,最好停止考虑支持平台,而是考虑描述功能您需要您的软件并使用autoconf(和系列)来发现实际存在的内容。

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

You have some good advice there (probe the platform, use variables) but you should also be aware that you're running very close to the point where it is better to stop thinking in terms of supporting platforms and instead in terms of describing features that you require for your software and using autoconf (and family) to discover what is actually present.

Mind you, if it is a GUI app then you'll probably have so many differences between the OSX code and the Linux/X11 code that detecting by platform is reasonable. It's just rare that you need to do that for anything that's command-line oriented, as OSX looks a lot like plain old Unix then.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文