代码之家  ›  专栏  ›  技术社区  ›  MateuszL

并发编译,串行链接

  •  0
  • MateuszL  · 技术社区  · 5 年前

    make -j20 . 但最糟糕的是联系。单次链接大约需要60秒和4GB内存。但是,当所有最终的二进制文件同时链接时(通常发生在修改了1个小的子库、很少重新编译、很多重新链接时),10个链接器使用40GB RAM(对于1个开发人员,可能会有更多的RAM)并且时间很长。IO很可能是瓶颈。

    我们在一个强大的服务器上有许多开发人员,每个人都使用 make -j20 -l30 这样我们就不会让CPU过载。但是我们没有限制并发链接器数量的方法。限制服务器上全局工作的链接器的数量是很好的,但是每次调用也会有帮助。理想的 make -j20 -l30 --concurrent-linkers=2

    我们使用黄金链接器。我们正在分离更小的独立模块,但这需要很长时间。

    0 回复  |  直到 5 年前
        1
  •  1
  •   Renaud Pacalet    5 年前

    你可以试试这样的方法:

    $ cat Makefile
    OBJS := foo bar baz...
    EXES := qux quux quuz...
    
    .PHONY: all
    
    all: $(OBJS)
        $(MAKE) -j $(concurrent-linkers) $(EXES)
    
    $(OBJS): ...
        <compile>
    
    $(EXES): ...
        <link>
    

    并称之为:

    $ make -j20 -l30 concurrent-linkers=2
    

    基本上,它将构建分为两个make调用,一个用于编译,一个用于链接,使用不同的 -j flock 标记文件将使其成为)并将其委托给链接作业。但如果你能忍受这个。。。

    $ cat Makefile
    OBJS := a b c d e f
    EXES := u v w x y z
    
    .PHONY: all
    
    all: $(OBJS)
        $(MAKE) -j $(concurrent-linkers) $(EXES)
    
    $(OBJS) $(EXES):
        @printf 'building $@...\n' && sleep 2 && printf 'done\n' && touch $@
    $ make -j20 -l30 concurrent-linkers=2
    building a...
    building d...
    building b...
    building c...
    building e...
    building f...
    done
    done
    done
    done
    done
    done
    make -j 2 u v w x y z
    make[1]: warning: -jN forced in submake: disabling jobserver mode.
    make[1]: Entering directory 'foobar'
    building u...
    building v...
    done
    done
    building w...
    building x...
    done
    done
    building y...
    building z...
    done
    done
    make[1]: Leaving directory 'foobar'
    

    如你所见 $(OBJS) 目标是并行构建的,而 $(EXES) 目标一次最多建立2个。

    编辑 如果makefile是由CMake生成的,则至少有两个选项:

    1. 调整CMake文件,以便CMake生成两个不同的makefile:一个用于编译,一个用于链接。然后编写一个简单的包装makefile,如下所示:

      .PHONY: myAll myCompile
      
      myAll: myCompile
          $(MAKE) -j $(concurrent-linkers) -f Makefile.link
      
      myCompile:
          $(MAKE) -f Makefile.compilation
      
    2. 说服CMake(如果还没有)生成定义两个make变量的makefile:一个( OBJS )设置为所有对象文件和一个( EXES )设置为所有可执行文件的列表。然后编写一个简单的包装makefile,如下所示:

      .DEFAULT_GOAL := myAll
      
      include CMake.generated.Makefile
      
      .PHONY: myAll
      
      myAll: $(OBJS)
          $(MAKE) -j $(concurrent-linkers) $(EXES)
      

      如果CMake生成两个虚假目标,一个用于所有对象文件,另一个用于所有可执行文件,则存在非常相似的解决方案:

      .DEFAULT_GOAL := myAll
      
      include CMake.generated.Makefile
      
      .PHONY: myAll
      
      myAll: cmake-target-for-compilation
          $(MAKE) -j $(concurrent-linkers) cmake-target-for-link