【问题标题】:How to run Linux shell commands from GNU make file to setup preconditions for a build target如何从 GNU make 文件运行 Linux shell 命令来设置构建目标的先决条件
【发布时间】:2014-05-19 05:55:35
【问题描述】:

我的问题是,在我的 make 文件中,我想在构建之前为所有目标代码创建目录,但我找不到这样做的方法,而不会影响 make 的输出。另外,我想在一个地方而不是针对每个目标文件进行。

我试过这个:

build: setup exe.i686

setup:
    mkdir -p obj

exe.i686: $(OBJS)
    @echo 'Building target: $@'
    @echo 'Invoking: GCC C++ Linker'
    ${GCC_LOCATION}/Linux/i686/bin/i686-pc-linux-gnu-g++ $(OBJS) -o "exe.i686" -L...
    @echo 'Finished building target: $@'
    @echo ' '

OBJS 是我所有的目标代码。如果我不先运行安装程序并且不存在 ./obj 目录,则构建将失败,因为在尝试构建目标代码时缺少目录。

为了清楚起见,这里是一个如何构建一个目标文件的示例:

./obj/Cell.o: ${CELL_ROOT}/main/cell/Cell/src/Cell.cc
    @echo 'Building file: $<'
    @echo 'Invoking: GCC C++ Compiler'
    $(GCC_C++_BUILD) -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
    @echo 'Finished building: $<'
    @echo ' '

我不想在与我的 make 文件相同的目录中构建目标代码。

现在到实际问题。当我第一次像这样构建目标“构建”时,一切正常:

make build

但是如果我再次构建它并且我的源代码中没有更新(目标代码是最新的)它的行为如下:

[7:37] [user1] [/local/repo/user1/project_x/test/bin] $ make build
mkdir -p obj
[7:37] [user1] [/local/repo/user1/project_x/test/bin] $ 

在这种情况下,我希望 make 像这样返回 nothing-to-be-done 字符串:

[7:37] [user1] [/local/repo/user1/project_x/test/bin] $ make build
make: Nothing to be done for `build'.
[7:41] [user1] [/local/repo/user1/project_x/test/bin] $ 

如果我不必依赖设置目标(添加到 .PHONY),就会出现这种情况。是为每个目标代码文件执行此操作的唯一选择吗?我想这是可能的,但我想尽可能避免这种情况,因为它会使 make 文件变得很混乱。至少在我看来。

谢谢

【问题讨论】:

  • 只是提一下,自从我发现 scons 后——我快乐多了。我记得我与那些制作文件作斗争。我发现使用 scons 更容易。

标签: linux makefile gnu-make


【解决方案1】:

你的目标 setup 总是被执行,因为它没有依赖关系。

你有两个选择:

(1) 创建一个stamp 或使用其他机制,以便有一个实际的依赖关系。目录本身可以是目标,但这可能会导致一些问题:例如,请参阅 http://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html

已修改链接文章的相关摘录:

$(OBJS): | obj

obj:
    mkdir $(OBJDIR)

(2) 通过测试是否存在来抑制输出:

setup:
    test -d obj || mkdir -p obj

【讨论】:

  • 实际上回想起来,上面的#2 可能不会抑制你想要隐藏的消息,只有配方执行,但我把它留在那里以防它对其他人有用。
  • 仅订购的先决条件似乎正是我所缺少的。谢谢!
  • 我认为原因不是因为“它没有依赖关系”。这是因为每次创建 obj 文件时,都会使用新的时间戳更新 obj/。在这种情况下,obj/ 总是比最后一个 obj 文件更新,从而形成循环依赖。鉴于此,该解决方案运行良好。
【解决方案2】:

这与之前的答案类似,只是为了更容易阅读:

build: exe.i686
$(OBJS): | obj
obj:
    @if [ ! -d obj ]; then mkdir -p obj; fi

exe.i686: $(OBJS)
    @echo 'Building target: $@'
    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多