34

如何运行必须在所有其他 makefile 命令之前执行的脚本?如果没有要构建的内容,那么不执行脚本会很好(但不是强制性的)。

我搜索了 SO 和 Google,但找不到任何东西。

我有这个解决方法:

# myscript.bat output is empty
CHEAT_ARGUMENT = (shell myscript.bat)
CFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT)
AFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT)

但它非常难看。还有其他方法可以在makefile中运行“预构建步骤”吗?

4

5 回答 5

36

我提出两个解决方案。第一个模仿 NetBeans IDE 生成的内容:

CC=gcc

.PHONY: all clean

all: post-build

pre-build:
    @echo PRE

post-build: main-build
    @echo POST

main-build: pre-build
    @$(MAKE) --no-print-directory target

target: $(OBJS)
    $(CC) -o $@ $(OBJS)

clean:
    rm -f $(OBJS) target

第二个灵感来自 Eclipse IDE 生成的内容:

CC=gcc

.PHONY: all clean
.SECONDARY: main-build

all: pre-build main-build

pre-build:
    @echo PRE

post-build:
    @echo POST

main-build: target

target: $(OBJS)
    $(CC) -o $@ $(OBJS)
    @$(MAKE) --no-print-directory post-build

clean:
    rm -f $(OBJS) target

请注意,在第一个版本中,无论主构建是否确定为最新,始终都会调用前构建和后构建。

在第二个中,如果主构建的状态是最新的,则不执行构建后步骤。虽然预构建步骤始终在两者中执行。

于 2009-10-25T21:45:41.137 回答
13

根据您的make版本,如果对 CFLAGS 和 AFLAGS 进行了数十次评估,则以下内容至少应避免运行数十次:

CHEAT_ARG := $(shell myscript)

注意冒号。

这只运行一次。永远不会超过一次,但也永远不会少于一次。选择你自己的权衡。

于 2009-10-23T09:19:49.173 回答
5

您可以将一个特殊目标添加到您的 Makefile 并让您的所有构建规则都依赖于它:

run-script:
    myscript

.o.c: run-script
     $(CC) $(CFLAGS) -o $@ $<

.o.S: run-script
     $(AS) $(AFLAGS) -o $@ $<

根据您的脚本实际执行的操作,将其在 Makefile 之前的某个阶段运行一次(用 autoconf 术语配置阶段)可能更有意义(并且工作量更少)。

于 2009-10-23T09:41:29.623 回答
3

你所提议的似乎有点“不像”。为什么不直接在任何你需要它的 makefile 目标中运行命令呢?

例如,如果您需要在链接之前运行它foo

foo: ${OBJS}
    my-command-goes-here
    ${CC} -o $@ ${OBJS} ${LIBS}
于 2009-10-23T09:24:56.277 回答
1

谢谢你的回答。ndim帮了我很多,asveikau。最终文件是一个二进制可执行文件,所以我现在可以使用如下内容:

run-script:
    myscript
$(AXF_FILE): run-script $(OBJ_DIRS) $(OBJ_FILES)
    $(LINK) #......

它将运行 myscript 一次。{AXF_FILE} 值取决于 myscript,我必须先运行。在这种情况下,myscript 始终运行,不仅在需要重建时运行。之后,我想到了最简单的答案:

all: run-script $(AXF_FILE)

就是这样(当然,可以使用任何目标来代替“全部”)


编辑:此方法在$(AXF_FILE)也被计算后执行脚本。所以可能会得到错误的 AXF_FILE 值。现在只有ndim的第一个答案可以满足我的需要。

于 2009-10-25T19:30:22.683 回答