与生成文件目录树创建适合并行(-j)构建 [英] makefile with directory tree creation suitable for parallel (-j ) build

查看:115
本文介绍了与生成文件目录树创建适合并行(-j)构建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目中使用的mkdir -p同样这需要它们在构建过程中创建的临时目录:

My project needs temporary directories which are created during the build using mkdir -p similarly to this:

all: dirtree $(OBJFILES)

dirtree: 
  @mkdir -p $(BUILD)/temp_directory

但是,这种方法不能与-j开关被使用,因为第一OBJFILES的由所述的mkdir目标之前被编译。

But this approach cannot be used with the -j switch, because first of the OBJFILES get compiled before the mkdir target is made.

有没有做到这一点的标准方式?

Is there a standard way to do this?

推荐答案

你的Makefile的问题是,你创建的目标文件不依赖于建立相关的目录(只有一个假冒的全能的目标所做的那样)。这种依赖是必要的 -j 选项,甚至没有它你的makefile只是偶然的作品。有两个(右)的方式来强加有问题的依赖性。

The problem with your makefile is that creation of your object files does not depend on creation of the relevant directories (only a phony "all" target does). This kind of dependency is necessary for -j option, and even without it your makefile works only by chance. There are two (right) ways to impose the dependency in question.

目录作为单独的目标

您创建了目录的创建目标;什么剩下的就是只是把它作为一个prerequisite对象文件规则:

You created the target for directory creation; what left is just put it as a prerequisite to object file rule:

$(BUILD)/temp_directory/%.o: %.c   |   dirtree
        $(CC) $^ -o $@

管道符号 | 表示dirtree是的命令仅prerequisite。它是用来当dirtree是prerequisite但dirtree不坏的目标文件的变化,并不影响编译命令的结果。

The pipe symbol | means that dirtree is an "order only prerequisite". It is used when "dirtree" is a prerequisite but changes in the dirtree do not invalidate object files and do not affect the outcome of compilation command.

订单只有prerequisite的使用是重要的在这里。问题是, dirtree 目标将在每次调用做重拍进行。这将导致依赖于它重拍以及一切,所以它会重建的所有的目标文件每次。

Use of "order-only" prerequisite is important here. The thing is that dirtree target would be remade at each Make invocation. That would cause everything that depends on it be remade as well, so it would rebuild all object files every time.

创建shell命令目录

另一种方法是,以确保目录中创建调用编译之前立即

Another way is to ensure that the directory is created immediately before you invoke compilation

$(BUILD)/temp_directory/%.o: %.c
        @mkdir -p $(@D)
        $(CC) $^ -o $@

请注意 $的使用(@ D)。此被扩展为目录目标文件。所以它可均匀地使用在许多地方,甚至具有可变的助剂。

Note the usage of $(@D). This is expanded as "the directory for the target file". So it may be used uniformly in many places, and even with aid of a variable.

Mkdir=@mkdir -p $(@D)
$(BUILD)/temp_directory/%.o: %.c
        $(Mkdir)
        $(CC) $^ -o $@
$(INSTALL_DIR)/%: src_dir/%
        $(Mkdir)
        cp -p $^ $@


这两种方式确保被调用编译命令之前的目录中创建。这两种方法要求你写一些文本( | dirtree $(MKDIR)),在需要它的每个规则。这两种方式都是 -j 兼容,但第二个解决方案需要的mkdir -p 是线程安全的(这样两个命令马上可以尝试创建同一目录下,其中一人会失败)。


Both ways ensure that the directory is created before the compilation commands are invoked. Both ways require you to write some text (either | dirtree or $(Mkdir)) at each rule that needs it. Both ways are -j compatible, but the second solution requires mkdir -p to be thread-safe (as two such commands at once may try to create the same directory, and one of them would fail).

虽然大多数系统中实现它的方式的mkdir -p 或多或少是线程安全的,在某些系统上(的在某些Solaris系统,例如),它们是线程安全的比别人少。然而,即使在GNU工具链的mkdir -p 可如果他们同时调用相同的的mkdir(2)库调用失败。

While most systems implement it in such a way that mkdir -p is more or less thread safe, on some systems (as in some Solaris systems, for example), they are less thread-safe than the others. However, even in GNU toolchain mkdir -p may fail if they simultaneously invoke the same mkdir(2) library call.

如果你想成为的非常的安全,你可以工作这周围也。可能是什么问题?这两个的mkdir -p 脚本尝试创建相同的目录,以及地方交锋C库里面。然后,其中一个的mkdir -s会成功,而其他将会失败。但是,如果的mkdir 您进行调用失败了,那么它可能是线程不安全相关仅当该目录是由一个并发的mkdir <创建失败/ code>。因此,这将是不够的,只是检查目标目录后的mkdir 创建调用:

If you want to be very safe, you can work this around as well. What could be the problem? That two mkdir -p scripts try to create the same directory, and clash somewhere inside C library. Then, one of these mkdir-s will succeed, and the other will fail. However, if the mkdir you invoked failed, then it could be thread-unsafety-related failure only if the directory had been created by a concurrent mkdir. So it would be enough to just check that the target directory is created after mkdir invocation:

Mkdir=@mkdir -p $(@D) || test -d $(@D)

(该解决方案还具有模式的一个问题:当目录中的mkdir可能会失败,但不符合的umask,所以你可能要检查以及但是这太多我猜)

(This solution also has an issue with mode: mkdir may fail when directory exists, but doesn't conform to umask, so you might want to check that as well. But that's too much I guess.)

这篇关于与生成文件目录树创建适合并行(-j)构建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆