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

如何编写一个makefile来自动检测和并行化GNU Make的构建?

  •  26
  • dlamotte  · 技术社区  · 16 年前

    不确定这是否在一个Makefile中就可以实现,但我希望编写一个Makefile时,尝试在文件中构建任何目标都会自动神奇地检测当前系统上的处理器数量,并针对处理器数量并行构建目标。

    类似于下面的“伪代码”示例,但更简洁?

    all:
        @make -j$(NUM_PROCESSORS) all
    

    或:

    all: .inparallel
        ... build all here ...
    
    .inparallel:
        @make -j$(NUM_PROCESSORS) $(ORIGINAL_TARGET)
    

    在这两种情况下,您只需键入:

    % make all
    

    希望这是有道理的。

    更新:仍然希望上面的Makefile示例。对查找进程的数量不感兴趣,但对如何编写makefile以在没有-j命令行选项的情况下并行构建感兴趣。

    7 回复  |  直到 16 年前
        1
  •  23
  •   r0estir0bbe    10 年前

    检测部分将依赖于操作系统。以下是一个将在Linux和Mac OS X上运行的片段:

    NPROCS:=1
    OS:=$(shell uname -s)
    
    ifeq($(OS),Linux)
      NPROCS:=$(shell grep -c ^processor /proc/cpuinfo)
    endif
    ifeq($(OS),Darwin) # Assume Mac OS X
      NPROCS:=$(shell system_profiler | awk '/Number Of CPUs/{print $4}{next;}')
    endif
    

    -j 价值),但它可能是精巧的。

        2
  •  7
  •   TedKotz    12 年前

    我刚把这个添加到我的Makefile的顶部。它允许make创建任意数量的作业,但试图将负载平均值保持在cpu核心数以下。

    MAKEFLAGS+="-j -l $(shell grep -c ^processor /proc/cpuinfo) "
    

    注意这是Linux特有的。

        3
  •  6
  •   dlamotte    16 年前

    在浏览了一下LDD3第2章并阅读了dmckee的答案之后,我想到了使用两个makefile(我宁愿只使用一个)这个不太好的答案。

    $ cat Makefile
    MAKEFLAGS += -rR --no-print-directory
    
    NPROCS := 1
    OS := $(shell uname)
    export NPROCS
    
    ifeq ($J,)
    
    ifeq ($(OS),Linux)
      NPROCS := $(shell grep -c ^processor /proc/cpuinfo)
    else ifeq ($(OS),Darwin)
      NPROCS := $(shell system_profiler | awk '/Number of CPUs/ {print $$4}{next;}')
    endif # $(OS)
    
    else
      NPROCS := $J
    endif # $J
    
    all:
        @echo "running $(NPROCS) jobs..."
        @$(MAKE) -j$(NPROCS) -f Makefile.goals $@
    
    %:
        @echo "building in $(NPROCS) jobs..."
        @$(MAKE) -j$(NPROCS) -f Makefile.goals $@
    $ cat Makefile.goals
    MAKEFLAGS += -rR --no-print-directory
    NPROCS ?= 1
    
    all: subgoal
        @echo "$(MAKELEVEL) nprocs = $(NPROCS)"
    
    subgoal:
        @echo "$(MAKELEVEL) subgoal"
    

    你觉得这个解决方案怎么样?

    make 建造。所以没有什么“驱动程序”脚本 NPROCS make -j$(NPROCS) 人们必须知道的工作而不是打字。

    make -f Makefile.goals 为了做一个系列的构建。我不知道怎么解决这个问题。。。

    更新:在上述代码段中添加了$J。看来工作做得很好。即使它有两个makefile而不是一个,它仍然非常无缝和有用。

        4
  •  6
  •   amos    14 年前

    以下是我的观点:

    ifeq ($(OS),Linux)
            NUMPROC := $(shell grep -c ^processor /proc/cpuinfo)
    else ifeq ($(OS),Darwin)
            NUMPROC := $(shell sysctl hw.ncpu | awk '{print $$2}')
    endif
    
    # Only take half as many processors as available
    NUMPROC := $(shell echo "$(NUMPROC)/2"|bc)
    
    ifeq ($(NUMPROC),0)
            NUMPROC = 1
    endif 
    
        5
  •  5
  •   Jack Kelly    15 年前

    $(NPROCS) 检测的东西,但这里有一个方法,你可以在一个单一的 Makefile

    ifeq ($(NPROCS),)
    # Code to set NPROCS...
    %:
        $(MAKE) -j$(NPROCS) NPROCS=$(NPROCS)
    else
    # All of your targets...
    endif
    

    看到了吗 Defining Last-Resort Default Rules Overriding Part of Another Makefile GNU Make Manual .

        6
  •  2
  •   grundprinzip    15 年前

    如果我正确地阅读了这个问题,那么目标就是尽可能地并行化构建过程。这个 make 手册页说明如下

    如果-j选项没有参数,make将不会限制可以同时运行的作业数。

    这基本上不是你想要的解决方案吗?如果Makefile有足够的并行目标,那么您将使用所有cpu,如果目标不并行,那么 -j

        7
  •  2
  •   mbinette    13 年前

    如果希望它是自动的,那么可以重写典型的make命令,使其成为 .bashrc 在您的主目录中。

    alias make="make -j"
    

    或者你可以这样做:

    alias jmake="make -j"
    

    在这种情况下,您不想覆盖它,但需要一个快速和简单(和难忘的)方式来并行运行make。