parallel-processing - 如何强制某组目标始终按顺序运行?

标签 parallel-processing makefile gnu-make ghc

有没有办法让 gmake 从不并行运行一组目标中的两个目标?

我不想使用 .NOTPARALLEL,因为它强制整个 Makefile 按顺序运行,而不仅仅是所需的部分。

我还可以添加依赖项,以便一个依赖于另一个,但是(除了丑陋之外)我需要构建所有依赖项才能构建最后一个,这不是必需的。

我需要这个的原因是我的 Makefile 的(只有一部分)调用了 ghc --make ,它自己处理它的依赖关系。并且不可能在两个不同的目标上并行运行它,因为如果两个目标共享一些依赖关系,它们可以重写彼此的.o文件。 (但 ghc 可以按顺序调用。)

更新:举一个具体的例子。假设我需要在 Makefile 中编译两个程序:

  • prog1取决于 prog1.hsmylib.hs ;
  • prog2取决于 prog2.hsmylib.hs .

  • 现在,如果我调用 ghc --make prog1.hs ,它检查它的依赖关系,编译prog1.hsmylib.hs进入它们各自的目标和接口(interface)文件,并链接prog1 .当我调用 ghc --make prog2.hs 时也会发生同样的情况.因此,如果两个命令并行运行,其中一个将覆盖 mylib.o另一个,导致它严重失败。

    但是,我不需要 prog1取决于 prog2反之亦然,因为它们应该可以单独编译。 (实际上它们非常大,有很多模块,并且需要编译它们都大大减慢了开发速度。)

    最佳答案

    嗯,可以提供更多信息,所以这只是在黑暗中刺伤。

    Make 并不真正支持这一点,但您可以通过几种方式对两个目标进行序列化。首先,递归make的真正用途:

    targ1: ; recipe1...
    targ2: ; recipe2...
    
    both-targets:
        ${MAKE} targ1
        ${MAKE} targ2
    

    所以在这里你可以make -j both-targets一切都很好。虽然很脆弱,因为 make -j targ1 targ2仍然并行运行。您可以改用依赖项:
    targ1: ; recipe1...
    targ2: | targ1 ; recipe2...
    

    现在make -j targ1 targ2做你想做的事。坏处? make targ2将始终尝试构建 targ1首先(依次)。这可能(或可能不会)对您来说是一个阻碍。

    编辑

    另一个不满意的策略是明确查看 $MAKECMDGOALS ,其中列出了您在命令行中指定的目标。仍然是一个脆弱的解决方案,因为当有人使用 Makefile 中的依赖项来构建东西时它会被破坏(不是不合理的行为)。

    假设您的 makefile 包含两个独立的目标 targ1targ2 .基本上它们保持独立,直到有人在命令行上指定它们都必须被构建。在这种特殊情况下,您打破了这种独立性。考虑这个片段:
    $(and $(filter targ1,${MAKECMDGOALS)),$(filter targ2,${MAKECMDGOALS}),$(eval targ1: | targ2))
    

    呃!这里发生了什么?
  • Make 评估 $(and)
  • 它首先必须扩展$(filter targ1,${MAKECMDGOALS})
  • targ1已指定,它继续扩展 $(filter targ2,${MAKECMDGOALS})
  • targ2也被指定,它继续扩展 $(eval) , 强制序列化 targ1targ2 .
  • 请注意 $(eval)扩展为空(它的所有工作都是作为副作用完成的),所以原来的 $(and)总是扩展到什么都没有,不会导致语法错误。

  • 啊!

    [现在我已经把它打出来了,更简单的 prog2: | $(filter prog1,${MAKECMDGOALS})发生在我身上。那好吧。]

    YMMV 等等。

    我对 ghc 不熟悉,但正确的解决方案是让 ghc 的两次运行使用不同的构建文件夹,然后它们可以愉快地并行运行。

    关于parallel-processing - 如何强制某组目标始终按顺序运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21832023/

    相关文章:

    c++ - MAKEFILE:在不修改文件的情况下将目标视为已更新

    makefile - 带有许多目标目录的 GNU make

    makefile - 定义自定义 GNU make 函数

    azure - 在 Azure 开发存储上,并行上传 block blob 时收到 "the specified blob already exists"

    Python计算集群

    c - valgrind 给出错误但无法找到位置

    makefile - 将 Makefile 转换为 Bazel?

    Makefile为 "activate"Python虚拟环境

    c# - 如何使用 System.Threading.Parallel (.Net 4.0) 增加并发并行任务

    parallel-processing - Redis 随客户端数量扩展